Skip to content

Commit e7cb1de

Browse files
Make typesafe
1 parent 312e4cf commit e7cb1de

File tree

3 files changed

+98
-106
lines changed

3 files changed

+98
-106
lines changed

packages/firestore/src/core/component_provider.ts

Lines changed: 73 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,20 @@ import {
4444
MemoryReferenceDelegate
4545
} from '../local/memory_persistence';
4646

47-
/**
48-
* Initializes and wires up all core components for Firestore. Implementations
49-
* override `initialize()` to provide all components.
50-
*/
51-
export interface ComponentProvider {
47+
export interface Components {
5248
persistence: Persistence;
5349
sharedClientState: SharedClientState;
5450
localStore: LocalStore;
5551
syncEngine: SyncEngine;
5652
gcScheduler: GarbageCollectionScheduler | null;
5753
remoteStore: RemoteStore;
5854
eventManager: EventManager;
55+
}
5956

57+
/**
58+
* Initializes and wires up all core components for Firestore.
59+
*/
60+
export interface ComponentProvider {
6061
initialize(
6162
asyncQueue: AsyncQueue,
6263
databaseInfo: DatabaseInfo,
@@ -66,7 +67,7 @@ export interface ComponentProvider {
6667
initialUser: User,
6768
maxConcurrentLimboResolutions: number,
6869
persistenceSettings: PersistenceSettings
69-
): Promise<void>;
70+
): Promise<Components>;
7071

7172
clearPersistence(databaseId: DatabaseInfo): Promise<void>;
7273
}
@@ -76,14 +77,6 @@ export interface ComponentProvider {
7677
* Consumers have to call `initialize()` before accessing any properties.
7778
*/
7879
export class IndexedDbComponentProvider implements ComponentProvider {
79-
persistence!: IndexedDbPersistence;
80-
sharedClientState!: SharedClientState;
81-
localStore!: LocalStore;
82-
syncEngine!: SyncEngine;
83-
gcScheduler!: GarbageCollectionScheduler | null;
84-
remoteStore!: RemoteStore;
85-
eventManager!: EventManager;
86-
8780
async initialize(
8881
asyncQueue: AsyncQueue,
8982
databaseInfo: DatabaseInfo,
@@ -93,12 +86,13 @@ export class IndexedDbComponentProvider implements ComponentProvider {
9386
initialUser: User,
9487
maxConcurrentLimboResolutions: number,
9588
persistenceSettings: PersistenceSettings
96-
): Promise<void> {
89+
): Promise<Components> {
9790
assert(
9891
persistenceSettings.durable,
9992
'IndexedDbComponentProvider can only provide durable persistence'
10093
);
101-
assert(!this.persistence, 'initialize() already called');
94+
95+
const components: Partial<Components> = {};
10296

10397
const persistenceKey = IndexedDbPersistence.buildStoragePrefix(
10498
databaseInfo
@@ -112,7 +106,7 @@ export class IndexedDbComponentProvider implements ComponentProvider {
112106
);
113107
}
114108

115-
this.sharedClientState = persistenceSettings.synchronizeTabs
109+
components.sharedClientState = persistenceSettings.synchronizeTabs
116110
? new WebStorageSharedClientState(
117111
asyncQueue,
118112
platform,
@@ -121,69 +115,73 @@ export class IndexedDbComponentProvider implements ComponentProvider {
121115
initialUser
122116
)
123117
: new MemorySharedClientState();
124-
this.sharedClientState.onlineStateHandler = onlineState =>
125-
this.syncEngine!.applyOnlineStateChange(
118+
components.sharedClientState.onlineStateHandler = onlineState =>
119+
components.syncEngine!.applyOnlineStateChange(
126120
onlineState,
127121
OnlineStateSource.SharedClientState
128122
);
129123

130-
this.persistence = await IndexedDbPersistence.createIndexedDbPersistence({
131-
allowTabSynchronization: persistenceSettings.synchronizeTabs,
132-
persistenceKey,
133-
clientId,
134-
platform,
135-
queue: asyncQueue,
136-
serializer,
137-
lruParams: LruParams.withCacheSize(persistenceSettings.cacheSizeBytes),
138-
sequenceNumberSyncer: this.sharedClientState
139-
});
124+
components.persistence = await IndexedDbPersistence.createIndexedDbPersistence(
125+
{
126+
allowTabSynchronization: persistenceSettings.synchronizeTabs,
127+
persistenceKey,
128+
clientId,
129+
platform,
130+
queue: asyncQueue,
131+
serializer,
132+
lruParams: LruParams.withCacheSize(persistenceSettings.cacheSizeBytes),
133+
sequenceNumberSyncer: components.sharedClientState
134+
}
135+
);
140136

141-
const garbageCollector = this.persistence.referenceDelegate
142-
.garbageCollector;
137+
const garbageCollector = (components.persistence as IndexedDbPersistence)
138+
.referenceDelegate.garbageCollector;
143139

144-
this.gcScheduler = new LruScheduler(garbageCollector, asyncQueue);
145-
this.localStore = new LocalStore(
146-
this.persistence,
140+
components.gcScheduler = new LruScheduler(garbageCollector, asyncQueue);
141+
components.localStore = new LocalStore(
142+
components.persistence,
147143
new IndexFreeQueryEngine(),
148144
initialUser
149145
);
150-
this.remoteStore = new RemoteStore(
151-
this.localStore,
146+
components.remoteStore = new RemoteStore(
147+
components.localStore,
152148
datastore,
153149
asyncQueue,
154150
onlineState =>
155-
this.syncEngine!.applyOnlineStateChange(
151+
components.syncEngine!.applyOnlineStateChange(
156152
onlineState,
157153
OnlineStateSource.RemoteStore
158154
),
159155
platform.newConnectivityMonitor()
160156
);
161-
this.syncEngine = new SyncEngine(
162-
this.localStore,
163-
this.remoteStore,
164-
this.sharedClientState,
157+
components.syncEngine = new SyncEngine(
158+
components.localStore,
159+
components.remoteStore,
160+
components.sharedClientState,
165161
initialUser,
166162
maxConcurrentLimboResolutions
167163
);
168-
this.eventManager = new EventManager(this.syncEngine);
164+
components.eventManager = new EventManager(components.syncEngine);
169165

170-
this.remoteStore.syncEngine = this.syncEngine;
171-
this.sharedClientState.syncEngine = this.syncEngine;
166+
components.remoteStore.syncEngine = components.syncEngine;
167+
components.sharedClientState.syncEngine = components.syncEngine;
172168

173-
await this.sharedClientState.start();
174-
await this.remoteStore.start();
175-
await this.localStore.start();
169+
await components.sharedClientState.start();
170+
await components.remoteStore.start();
171+
await components.localStore.start();
176172

177173
// NOTE: This will immediately call the listener, so we make sure to
178174
// set it after localStore / remoteStore are started.
179-
await this.persistence.setPrimaryStateListener(async isPrimary => {
180-
await this.syncEngine!.applyPrimaryState(isPrimary);
181-
if (isPrimary && !this.gcScheduler!.started) {
182-
this.gcScheduler!.start(this.localStore!);
175+
await components.persistence.setPrimaryStateListener(async isPrimary => {
176+
await components.syncEngine!.applyPrimaryState(isPrimary);
177+
if (isPrimary && !components.gcScheduler!.started) {
178+
components.gcScheduler!.start(components.localStore!);
183179
} else if (!isPrimary) {
184-
this.gcScheduler!.stop();
180+
components.gcScheduler!.stop();
185181
}
186182
});
183+
184+
return components as Components;
187185
}
188186

189187
clearPersistence(databaseInfo: DatabaseInfo): Promise<void> {
@@ -204,20 +202,11 @@ const MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE =
204202
* Consumers have to call `initialize()` before accessing any properties.
205203
*/
206204
export class MemoryComponentProvider implements ComponentProvider {
207-
persistence!: Persistence;
208-
sharedClientState!: SharedClientState;
209-
localStore!: LocalStore;
210-
syncEngine!: SyncEngine;
211-
gcScheduler!: GarbageCollectionScheduler | null;
212-
remoteStore!: RemoteStore;
213-
eventManager!: EventManager;
214-
215205
constructor(
216206
readonly referenceDelegateFactory: (
217207
p: MemoryPersistence
218208
) => MemoryReferenceDelegate = MemoryEagerDelegate.factory
219-
) {
220-
}
209+
) {}
221210

222211
async initialize(
223212
asyncQueue: AsyncQueue,
@@ -228,50 +217,54 @@ export class MemoryComponentProvider implements ComponentProvider {
228217
initialUser: User,
229218
maxConcurrentLimboResolutions: number,
230219
persistenceSettings: PersistenceSettings
231-
): Promise<void> {
220+
): Promise<Components> {
232221
if (persistenceSettings.durable) {
233222
throw new FirestoreError(
234223
Code.FAILED_PRECONDITION,
235224
MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE
236225
);
237226
}
238227

239-
this.persistence = new MemoryPersistence(
228+
const components: Partial<Components> = {};
229+
230+
components.persistence = new MemoryPersistence(
240231
clientId,
241232
this.referenceDelegateFactory
242233
);
243-
this.gcScheduler = null;
244-
this.sharedClientState = new MemorySharedClientState();
245-
this.localStore = new LocalStore(
246-
this.persistence,
234+
components.gcScheduler = null;
235+
components.sharedClientState = new MemorySharedClientState();
236+
components.localStore = new LocalStore(
237+
components.persistence,
247238
new IndexFreeQueryEngine(),
248239
initialUser
249240
);
250-
this.remoteStore = new RemoteStore(
251-
this.localStore,
241+
components.remoteStore = new RemoteStore(
242+
components.localStore,
252243
datastore,
253244
asyncQueue,
254245
onlineState =>
255-
this.syncEngine!.applyOnlineStateChange(
246+
components.syncEngine!.applyOnlineStateChange(
256247
onlineState,
257248
OnlineStateSource.RemoteStore
258249
),
259250
platform.newConnectivityMonitor()
260251
);
261-
this.syncEngine = new SyncEngine(
262-
this.localStore,
263-
this.remoteStore,
264-
this.sharedClientState,
252+
components.syncEngine = new SyncEngine(
253+
components.localStore,
254+
components.remoteStore,
255+
components.sharedClientState,
265256
initialUser,
266257
maxConcurrentLimboResolutions
267258
);
268-
this.eventManager = new EventManager(this.syncEngine);
259+
components.eventManager = new EventManager(components.syncEngine);
260+
261+
components.remoteStore.syncEngine = components.syncEngine;
269262

270-
this.remoteStore.syncEngine = this.syncEngine;
263+
await components.remoteStore.start();
264+
await components.remoteStore.applyPrimaryState(true);
265+
await components.syncEngine.applyPrimaryState(true);
271266

272-
await this.remoteStore.start();
273-
await this.remoteStore.applyPrimaryState(true);
274-
await this.syncEngine.applyPrimaryState(true);
267+
return components as Components;
275268
}
276269

277270
clearPersistence(): never {

packages/firestore/src/core/firestore_client.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ export class FirestoreClient {
248248
persistenceResult: Deferred<void>
249249
): Promise<void> {
250250
try {
251-
await componentProvider.initialize(
251+
const components = await componentProvider.initialize(
252252
this.asyncQueue,
253253
this.databaseInfo,
254254
this.platform,
@@ -259,13 +259,13 @@ export class FirestoreClient {
259259
persistenceSettings
260260
);
261261

262-
this.persistence = componentProvider.persistence;
263-
this.sharedClientState = componentProvider.sharedClientState;
264-
this.localStore = componentProvider.localStore;
265-
this.remoteStore = componentProvider.remoteStore;
266-
this.syncEngine = componentProvider.syncEngine;
267-
this.gcScheduler = componentProvider.gcScheduler;
268-
this.eventMgr = componentProvider.eventManager;
262+
this.persistence = components.persistence;
263+
this.sharedClientState = components.sharedClientState;
264+
this.localStore = components.localStore;
265+
this.remoteStore = components.remoteStore;
266+
this.syncEngine = components.syncEngine;
267+
this.gcScheduler = components.gcScheduler;
268+
this.eventMgr = components.eventManager;
269269

270270
// When a user calls clearPersistence() in one client, all other clients
271271
// need to be terminated to allow the delete to succeed.

0 commit comments

Comments
 (0)