Skip to content

Commit 751324f

Browse files
Merge c4d6a84 into a36b51b
2 parents a36b51b + c4d6a84 commit 751324f

23 files changed

+639
-620
lines changed

packages/firestore/src/api/database.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
288288
constructor(
289289
databaseIdOrApp: FirestoreDatabase | FirebaseApp,
290290
authProvider: Provider<FirebaseAuthInternalName>,
291-
persistenceProvider: ComponentProvider = new MemoryComponentProvider()
291+
componentProvider: ComponentProvider = new MemoryComponentProvider()
292292
) {
293293
if (typeof (databaseIdOrApp as FirebaseApp).options === 'object') {
294294
// This is very likely a Firebase app object
@@ -313,7 +313,7 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
313313
this._credentials = new EmptyCredentialsProvider();
314314
}
315315

316-
this._componentProvider = persistenceProvider;
316+
this._componentProvider = componentProvider;
317317
this._settings = new FirestoreSettings({});
318318
this._dataReader = this.createDataReader(this._databaseId);
319319
}

packages/firestore/src/core/component_provider.ts

Lines changed: 67 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import {
2121
SharedClientState,
2222
WebStorageSharedClientState
2323
} from '../local/shared_client_state';
24-
import { LocalStore } from '../local/local_store';
25-
import { SyncEngine } from './sync_engine';
24+
import { LocalStore, MultiTabLocalStore } from '../local/local_store';
25+
import { MultiTabSyncEngine, SyncEngine } from './sync_engine';
2626
import { RemoteStore } from '../remote/remote_store';
2727
import { EventManager } from './event_manager';
2828
import { AsyncQueue } from '../util/async_queue';
@@ -81,7 +81,7 @@ export interface ComponentProvider {
8181
* Provides all components needed for Firestore with in-memory persistence.
8282
* Uses EagerGC garbage collection.
8383
*/
84-
export class MemoryComponentProvider {
84+
export class MemoryComponentProvider implements ComponentProvider {
8585
persistence!: Persistence;
8686
sharedClientState!: SharedClientState;
8787
localStore!: LocalStore;
@@ -106,24 +106,12 @@ export class MemoryComponentProvider {
106106
OnlineStateSource.SharedClientState
107107
);
108108
this.remoteStore.syncEngine = this.syncEngine;
109-
this.sharedClientState.syncEngine = this.syncEngine;
110109

110+
await this.localStore.start();
111111
await this.sharedClientState.start();
112112
await this.remoteStore.start();
113-
await this.localStore.start();
114113

115-
// NOTE: This will immediately call the listener, so we make sure to
116-
// set it after localStore / remoteStore are started.
117-
await this.persistence.setPrimaryStateListener(async isPrimary => {
118-
await this.syncEngine.applyPrimaryState(isPrimary);
119-
if (this.gcScheduler) {
120-
if (isPrimary && !this.gcScheduler.started) {
121-
this.gcScheduler.start(this.localStore);
122-
} else if (!isPrimary) {
123-
this.gcScheduler.stop();
124-
}
125-
}
126-
});
114+
await this.remoteStore.applyPrimaryState(this.syncEngine.isPrimaryClient);
127115
}
128116

129117
createEventManager(cfg: ComponentConfiguration): EventManager {
@@ -149,7 +137,7 @@ export class MemoryComponentProvider {
149137
!cfg.persistenceSettings.durable,
150138
'Can only start memory persistence'
151139
);
152-
return new MemoryPersistence(cfg.clientId, MemoryEagerDelegate.factory);
140+
return new MemoryPersistence(MemoryEagerDelegate.factory);
153141
}
154142

155143
createRemoteStore(cfg: ComponentConfiguration): RemoteStore {
@@ -192,13 +180,58 @@ export class MemoryComponentProvider {
192180
* Provides all components needed for Firestore with IndexedDB persistence.
193181
*/
194182
export class IndexedDbComponentProvider extends MemoryComponentProvider {
183+
persistence!: IndexedDbPersistence;
184+
185+
// TODO(tree-shaking): Create an IndexedDbComponentProvider and a
186+
// MultiTabComponentProvider. The IndexedDbComponentProvider should depend
187+
// on LocalStore and SyncEngine.
188+
localStore!: MultiTabLocalStore;
189+
syncEngine!: MultiTabSyncEngine;
190+
191+
async initialize(cfg: ComponentConfiguration): Promise<void> {
192+
await super.initialize(cfg);
193+
194+
// NOTE: This will immediately call the listener, so we make sure to
195+
// set it after localStore / remoteStore are started.
196+
await this.persistence.setPrimaryStateListener(async isPrimary => {
197+
await (this.syncEngine as MultiTabSyncEngine).applyPrimaryState(
198+
isPrimary
199+
);
200+
if (this.gcScheduler) {
201+
if (isPrimary && !this.gcScheduler.started) {
202+
this.gcScheduler.start(this.localStore);
203+
} else if (!isPrimary) {
204+
this.gcScheduler.stop();
205+
}
206+
}
207+
});
208+
}
209+
210+
createLocalStore(cfg: ComponentConfiguration): LocalStore {
211+
return new MultiTabLocalStore(
212+
this.persistence,
213+
new IndexFreeQueryEngine(),
214+
cfg.initialUser
215+
);
216+
}
217+
218+
createSyncEngine(cfg: ComponentConfiguration): SyncEngine {
219+
const syncEngine = new MultiTabSyncEngine(
220+
this.localStore,
221+
this.remoteStore,
222+
this.sharedClientState,
223+
cfg.initialUser,
224+
cfg.maxConcurrentLimboResolutions
225+
);
226+
if (this.sharedClientState instanceof WebStorageSharedClientState) {
227+
this.sharedClientState.syncEngine = syncEngine;
228+
}
229+
return syncEngine;
230+
}
231+
195232
createGarbageCollectionScheduler(
196233
cfg: ComponentConfiguration
197234
): GarbageCollectionScheduler | null {
198-
debugAssert(
199-
this.persistence instanceof IndexedDbPersistence,
200-
'IndexedDbComponentProvider should provide IndexedDBPersistence'
201-
);
202235
const garbageCollector = this.persistence.referenceDelegate
203236
.garbageCollector;
204237
return new LruScheduler(garbageCollector, cfg.asyncQueue);
@@ -214,27 +247,23 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
214247
cfg.databaseInfo
215248
);
216249
const serializer = cfg.platform.newSerializer(cfg.databaseInfo.databaseId);
217-
return IndexedDbPersistence.createIndexedDbPersistence({
218-
allowTabSynchronization: cfg.persistenceSettings.synchronizeTabs,
250+
return new IndexedDbPersistence(
251+
cfg.persistenceSettings.synchronizeTabs,
219252
persistenceKey,
220-
clientId: cfg.clientId,
221-
platform: cfg.platform,
222-
queue: cfg.asyncQueue,
253+
cfg.clientId,
254+
cfg.platform,
255+
LruParams.withCacheSize(cfg.persistenceSettings.cacheSizeBytes),
256+
cfg.asyncQueue,
223257
serializer,
224-
lruParams: LruParams.withCacheSize(
225-
cfg.persistenceSettings.cacheSizeBytes
226-
),
227-
sequenceNumberSyncer: this.sharedClientState
228-
});
258+
this.sharedClientState
259+
);
229260
}
230261

231262
createSharedClientState(cfg: ComponentConfiguration): SharedClientState {
232-
debugAssert(
233-
cfg.persistenceSettings.durable,
234-
'Can only start durable persistence'
235-
);
236-
237-
if (cfg.persistenceSettings.synchronizeTabs) {
263+
if (
264+
cfg.persistenceSettings.durable &&
265+
cfg.persistenceSettings.synchronizeTabs
266+
) {
238267
if (!WebStorageSharedClientState.isAvailable(cfg.platform)) {
239268
throw new FirestoreError(
240269
Code.UNIMPLEMENTED,

0 commit comments

Comments
 (0)