@@ -13,6 +13,11 @@ export enum WASQLiteVFS {
1313 AccessHandlePoolVFS = 'AccessHandlePoolVFS'
1414}
1515
16+ export type WASQLiteBroadCastTableUpdateEvent = {
17+ changedTables : Set < string > ;
18+ connectionId : number ;
19+ } ;
20+
1621/**
1722 * @internal
1823 */
@@ -106,11 +111,19 @@ export class WASqliteConnection extends BaseObserver<WASQLiteConnectionListener>
106111 protected updatedTables : Set < string > ;
107112 protected updateTimer : ReturnType < typeof setTimeout > | null ;
108113 protected statementMutex : Mutex ;
114+ protected broadcastChannel : BroadcastChannel | null ;
115+ /**
116+ * Unique id for this specific connection. This is used to prevent broadcast table change
117+ * notification loops.
118+ */
119+ protected connectionId : number ;
109120
110121 constructor ( protected options : WASQLiteOpenOptions ) {
111122 super ( ) ;
112123 this . updatedTables = new Set ( ) ;
113124 this . updateTimer = null ;
125+ this . broadcastChannel = null ;
126+ this . connectionId = new Date ( ) . valueOf ( ) + Math . random ( ) * 1000 ;
114127 this . statementMutex = new Mutex ( ) ;
115128 this . _moduleFactory = DEFAULT_MODULE_FACTORIES [ this . options . vfs ?? WASQLiteVFS . IDBBatchAtomicVFS ] ;
116129 }
@@ -146,24 +159,47 @@ export class WASqliteConnection extends BaseObserver<WASQLiteConnectionListener>
146159 return sqlite3 ;
147160 }
148161
162+ protected registerBroadcastListeners ( ) {
163+ this . broadcastChannel = new BroadcastChannel ( `${ this . options . dbFilename } -table-updates` ) ;
164+ this . broadcastChannel . addEventListener ( 'message' , ( event ) => {
165+ const data : WASQLiteBroadCastTableUpdateEvent = event . data ;
166+ if ( this . connectionId == data . connectionId ) {
167+ // Ignore messages from the same connection
168+ return ;
169+ }
170+ this . queueTableUpdate ( data . changedTables ) ;
171+ } ) ;
172+ }
173+
174+ protected queueTableUpdate ( tableNames : Set < string > ) {
175+ tableNames . forEach ( ( tableName ) => this . updatedTables . add ( tableName ) ) ;
176+ if ( this . updateTimer == null ) {
177+ this . updateTimer = setTimeout ( ( ) => this . fireUpdates ( ) , 0 ) ;
178+ }
179+ }
180+
149181 async init ( ) {
150182 this . _sqliteAPI = await this . openSQLiteAPI ( ) ;
151183 await this . openDB ( ) ;
184+ this . registerBroadcastListeners ( ) ;
152185
153186 this . sqliteAPI . update_hook ( this . dbP , ( updateType : number , dbName : string | null , tableName : string | null ) => {
154187 if ( ! tableName ) {
155188 return ;
156189 }
157- this . updatedTables . add ( tableName ) ;
158- if ( this . updateTimer == null ) {
159- this . updateTimer = setTimeout ( ( ) => this . fireUpdates ( ) , 0 ) ;
160- }
190+ const changedTables = new Set ( [ tableName ] ) ;
191+ this . queueTableUpdate ( changedTables ) ;
161192 } ) ;
162193 }
163194
164195 fireUpdates ( ) {
165196 this . updateTimer = null ;
166197 const event : BatchedUpdateNotification = { tables : [ ...this . updatedTables ] , groupedUpdates : { } , rawUpdates : [ ] } ;
198+ // Share to other connections
199+ this . broadcastChannel ! . postMessage ( {
200+ changedTables : this . updatedTables ,
201+ connectionId : this . connectionId
202+ } satisfies WASQLiteBroadCastTableUpdateEvent ) ;
167203 this . updatedTables . clear ( ) ;
168204 this . iterateListeners ( ( cb ) => cb . tablesUpdated ?.( event ) ) ;
169205 }
@@ -238,6 +274,7 @@ export class WASqliteConnection extends BaseObserver<WASQLiteConnectionListener>
238274 }
239275
240276 async close ( ) {
277+ this . broadcastChannel ?. close ( ) ;
241278 await this . sqliteAPI . close ( this . dbP ) ;
242279 }
243280
0 commit comments