Skip to content

Commit b2e9ad5

Browse files
Merge d7b5d2a into e8b950f
2 parents e8b950f + d7b5d2a commit b2e9ad5

File tree

10 files changed

+1206
-984
lines changed

10 files changed

+1206
-984
lines changed

packages/firestore/exp/dependencies.json

Lines changed: 211 additions & 238 deletions
Large diffs are not rendered by default.

packages/firestore/exp/src/api/components.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ import {
2323
OfflineComponentProvider,
2424
OnlineComponentProvider
2525
} from '../../../src/core/component_provider';
26-
import {handleUserChange, LocalStore} from '../../../src/local/local_store';
26+
import { handleUserChange, LocalStore } from '../../../src/local/local_store';
2727
import { Deferred } from '../../../src/util/promise';
2828
import { logDebug } from '../../../src/util/log';
29-
import { SyncEngine } from '../../../src/core/sync_engine';
29+
import {
30+
SyncEngine,
31+
syncEngineListen,
32+
syncEngineUnlisten
33+
} from '../../../src/core/sync_engine';
3034
import { RemoteStore } from '../../../src/remote/remote_store';
3135
import { Persistence } from '../../../src/local/persistence';
3236
import { EventManager } from '../../../src/core/event_manager';
@@ -153,9 +157,14 @@ export function getRemoteStore(firestore: Firestore): Promise<RemoteStore> {
153157
}
154158

155159
export function getEventManager(firestore: Firestore): Promise<EventManager> {
156-
return getOnlineComponentProvider(firestore).then(
157-
components => components.eventManager
158-
);
160+
return getOnlineComponentProvider(firestore).then(components => {
161+
const eventManager = components.eventManager;
162+
eventManager.subscribe(
163+
syncEngineListen.bind(null, components.syncEngine),
164+
syncEngineUnlisten.bind(null, components.syncEngine)
165+
);
166+
return eventManager;
167+
});
159168
}
160169

161170
export function getPersistence(firestore: Firestore): Promise<Persistence> {

packages/firestore/src/core/component_provider.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ import {
2929
import {
3030
applyActiveTargetsChange,
3131
applyBatchState,
32+
applyOnlineStateChange,
3233
applyPrimaryState,
3334
applyTargetState,
3435
getActiveClients,
36+
handleCredentialChange,
3537
newSyncEngine,
3638
SyncEngine
3739
} from './sync_engine';
@@ -332,20 +334,26 @@ export class OnlineComponentProvider {
332334
this.syncEngine = this.createSyncEngine(cfg);
333335
this.eventManager = this.createEventManager(cfg);
334336

337+
this.syncEngine.subscribe(this.eventManager);
338+
335339
this.sharedClientState.onlineStateHandler = onlineState =>
336-
this.syncEngine.applyOnlineStateChange(
340+
applyOnlineStateChange(
341+
this.syncEngine,
337342
onlineState,
338343
OnlineStateSource.SharedClientState
339344
);
340345

341-
this.remoteStore.syncEngine = this.syncEngine;
346+
this.remoteStore.remoteSyncer.handleCredentialChange = handleCredentialChange.bind(
347+
null,
348+
this.syncEngine
349+
);
342350

343351
await this.remoteStore.start();
344352
await this.remoteStore.applyPrimaryState(this.syncEngine.isPrimaryClient);
345353
}
346354

347355
createEventManager(cfg: ComponentConfiguration): EventManager {
348-
return new EventManager(this.syncEngine);
356+
return new EventManager();
349357
}
350358

351359
createDatastore(cfg: ComponentConfiguration): Datastore {
@@ -360,7 +368,8 @@ export class OnlineComponentProvider {
360368
this.datastore,
361369
cfg.asyncQueue,
362370
onlineState =>
363-
this.syncEngine.applyOnlineStateChange(
371+
applyOnlineStateChange(
372+
this.syncEngine,
364373
onlineState,
365374
OnlineStateSource.RemoteStore
366375
),
@@ -372,7 +381,6 @@ export class OnlineComponentProvider {
372381
return newSyncEngine(
373382
this.localStore,
374383
this.remoteStore,
375-
this.datastore,
376384
this.sharedClientState,
377385
cfg.initialUser,
378386
cfg.maxConcurrentLimboResolutions,

packages/firestore/src/core/event_manager.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { debugAssert } from '../util/assert';
1919
import { EventHandler } from '../util/misc';
2020
import { ObjectMap } from '../util/obj_map';
2121
import { canonifyQuery, Query, queryEquals, stringifyQuery } from './query';
22-
import { SyncEngine, SyncEngineListener } from './sync_engine';
22+
import { SyncEngineListener } from './sync_engine';
2323
import { OnlineState } from './types';
2424
import { ChangeType, DocumentViewChange, ViewSnapshot } from './view_snapshot';
2525
import { wrapInUserErrorIfRecoverable } from '../util/async_queue';
@@ -45,6 +45,10 @@ export interface Observer<T> {
4545
* EventManager is responsible for mapping queries to query event emitters.
4646
* It handles "fan-out". -- Identical queries will re-use the same watch on the
4747
* backend.
48+
*
49+
* PORTING NOTE: On Web, EventManager requires a call to `subscribe()` to
50+
* register SyncEngine's `listen()` and `unlisten()` functionality. This allows
51+
* users to tree-shake the Watch logic.
4852
*/
4953
export class EventManager implements SyncEngineListener {
5054
private queries = new ObjectMap<Query, QueryListenersInfo>(
@@ -56,11 +60,21 @@ export class EventManager implements SyncEngineListener {
5660

5761
private snapshotsInSyncListeners: Set<Observer<void>> = new Set();
5862

59-
constructor(private syncEngine: SyncEngine) {
60-
this.syncEngine.subscribe(this);
63+
/** Callback invoked when a Query is first listen to. */
64+
private onListen?: (query: Query) => Promise<ViewSnapshot>;
65+
/** Callback invoked once all listeners to a Query are removed. */
66+
private onUnlisten?: (query: Query) => Promise<void>;
67+
68+
subscribe(
69+
onListen: (query: Query) => Promise<ViewSnapshot>,
70+
onUnlisten: (query: Query) => Promise<void>
71+
): void {
72+
this.onListen = onListen;
73+
this.onUnlisten = onUnlisten;
6174
}
6275

6376
async listen(listener: QueryListener): Promise<void> {
77+
debugAssert(!!this.onListen, 'onListen not set');
6478
const query = listener.query;
6579
let firstListen = false;
6680

@@ -72,7 +86,7 @@ export class EventManager implements SyncEngineListener {
7286

7387
if (firstListen) {
7488
try {
75-
queryInfo.viewSnap = await this.syncEngine.listen(query);
89+
queryInfo.viewSnap = await this.onListen(query);
7690
} catch (e) {
7791
const firestoreError = wrapInUserErrorIfRecoverable(
7892
e,
@@ -102,6 +116,7 @@ export class EventManager implements SyncEngineListener {
102116
}
103117

104118
async unlisten(listener: QueryListener): Promise<void> {
119+
debugAssert(!!this.onUnlisten, 'onUnlisten not set');
105120
const query = listener.query;
106121
let lastListen = false;
107122

@@ -116,7 +131,7 @@ export class EventManager implements SyncEngineListener {
116131

117132
if (lastListen) {
118133
this.queries.delete(query);
119-
return this.syncEngine.unlisten(query);
134+
return this.onUnlisten(query);
120135
}
121136
}
122137

packages/firestore/src/core/firestore_client.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ import {
3939
Observer,
4040
QueryListener
4141
} from './event_manager';
42-
import { SyncEngine } from './sync_engine';
42+
import {
43+
registerPendingWritesCallback,
44+
SyncEngine,
45+
syncEngineListen,
46+
syncEngineUnlisten,
47+
syncEngineWrite
48+
} from './sync_engine';
4349
import { View } from './view';
4450
import { SharedClientState } from '../local/shared_client_state';
4551
import { AutoId } from '../util/misc';
@@ -277,6 +283,11 @@ export class FirestoreClient {
277283
this.syncEngine = onlineComponentProvider.syncEngine;
278284
this.eventMgr = onlineComponentProvider.eventManager;
279285

286+
this.eventMgr.subscribe(
287+
syncEngineListen.bind(null, this.syncEngine),
288+
syncEngineUnlisten.bind(null, this.syncEngine)
289+
);
290+
280291
// When a user calls clearPersistence() in one client, all other clients
281292
// need to be terminated to allow the delete to succeed.
282293
this.persistence.setDatabaseDeletedListener(async () => {
@@ -405,9 +416,9 @@ export class FirestoreClient {
405416
this.verifyNotTerminated();
406417

407418
const deferred = new Deferred<void>();
408-
this.asyncQueue.enqueueAndForget(() => {
409-
return this.syncEngine.registerPendingWritesCallback(deferred);
410-
});
419+
this.asyncQueue.enqueueAndForget(() =>
420+
registerPendingWritesCallback(this.syncEngine, deferred)
421+
);
411422
return deferred.promise;
412423
}
413424

@@ -480,7 +491,7 @@ export class FirestoreClient {
480491
this.verifyNotTerminated();
481492
const deferred = new Deferred<void>();
482493
this.asyncQueue.enqueueAndForget(() =>
483-
this.syncEngine.write(mutations, deferred)
494+
syncEngineWrite(this.syncEngine, mutations, deferred)
484495
);
485496
return deferred.promise;
486497
}
@@ -549,7 +560,9 @@ export function enqueueWrite(
549560
mutations: Mutation[]
550561
): Promise<void> {
551562
const deferred = new Deferred<void>();
552-
asyncQueue.enqueueAndForget(() => syncEngine.write(mutations, deferred));
563+
asyncQueue.enqueueAndForget(() =>
564+
syncEngineWrite(syncEngine, mutations, deferred)
565+
);
553566
return deferred.promise;
554567
}
555568

@@ -570,9 +583,9 @@ export function enqueueWaitForPendingWrites(
570583
syncEngine: SyncEngine
571584
): Promise<void> {
572585
const deferred = new Deferred<void>();
573-
asyncQueue.enqueueAndForget(() => {
574-
return syncEngine.registerPendingWritesCallback(deferred);
575-
});
586+
asyncQueue.enqueueAndForget(() =>
587+
registerPendingWritesCallback(syncEngine, deferred)
588+
);
576589
return deferred.promise;
577590
}
578591

0 commit comments

Comments
 (0)