@@ -145,7 +145,96 @@ export interface SyncEngineListener {
145
145
* The SyncEngine’s methods should only ever be called by methods running in the
146
146
* global async queue.
147
147
*/
148
- export class SyncEngine implements RemoteSyncer {
148
+ export interface SyncEngine extends RemoteSyncer {
149
+ isPrimaryClient : boolean ;
150
+
151
+ /** Subscribes to SyncEngine notifications. Has to be called exactly once. */
152
+ subscribe ( syncEngineListener : SyncEngineListener ) : void ;
153
+
154
+ /**
155
+ * Initiates the new listen, resolves promise when listen enqueued to the
156
+ * server. All the subsequent view snapshots or errors are sent to the
157
+ * subscribed handlers. Returns the initial snapshot.
158
+ */
159
+ listen ( query : Query ) : Promise < ViewSnapshot > ;
160
+
161
+ /** Stops listening to the query. */
162
+ unlisten ( query : Query ) : Promise < void > ;
163
+
164
+ /**
165
+ * Initiates the write of local mutation batch which involves adding the
166
+ * writes to the mutation queue, notifying the remote store about new
167
+ * mutations and raising events for any changes this write caused.
168
+ *
169
+ * The promise returned by this call is resolved when the above steps
170
+ * have completed, *not* when the write was acked by the backend. The
171
+ * userCallback is resolved once the write was acked/rejected by the
172
+ * backend (or failed locally for any other reason).
173
+ */
174
+ write ( batch : Mutation [ ] , userCallback : Deferred < void > ) : Promise < void > ;
175
+
176
+ /**
177
+ * Takes an updateFunction in which a set of reads and writes can be performed
178
+ * atomically. In the updateFunction, the client can read and write values
179
+ * using the supplied transaction object. After the updateFunction, all
180
+ * changes will be committed. If a retryable error occurs (ex: some other
181
+ * client has changed any of the data referenced), then the updateFunction
182
+ * will be called again after a backoff. If the updateFunction still fails
183
+ * after all retries, then the transaction will be rejected.
184
+ *
185
+ * The transaction object passed to the updateFunction contains methods for
186
+ * accessing documents and collections. Unlike other datastore access, data
187
+ * accessed with the transaction will not reflect local changes that have not
188
+ * been committed. For this reason, it is required that all reads are
189
+ * performed before any writes. Transactions must be performed while online.
190
+ *
191
+ * The Deferred input is resolved when the transaction is fully committed.
192
+ */
193
+ runTransaction < T > (
194
+ asyncQueue : AsyncQueue ,
195
+ updateFunction : ( transaction : Transaction ) => Promise < T > ,
196
+ deferred : Deferred < T >
197
+ ) : void ;
198
+
199
+ /**
200
+ * Applies an OnlineState change to the sync engine and notifies any views of
201
+ * the change.
202
+ */
203
+ applyOnlineStateChange (
204
+ onlineState : OnlineState ,
205
+ source : OnlineStateSource
206
+ ) : void ;
207
+
208
+ /**
209
+ * Registers a user callback that resolves when all pending mutations at the moment of calling
210
+ * are acknowledged .
211
+ */
212
+ registerPendingWritesCallback ( callback : Deferred < void > ) : Promise < void > ;
213
+
214
+ // Visible for testing
215
+ activeLimboDocumentResolutions ( ) : SortedMap < DocumentKey , TargetId > ;
216
+
217
+ // Visible for testing
218
+ enqueuedLimboDocumentResolutions ( ) : DocumentKey [ ] ;
219
+
220
+ handleCredentialChange ( user : User ) : Promise < void > ;
221
+
222
+ enableNetwork ( ) : Promise < void > ;
223
+
224
+ disableNetwork ( ) : Promise < void > ;
225
+
226
+ getRemoteKeysForTarget ( targetId : TargetId ) : DocumentKeySet ;
227
+ }
228
+
229
+ /**
230
+ * An implementation of `SyncEngine` coordinating with other parts of SDK.
231
+ *
232
+ * Note: some field defined in this class might have public access level, but
233
+ * the class is not exported so they are only accessible from this module.
234
+ * This is useful to implement optional features (like bundles) in free
235
+ * functions, such that they are tree-shakeable.
236
+ */
237
+ class SyncEngineImpl implements SyncEngine {
149
238
protected syncEngineListener : SyncEngineListener | null = null ;
150
239
151
240
protected queryViewsByQuery = new ObjectMap < Query , QueryView > (
@@ -198,7 +287,6 @@ export class SyncEngine implements RemoteSyncer {
198
287
return true ;
199
288
}
200
289
201
- /** Subscribes to SyncEngine notifications. Has to be called exactly once. */
202
290
subscribe ( syncEngineListener : SyncEngineListener ) : void {
203
291
debugAssert (
204
292
syncEngineListener !== null ,
@@ -212,11 +300,6 @@ export class SyncEngine implements RemoteSyncer {
212
300
this . syncEngineListener = syncEngineListener ;
213
301
}
214
302
215
- /**
216
- * Initiates the new listen, resolves promise when listen enqueued to the
217
- * server. All the subsequent view snapshots or errors are sent to the
218
- * subscribed handlers. Returns the initial snapshot.
219
- */
220
303
async listen ( query : Query ) : Promise < ViewSnapshot > {
221
304
this . assertSubscribed ( 'listen()' ) ;
222
305
@@ -295,7 +378,6 @@ export class SyncEngine implements RemoteSyncer {
295
378
return viewChange . snapshot ! ;
296
379
}
297
380
298
- /** Stops listening to the query. */
299
381
async unlisten ( query : Query ) : Promise < void > {
300
382
this . assertSubscribed ( 'unlisten()' ) ;
301
383
@@ -342,16 +424,6 @@ export class SyncEngine implements RemoteSyncer {
342
424
}
343
425
}
344
426
345
- /**
346
- * Initiates the write of local mutation batch which involves adding the
347
- * writes to the mutation queue, notifying the remote store about new
348
- * mutations and raising events for any changes this write caused.
349
- *
350
- * The promise returned by this call is resolved when the above steps
351
- * have completed, *not* when the write was acked by the backend. The
352
- * userCallback is resolved once the write was acked/rejected by the
353
- * backend (or failed locally for any other reason).
354
- */
355
427
async write ( batch : Mutation [ ] , userCallback : Deferred < void > ) : Promise < void > {
356
428
this . assertSubscribed ( 'write()' ) ;
357
429
@@ -369,23 +441,6 @@ export class SyncEngine implements RemoteSyncer {
369
441
}
370
442
}
371
443
372
- /**
373
- * Takes an updateFunction in which a set of reads and writes can be performed
374
- * atomically. In the updateFunction, the client can read and write values
375
- * using the supplied transaction object. After the updateFunction, all
376
- * changes will be committed. If a retryable error occurs (ex: some other
377
- * client has changed any of the data referenced), then the updateFunction
378
- * will be called again after a backoff. If the updateFunction still fails
379
- * after all retries, then the transaction will be rejected.
380
- *
381
- * The transaction object passed to the updateFunction contains methods for
382
- * accessing documents and collections. Unlike other datastore access, data
383
- * accessed with the transaction will not reflect local changes that have not
384
- * been committed. For this reason, it is required that all reads are
385
- * performed before any writes. Transactions must be performed while online.
386
- *
387
- * The Deferred input is resolved when the transaction is fully committed.
388
- */
389
444
runTransaction < T > (
390
445
asyncQueue : AsyncQueue ,
391
446
updateFunction : ( transaction : Transaction ) => Promise < T > ,
@@ -442,10 +497,6 @@ export class SyncEngine implements RemoteSyncer {
442
497
}
443
498
}
444
499
445
- /**
446
- * Applies an OnlineState change to the sync engine and notifies any views of
447
- * the change.
448
- */
449
500
applyOnlineStateChange (
450
501
onlineState : OnlineState ,
451
502
source : OnlineStateSource
@@ -568,10 +619,6 @@ export class SyncEngine implements RemoteSyncer {
568
619
}
569
620
}
570
621
571
- /**
572
- * Registers a user callback that resolves when all pending mutations at the moment of calling
573
- * are acknowledged .
574
- */
575
622
async registerPendingWritesCallback ( callback : Deferred < void > ) : Promise < void > {
576
623
if ( ! this . remoteStore . canUseNetwork ( ) ) {
577
624
logDebug (
@@ -912,13 +959,46 @@ export class SyncEngine implements RemoteSyncer {
912
959
}
913
960
}
914
961
962
+ export function newSyncEngine (
963
+ localStore : LocalStore ,
964
+ remoteStore : RemoteStore ,
965
+ datastore : Datastore ,
966
+ // PORTING NOTE: Manages state synchronization in multi-tab environments.
967
+ sharedClientState : SharedClientState ,
968
+ currentUser : User ,
969
+ maxConcurrentLimboResolutions : number
970
+ ) : SyncEngine {
971
+ return new SyncEngineImpl (
972
+ localStore ,
973
+ remoteStore ,
974
+ datastore ,
975
+ sharedClientState ,
976
+ currentUser ,
977
+ maxConcurrentLimboResolutions
978
+ ) ;
979
+ }
980
+
915
981
/**
916
- * An impplementation of SyncEngine that implement SharedClientStateSyncer for
982
+ * An extension of SyncEngine that also includes SharedClientStateSyncer for
917
983
* Multi-Tab synchronization.
918
984
*/
919
985
// PORTING NOTE: Web only
920
- export class MultiTabSyncEngine extends SyncEngine
921
- implements SharedClientStateSyncer {
986
+ export interface MultiTabSyncEngine
987
+ extends SharedClientStateSyncer ,
988
+ SyncEngine {
989
+ applyPrimaryState ( isPrimary : boolean ) : Promise < void > ;
990
+ }
991
+
992
+ /**
993
+ * An implementation of `SyncEngineImpl` providing multi-tab synchronization on
994
+ * top of `SyncEngineImpl`.
995
+ *
996
+ * Note: some field defined in this class might have public access level, but
997
+ * the class is not exported so they are only accessible from this module.
998
+ * This is useful to implement optional features (like bundles) in free
999
+ * functions, such that they are tree-shakeable.
1000
+ */
1001
+ class MultiTabSyncEngineImpl extends SyncEngineImpl {
922
1002
// The primary state is set to `true` or `false` immediately after Firestore
923
1003
// startup. In the interim, a client should only be considered primary if
924
1004
// `isPrimary` is true.
@@ -1273,3 +1353,21 @@ export class MultiTabSyncEngine extends SyncEngine
1273
1353
}
1274
1354
}
1275
1355
}
1356
+
1357
+ export function newMultiTabSyncEngine (
1358
+ localStore : MultiTabLocalStore ,
1359
+ remoteStore : RemoteStore ,
1360
+ datastore : Datastore ,
1361
+ sharedClientState : SharedClientState ,
1362
+ currentUser : User ,
1363
+ maxConcurrentLimboResolutions : number
1364
+ ) : MultiTabSyncEngine {
1365
+ return new MultiTabSyncEngineImpl (
1366
+ localStore ,
1367
+ remoteStore ,
1368
+ datastore ,
1369
+ sharedClientState ,
1370
+ currentUser ,
1371
+ maxConcurrentLimboResolutions
1372
+ ) ;
1373
+ }
0 commit comments