Skip to content

Commit c0b9713

Browse files
Use initialization function
1 parent 4324f54 commit c0b9713

File tree

3 files changed

+203
-190
lines changed

3 files changed

+203
-190
lines changed

packages/firestore/src/core/component_provider.ts

Lines changed: 134 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -44,193 +44,145 @@ import {
4444
MemoryReferenceDelegate
4545
} from '../local/memory_persistence';
4646

47+
export interface ComponentConfiguration {
48+
asyncQueue: AsyncQueue;
49+
databaseInfo: DatabaseInfo;
50+
platform: Platform;
51+
datastore: Datastore;
52+
clientId: ClientId;
53+
initialUser: User;
54+
maxConcurrentLimboResolutions: number;
55+
persistenceSettings: PersistenceSettings;
56+
}
57+
4758
/**
4859
* Initializes and wires up all core components for Firestore. Implementations
4960
* override `initialize()` to provide all components.
5061
*/
51-
export abstract class ComponentProvider {
52-
protected asyncQueue!: AsyncQueue;
53-
protected databaseInfo!: DatabaseInfo;
54-
protected platform!: Platform;
55-
protected datastore!: Datastore;
56-
protected clientId!: ClientId;
57-
protected initialUser!: User;
58-
protected maxConcurrentLimboResolutions!: number;
59-
protected persistenceSettings!: PersistenceSettings;
62+
export interface ComponentProvider {
63+
persistence: Persistence;
64+
sharedClientState: SharedClientState;
65+
localStore: LocalStore;
66+
syncEngine: SyncEngine;
67+
gcScheduler: GarbageCollectionScheduler | null;
68+
remoteStore: RemoteStore;
69+
eventManager: EventManager;
6070

61-
persistence!: Persistence;
71+
initialize(cfg: ComponentConfiguration): Promise<void>;
72+
73+
clearPersistence(databaseId: DatabaseInfo): Promise<void>;
74+
}
75+
76+
/**
77+
* Provides all components needed for Firestore with IndexedDB persistence.
78+
*/
79+
export class IndexedDbComponentProvider implements ComponentProvider {
80+
persistence!: IndexedDbPersistence;
6281
sharedClientState!: SharedClientState;
6382
localStore!: LocalStore;
6483
syncEngine!: SyncEngine;
65-
gcScheduler!: GarbageCollectionScheduler | null;
84+
gcScheduler!: GarbageCollectionScheduler;
6685
remoteStore!: RemoteStore;
6786
eventManager!: EventManager;
6887

69-
async initialize(
70-
asyncQueue: AsyncQueue,
71-
databaseInfo: DatabaseInfo,
72-
platform: Platform,
73-
datastore: Datastore,
74-
clientId: ClientId,
75-
initialUser: User,
76-
maxConcurrentLimboResolutions: number,
77-
persistenceSettings: PersistenceSettings
78-
): Promise<void> {
79-
this.asyncQueue = asyncQueue;
80-
this.databaseInfo = databaseInfo;
81-
this.platform = platform;
82-
this.datastore = datastore;
83-
this.clientId = clientId;
84-
this.initialUser = initialUser;
85-
this.maxConcurrentLimboResolutions = maxConcurrentLimboResolutions;
86-
this.persistenceSettings = persistenceSettings;
87-
88-
this.sharedClientState = this.createSharedClientState();
89-
this.persistence = this.createPersistence();
90-
await this.persistence.start();
91-
this.gcScheduler = this.createGarbageCollectionScheduler();
92-
this.localStore = this.createLocalStore();
93-
this.remoteStore = this.createRemoteStore();
94-
this.syncEngine = this.createSyncEngine();
95-
this.eventManager = this.createEventManager();
96-
97-
this.sharedClientState.onlineStateHandler = onlineState =>
98-
this.syncEngine.applyOnlineStateChange(
99-
onlineState,
100-
OnlineStateSource.SharedClientState
101-
);
102-
this.remoteStore.syncEngine = this.syncEngine;
103-
this.sharedClientState.syncEngine = this.syncEngine;
104-
105-
await this.sharedClientState.start();
106-
await this.remoteStore.start();
107-
await this.localStore.start();
108-
109-
// NOTE: This will immediately call the listener, so we make sure to
110-
// set it after localStore / remoteStore are started.
111-
await this.persistence.setPrimaryStateListener(async isPrimary => {
112-
await this.syncEngine.applyPrimaryState(isPrimary);
113-
if (this.gcScheduler) {
114-
if (isPrimary && !this.gcScheduler.started) {
115-
this.gcScheduler.start(this.localStore);
116-
} else if (!isPrimary) {
117-
this.gcScheduler.stop();
118-
}
119-
}
120-
});
88+
initialize(cfg: ComponentConfiguration): Promise<void> {
89+
return initializeComponentProvider(this, cfg);
12190
}
12291

123-
protected abstract createSharedClientState(): SharedClientState;
124-
protected abstract createPersistence(): Persistence;
125-
protected abstract createGarbageCollectionScheduler(): GarbageCollectionScheduler | null;
126-
protected abstract createLocalStore(): LocalStore;
127-
protected abstract createRemoteStore(): RemoteStore;
128-
protected abstract createSyncEngine(): SyncEngine;
129-
protected abstract createEventManager(): EventManager;
130-
131-
abstract clearPersistence(databaseId: DatabaseInfo): Promise<void>;
132-
}
133-
134-
/**
135-
* Provides all components needed for Firestore with IndexedDB persistence.
136-
*/
137-
export class IndexedDbComponentProvider extends ComponentProvider {
138-
protected createEventManager(): EventManager {
92+
createEventManager(cfg: ComponentConfiguration): EventManager {
13993
return new EventManager(this.syncEngine);
14094
}
14195

142-
protected createGarbageCollectionScheduler(): GarbageCollectionScheduler | null {
143-
debugAssert(
144-
this.persistence instanceof IndexedDbPersistence,
145-
'Expected persistence to be of type IndexedDbPersistence'
146-
);
96+
createGarbageCollectionScheduler(
97+
cfg: ComponentConfiguration
98+
): GarbageCollectionScheduler | null {
14799
const garbageCollector = this.persistence.referenceDelegate
148100
.garbageCollector;
149-
return new LruScheduler(garbageCollector, this.asyncQueue);
101+
return new LruScheduler(garbageCollector, cfg.asyncQueue);
150102
}
151103

152-
protected createLocalStore(): LocalStore {
104+
createLocalStore(cfg: ComponentConfiguration): LocalStore {
153105
return new LocalStore(
154106
this.persistence,
155107
new IndexFreeQueryEngine(),
156-
this.initialUser
108+
cfg.initialUser
157109
);
158110
}
159111

160-
protected createPersistence(): Persistence {
112+
createPersistence(cfg: ComponentConfiguration): Persistence {
161113
debugAssert(
162-
this.persistenceSettings.durable,
114+
cfg.persistenceSettings.durable,
163115
'Can only start durable persistence'
164116
);
165117

166118
const persistenceKey = IndexedDbPersistence.buildStoragePrefix(
167-
this.databaseInfo
119+
cfg.databaseInfo
168120
);
169-
const serializer = this.platform.newSerializer(
170-
this.databaseInfo.databaseId
121+
const serializer = cfg.platform.newSerializer(
122+
cfg.databaseInfo.databaseId
171123
);
172124
return IndexedDbPersistence.createIndexedDbPersistence({
173-
allowTabSynchronization: this.persistenceSettings.synchronizeTabs,
125+
allowTabSynchronization: cfg.persistenceSettings.synchronizeTabs,
174126
persistenceKey,
175-
clientId: this.clientId,
176-
platform: this.platform,
177-
queue: this.asyncQueue,
127+
clientId: cfg.clientId,
128+
platform: cfg.platform,
129+
queue: cfg.asyncQueue,
178130
serializer,
179131
lruParams: LruParams.withCacheSize(
180-
this.persistenceSettings.cacheSizeBytes
132+
cfg.persistenceSettings.cacheSizeBytes
181133
),
182134
sequenceNumberSyncer: this.sharedClientState
183135
});
184136
}
185137

186-
protected createRemoteStore(): RemoteStore {
138+
createRemoteStore(cfg: ComponentConfiguration): RemoteStore {
187139
return new RemoteStore(
188140
this.localStore,
189-
this.datastore,
190-
this.asyncQueue,
141+
cfg.datastore,
142+
cfg.asyncQueue,
191143
onlineState =>
192144
this.syncEngine.applyOnlineStateChange(
193145
onlineState,
194146
OnlineStateSource.RemoteStore
195147
),
196-
this.platform.newConnectivityMonitor()
148+
cfg.platform.newConnectivityMonitor()
197149
);
198150
}
199151

200-
protected createSharedClientState(): SharedClientState {
152+
createSharedClientState(cfg: ComponentConfiguration): SharedClientState {
201153
debugAssert(
202-
this.persistenceSettings.durable,
154+
cfg.persistenceSettings.durable,
203155
'Can only start durable persistence'
204156
);
205157

206-
if (this.persistenceSettings.synchronizeTabs) {
207-
if (!WebStorageSharedClientState.isAvailable(this.platform)) {
158+
if (cfg.persistenceSettings.synchronizeTabs) {
159+
if (!WebStorageSharedClientState.isAvailable(cfg.platform)) {
208160
throw new FirestoreError(
209161
Code.UNIMPLEMENTED,
210162
'IndexedDB persistence is only available on platforms that support LocalStorage.'
211163
);
212164
}
213165
const persistenceKey = IndexedDbPersistence.buildStoragePrefix(
214-
this.databaseInfo
166+
cfg.databaseInfo
215167
);
216168
return new WebStorageSharedClientState(
217-
this.asyncQueue,
218-
this.platform,
169+
cfg.asyncQueue,
170+
cfg.platform,
219171
persistenceKey,
220-
this.clientId,
221-
this.initialUser
172+
cfg.clientId,
173+
cfg.initialUser
222174
);
223175
}
224176
return new MemorySharedClientState();
225177
}
226178

227-
protected createSyncEngine(): SyncEngine {
179+
createSyncEngine(cfg: ComponentConfiguration): SyncEngine {
228180
return new SyncEngine(
229181
this.localStore,
230182
this.remoteStore,
231183
this.sharedClientState,
232-
this.initialUser,
233-
this.maxConcurrentLimboResolutions
184+
cfg.initialUser,
185+
cfg.maxConcurrentLimboResolutions
234186
);
235187
}
236188

@@ -250,64 +202,76 @@ const MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE =
250202
/**
251203
* Provides all components needed for Firestore with in-memory persistence.
252204
*/
253-
export class MemoryComponentProvider extends ComponentProvider {
205+
export class MemoryComponentProvider implements ComponentProvider {
206+
persistence!: Persistence;
207+
sharedClientState!: SharedClientState;
208+
localStore!: LocalStore;
209+
syncEngine!: SyncEngine;
210+
gcScheduler!: null;
211+
remoteStore!: RemoteStore;
212+
eventManager!: EventManager;
213+
254214
constructor(
255215
readonly referenceDelegateFactory: (
256216
p: MemoryPersistence
257217
) => MemoryReferenceDelegate = MemoryEagerDelegate.factory
258-
) {
259-
super();
218+
) {}
219+
220+
initialize(cfg: ComponentConfiguration): Promise<void> {
221+
return initializeComponentProvider(this, cfg);
260222
}
261223

262-
protected createEventManager(): EventManager {
224+
createEventManager(cfg: ComponentConfiguration): EventManager {
263225
return new EventManager(this.syncEngine);
264226
}
265227

266-
protected createGarbageCollectionScheduler(): GarbageCollectionScheduler | null {
228+
createGarbageCollectionScheduler(
229+
cfg: ComponentConfiguration
230+
): GarbageCollectionScheduler | null {
267231
return null;
268232
}
269233

270-
protected createLocalStore(): LocalStore {
234+
createLocalStore(cfg: ComponentConfiguration): LocalStore {
271235
return new LocalStore(
272236
this.persistence,
273237
new IndexFreeQueryEngine(),
274-
this.initialUser
238+
cfg.initialUser
275239
);
276240
}
277241

278-
protected createPersistence(): Persistence {
242+
createPersistence(cfg: ComponentConfiguration): Persistence {
279243
debugAssert(
280-
!this.persistenceSettings.durable,
244+
!cfg.persistenceSettings.durable,
281245
'Can only start memory persistence'
282246
);
283-
return new MemoryPersistence(this.clientId, this.referenceDelegateFactory);
247+
return new MemoryPersistence(cfg.clientId, this.referenceDelegateFactory);
284248
}
285249

286-
protected createRemoteStore(): RemoteStore {
250+
createRemoteStore(cfg: ComponentConfiguration): RemoteStore {
287251
return new RemoteStore(
288252
this.localStore,
289-
this.datastore,
290-
this.asyncQueue,
253+
cfg.datastore,
254+
cfg.asyncQueue,
291255
onlineState =>
292256
this.syncEngine.applyOnlineStateChange(
293257
onlineState,
294258
OnlineStateSource.RemoteStore
295259
),
296-
this.platform.newConnectivityMonitor()
260+
cfg.platform.newConnectivityMonitor()
297261
);
298262
}
299263

300-
protected createSharedClientState(): SharedClientState {
264+
createSharedClientState(cfg: ComponentConfiguration): SharedClientState {
301265
return new MemorySharedClientState();
302266
}
303267

304-
protected createSyncEngine(): SyncEngine {
268+
createSyncEngine(cfg: ComponentConfiguration): SyncEngine {
305269
return new SyncEngine(
306270
this.localStore,
307271
this.remoteStore,
308272
this.sharedClientState,
309-
this.initialUser,
310-
this.maxConcurrentLimboResolutions
273+
cfg.initialUser,
274+
cfg.maxConcurrentLimboResolutions
311275
);
312276
}
313277

@@ -318,3 +282,42 @@ export class MemoryComponentProvider extends ComponentProvider {
318282
);
319283
}
320284
}
285+
286+
async function initializeComponentProvider(
287+
target: MemoryComponentProvider | IndexedDbComponentProvider,
288+
cfg: ComponentConfiguration
289+
): Promise<void> {
290+
target.sharedClientState = target.createSharedClientState(cfg);
291+
target.persistence = target.createPersistence(cfg);
292+
await target.persistence.start();
293+
target.gcScheduler = target.createGarbageCollectionScheduler(cfg);
294+
target.localStore = target.createLocalStore(cfg);
295+
target.remoteStore = target.createRemoteStore(cfg);
296+
target.syncEngine = target.createSyncEngine(cfg);
297+
target.eventManager = target.createEventManager(cfg);
298+
299+
target.sharedClientState.onlineStateHandler = onlineState =>
300+
target.syncEngine.applyOnlineStateChange(
301+
onlineState,
302+
OnlineStateSource.SharedClientState
303+
);
304+
target.remoteStore.syncEngine = target.syncEngine;
305+
target.sharedClientState.syncEngine = target.syncEngine;
306+
307+
await target.sharedClientState.start();
308+
await target.remoteStore.start();
309+
await target.localStore.start();
310+
311+
// NOTE: This will immediately call the listener, so we make sure to
312+
// set it after localStore / remoteStore are started.
313+
await target.persistence.setPrimaryStateListener(async isPrimary => {
314+
await target.syncEngine.applyPrimaryState(isPrimary);
315+
if (target.gcScheduler) {
316+
if (isPrimary && !target.gcScheduler.started) {
317+
target.gcScheduler.start(target.localStore);
318+
} else if (!isPrimary) {
319+
target.gcScheduler.stop();
320+
}
321+
}
322+
});
323+
}

0 commit comments

Comments
 (0)