@@ -17,7 +17,7 @@ import { createActorRouter } from "../../src/actor/router";
1717import { routeWebSocket } from "../../src/actor/router-websocket-endpoints" ;
1818import { HEADER_CONN_PARAMS } from "../../src/common/actor-router-consts" ;
1919import { InlineWebSocketAdapter } from "../../src/common/inline-websocket-adapter" ;
20- import type { ISqliteVfs } from "@rivetkit/sqlite-wasm " ;
20+ import type { NativeDatabaseProvider , SqliteDatabase } from "../../src/db/config " ;
2121import {
2222 DYNAMIC_BOOTSTRAP_CONFIG_GLOBAL_KEY ,
2323 DYNAMIC_HOST_BRIDGE_GLOBAL_KEYS ,
@@ -34,8 +34,6 @@ import {
3434} from "../../src/dynamic/runtime-bridge" ;
3535import { RegistryConfigSchema } from "../../src/registry/config" ;
3636
37- const { SqliteVfsPool } = require ( "@rivetkit/sqlite-wasm" ) as typeof import ( "@rivetkit/sqlite-wasm" ) ;
38-
3937interface IsolateReferenceLike {
4038 applySyncPromise (
4139 receiver : unknown ,
@@ -60,6 +58,10 @@ interface DynamicHostBridge {
6058 kvDeleteRange : IsolateReferenceLike ;
6159 kvListPrefix : IsolateReferenceLike ;
6260 kvListRange : IsolateReferenceLike ;
61+ dbExec : IsolateReferenceLike ;
62+ dbQuery : IsolateReferenceLike ;
63+ dbRun : IsolateReferenceLike ;
64+ dbClose : IsolateReferenceLike ;
6365 setAlarm : IsolateReferenceLike ;
6466 clientCall : IsolateReferenceLike ;
6567 ackHibernatableWebSocketMessage : IsolateReferenceLike ;
@@ -108,7 +110,7 @@ interface DynamicActorDriver {
108110 } ,
109111 ) : Promise < Array < [ Uint8Array , Uint8Array ] > > ;
110112 setAlarm ( actor : { id : string } , timestamp : number ) : Promise < void > ;
111- createSqliteVfs ( actorId : string ) : Promise < ISqliteVfs > ;
113+ getNativeDatabaseProvider ( ) : NativeDatabaseProvider ;
112114 startSleep ( actorId : string ) : void ;
113115 ackHibernatableWebSocketMessage (
114116 gatewayId : ArrayBuffer ,
@@ -282,12 +284,7 @@ const webSocketSessions = new Map<
282284 }
283285> ( ) ;
284286const CLIENT_ACCESSOR_METHODS = new Set ( [ "get" , "getOrCreate" , "getForId" , "create" ] ) ;
285- let sqliteVfsPoolPromise :
286- | Promise < {
287- acquire ( actorId : string ) : Promise < ISqliteVfs > ;
288- shutdown ( ) : Promise < void > ;
289- } >
290- | undefined ;
287+ const nativeDatabaseCache = new Map < string , SqliteDatabase > ( ) ;
291288
292289type DynamicActorRouter = ReturnType < typeof createActorRouter > ;
293290
@@ -371,6 +368,10 @@ function readHostBridge(): DynamicHostBridge {
371368 kvListRange : getRequiredHostRef (
372369 DYNAMIC_HOST_BRIDGE_GLOBAL_KEYS . kvListRange ,
373370 ) ,
371+ dbExec : getRequiredHostRef ( DYNAMIC_HOST_BRIDGE_GLOBAL_KEYS . dbExec ) ,
372+ dbQuery : getRequiredHostRef ( DYNAMIC_HOST_BRIDGE_GLOBAL_KEYS . dbQuery ) ,
373+ dbRun : getRequiredHostRef ( DYNAMIC_HOST_BRIDGE_GLOBAL_KEYS . dbRun ) ,
374+ dbClose : getRequiredHostRef ( DYNAMIC_HOST_BRIDGE_GLOBAL_KEYS . dbClose ) ,
374375 setAlarm : getRequiredHostRef ( DYNAMIC_HOST_BRIDGE_GLOBAL_KEYS . setAlarm ) ,
375376 clientCall : getRequiredHostRef ( DYNAMIC_HOST_BRIDGE_GLOBAL_KEYS . clientCall ) ,
376377 ackHibernatableWebSocketMessage : getRequiredHostRef (
@@ -452,23 +453,6 @@ async function getRuntimeState(): Promise<DynamicRuntimeState> {
452453 return await runtimeStatePromise ;
453454}
454455
455- async function loadSqliteVfsPool ( ) : Promise < {
456- acquire ( actorId : string ) : Promise < ISqliteVfs > ;
457- shutdown ( ) : Promise < void > ;
458- } > {
459- if ( ! sqliteVfsPoolPromise ) {
460- sqliteVfsPoolPromise = Promise . resolve ( ) . then (
461- ( ) =>
462- new SqliteVfsPool ( {
463- actorsPerInstance : 50 ,
464- idleDestroyMs : 30_000 ,
465- } ) ,
466- ) ;
467- }
468-
469- return await sqliteVfsPoolPromise ;
470- }
471-
472456function dynamicHostLog ( level : "debug" | "warn" , message : string ) : void {
473457 if ( ! hostBridge . log ) {
474458 return ;
@@ -512,6 +496,45 @@ function bridgeCallSync<T>(ref: IsolateReferenceLike, args: unknown[]): T {
512496 } ) as T ;
513497}
514498
499+ function createNativeDatabaseBridge ( actorIdValue : string ) : SqliteDatabase {
500+ return {
501+ async exec (
502+ sql : string ,
503+ callback ?: ( row : unknown [ ] , columns : string [ ] ) => void ,
504+ ) : Promise < void > {
505+ const result = await bridgeCall < {
506+ columns : string [ ] ;
507+ rows : unknown [ ] [ ] ;
508+ } > ( hostBridge . dbExec , [ actorIdValue , sql ] ) ;
509+ if ( ! callback ) {
510+ return ;
511+ }
512+ for ( const row of result . rows ) {
513+ callback ( row , result . columns ) ;
514+ }
515+ } ,
516+ async run (
517+ sql : string ,
518+ params ?: unknown [ ] | Record < string , unknown > ,
519+ ) : Promise < void > {
520+ await bridgeCall ( hostBridge . dbRun , [ actorIdValue , sql , params ] ) ;
521+ } ,
522+ async query (
523+ sql : string ,
524+ params ?: unknown [ ] | Record < string , unknown > ,
525+ ) : Promise < { rows : unknown [ ] [ ] ; columns : string [ ] } > {
526+ return await bridgeCall ( hostBridge . dbQuery , [ actorIdValue , sql , params ] ) ;
527+ } ,
528+ async close ( ) : Promise < void > {
529+ try {
530+ await bridgeCall ( hostBridge . dbClose , [ actorIdValue ] ) ;
531+ } finally {
532+ nativeDatabaseCache . delete ( actorIdValue ) ;
533+ }
534+ } ,
535+ } ;
536+ }
537+
515538function toArrayBuffer ( input : Uint8Array | ArrayBuffer ) : ArrayBuffer {
516539 if ( input instanceof ArrayBuffer ) {
517540 return input ;
@@ -851,9 +874,18 @@ const actorDriver: DynamicActorDriver = {
851874 async setAlarm ( actor , timestamp : number ) : Promise < void > {
852875 await bridgeCall ( hostBridge . setAlarm , [ actor . id , timestamp ] ) ;
853876 } ,
854- async createSqliteVfs ( actorIdValue : string ) : Promise < ISqliteVfs > {
855- const pool = await loadSqliteVfsPool ( ) ;
856- return await pool . acquire ( actorIdValue ) ;
877+ getNativeDatabaseProvider ( ) : NativeDatabaseProvider {
878+ return {
879+ open : async ( actorIdValue : string ) : Promise < SqliteDatabase > => {
880+ const existing = nativeDatabaseCache . get ( actorIdValue ) ;
881+ if ( existing ) {
882+ return existing ;
883+ }
884+ const database = createNativeDatabaseBridge ( actorIdValue ) ;
885+ nativeDatabaseCache . set ( actorIdValue , database ) ;
886+ return database ;
887+ } ,
888+ } ;
857889 } ,
858890 startSleep ( requestActorId : string ) : void {
859891 bridgeCallSync ( hostBridge . startSleep , [ requestActorId ] ) ;
@@ -1306,10 +1338,13 @@ async function dynamicDisposeEnvelope(): Promise<boolean> {
13061338 }
13071339 webSocketSessions . clear ( ) ;
13081340 runtimeStopMode = undefined ;
1309- if ( sqliteVfsPoolPromise ) {
1310- const sqliteVfsPool = await sqliteVfsPoolPromise ;
1311- await sqliteVfsPool . shutdown ( ) ;
1312- sqliteVfsPoolPromise = undefined ;
1341+ for ( const [ actorId , database ] of nativeDatabaseCache . entries ( ) ) {
1342+ try {
1343+ await database . close ( ) ;
1344+ } catch {
1345+ // noop
1346+ }
1347+ nativeDatabaseCache . delete ( actorId ) ;
13131348 }
13141349 return true ;
13151350}
0 commit comments