@@ -44,193 +44,145 @@ import {
44
44
MemoryReferenceDelegate
45
45
} from '../local/memory_persistence' ;
46
46
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
+
47
58
/**
48
59
* Initializes and wires up all core components for Firestore. Implementations
49
60
* override `initialize()` to provide all components.
50
61
*/
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 ;
60
70
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 ;
62
81
sharedClientState ! : SharedClientState ;
63
82
localStore ! : LocalStore ;
64
83
syncEngine ! : SyncEngine ;
65
- gcScheduler ! : GarbageCollectionScheduler | null ;
84
+ gcScheduler ! : GarbageCollectionScheduler ;
66
85
remoteStore ! : RemoteStore ;
67
86
eventManager ! : EventManager ;
68
87
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 ) ;
121
90
}
122
91
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 {
139
93
return new EventManager ( this . syncEngine ) ;
140
94
}
141
95
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 {
147
99
const garbageCollector = this . persistence . referenceDelegate
148
100
. garbageCollector ;
149
- return new LruScheduler ( garbageCollector , this . asyncQueue ) ;
101
+ return new LruScheduler ( garbageCollector , cfg . asyncQueue ) ;
150
102
}
151
103
152
- protected createLocalStore ( ) : LocalStore {
104
+ createLocalStore ( cfg : ComponentConfiguration ) : LocalStore {
153
105
return new LocalStore (
154
106
this . persistence ,
155
107
new IndexFreeQueryEngine ( ) ,
156
- this . initialUser
108
+ cfg . initialUser
157
109
) ;
158
110
}
159
111
160
- protected createPersistence ( ) : Persistence {
112
+ createPersistence ( cfg : ComponentConfiguration ) : Persistence {
161
113
debugAssert (
162
- this . persistenceSettings . durable ,
114
+ cfg . persistenceSettings . durable ,
163
115
'Can only start durable persistence'
164
116
) ;
165
117
166
118
const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
167
- this . databaseInfo
119
+ cfg . databaseInfo
168
120
) ;
169
- const serializer = this . platform . newSerializer (
170
- this . databaseInfo . databaseId
121
+ const serializer = cfg . platform . newSerializer (
122
+ cfg . databaseInfo . databaseId
171
123
) ;
172
124
return IndexedDbPersistence . createIndexedDbPersistence ( {
173
- allowTabSynchronization : this . persistenceSettings . synchronizeTabs ,
125
+ allowTabSynchronization : cfg . persistenceSettings . synchronizeTabs ,
174
126
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 ,
178
130
serializer,
179
131
lruParams : LruParams . withCacheSize (
180
- this . persistenceSettings . cacheSizeBytes
132
+ cfg . persistenceSettings . cacheSizeBytes
181
133
) ,
182
134
sequenceNumberSyncer : this . sharedClientState
183
135
} ) ;
184
136
}
185
137
186
- protected createRemoteStore ( ) : RemoteStore {
138
+ createRemoteStore ( cfg : ComponentConfiguration ) : RemoteStore {
187
139
return new RemoteStore (
188
140
this . localStore ,
189
- this . datastore ,
190
- this . asyncQueue ,
141
+ cfg . datastore ,
142
+ cfg . asyncQueue ,
191
143
onlineState =>
192
144
this . syncEngine . applyOnlineStateChange (
193
145
onlineState ,
194
146
OnlineStateSource . RemoteStore
195
147
) ,
196
- this . platform . newConnectivityMonitor ( )
148
+ cfg . platform . newConnectivityMonitor ( )
197
149
) ;
198
150
}
199
151
200
- protected createSharedClientState ( ) : SharedClientState {
152
+ createSharedClientState ( cfg : ComponentConfiguration ) : SharedClientState {
201
153
debugAssert (
202
- this . persistenceSettings . durable ,
154
+ cfg . persistenceSettings . durable ,
203
155
'Can only start durable persistence'
204
156
) ;
205
157
206
- if ( this . persistenceSettings . synchronizeTabs ) {
207
- if ( ! WebStorageSharedClientState . isAvailable ( this . platform ) ) {
158
+ if ( cfg . persistenceSettings . synchronizeTabs ) {
159
+ if ( ! WebStorageSharedClientState . isAvailable ( cfg . platform ) ) {
208
160
throw new FirestoreError (
209
161
Code . UNIMPLEMENTED ,
210
162
'IndexedDB persistence is only available on platforms that support LocalStorage.'
211
163
) ;
212
164
}
213
165
const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
214
- this . databaseInfo
166
+ cfg . databaseInfo
215
167
) ;
216
168
return new WebStorageSharedClientState (
217
- this . asyncQueue ,
218
- this . platform ,
169
+ cfg . asyncQueue ,
170
+ cfg . platform ,
219
171
persistenceKey ,
220
- this . clientId ,
221
- this . initialUser
172
+ cfg . clientId ,
173
+ cfg . initialUser
222
174
) ;
223
175
}
224
176
return new MemorySharedClientState ( ) ;
225
177
}
226
178
227
- protected createSyncEngine ( ) : SyncEngine {
179
+ createSyncEngine ( cfg : ComponentConfiguration ) : SyncEngine {
228
180
return new SyncEngine (
229
181
this . localStore ,
230
182
this . remoteStore ,
231
183
this . sharedClientState ,
232
- this . initialUser ,
233
- this . maxConcurrentLimboResolutions
184
+ cfg . initialUser ,
185
+ cfg . maxConcurrentLimboResolutions
234
186
) ;
235
187
}
236
188
@@ -250,64 +202,76 @@ const MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE =
250
202
/**
251
203
* Provides all components needed for Firestore with in-memory persistence.
252
204
*/
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
+
254
214
constructor (
255
215
readonly referenceDelegateFactory : (
256
216
p : MemoryPersistence
257
217
) => MemoryReferenceDelegate = MemoryEagerDelegate . factory
258
- ) {
259
- super ( ) ;
218
+ ) { }
219
+
220
+ initialize ( cfg : ComponentConfiguration ) : Promise < void > {
221
+ return initializeComponentProvider ( this , cfg ) ;
260
222
}
261
223
262
- protected createEventManager ( ) : EventManager {
224
+ createEventManager ( cfg : ComponentConfiguration ) : EventManager {
263
225
return new EventManager ( this . syncEngine ) ;
264
226
}
265
227
266
- protected createGarbageCollectionScheduler ( ) : GarbageCollectionScheduler | null {
228
+ createGarbageCollectionScheduler (
229
+ cfg : ComponentConfiguration
230
+ ) : GarbageCollectionScheduler | null {
267
231
return null ;
268
232
}
269
233
270
- protected createLocalStore ( ) : LocalStore {
234
+ createLocalStore ( cfg : ComponentConfiguration ) : LocalStore {
271
235
return new LocalStore (
272
236
this . persistence ,
273
237
new IndexFreeQueryEngine ( ) ,
274
- this . initialUser
238
+ cfg . initialUser
275
239
) ;
276
240
}
277
241
278
- protected createPersistence ( ) : Persistence {
242
+ createPersistence ( cfg : ComponentConfiguration ) : Persistence {
279
243
debugAssert (
280
- ! this . persistenceSettings . durable ,
244
+ ! cfg . persistenceSettings . durable ,
281
245
'Can only start memory persistence'
282
246
) ;
283
- return new MemoryPersistence ( this . clientId , this . referenceDelegateFactory ) ;
247
+ return new MemoryPersistence ( cfg . clientId , this . referenceDelegateFactory ) ;
284
248
}
285
249
286
- protected createRemoteStore ( ) : RemoteStore {
250
+ createRemoteStore ( cfg : ComponentConfiguration ) : RemoteStore {
287
251
return new RemoteStore (
288
252
this . localStore ,
289
- this . datastore ,
290
- this . asyncQueue ,
253
+ cfg . datastore ,
254
+ cfg . asyncQueue ,
291
255
onlineState =>
292
256
this . syncEngine . applyOnlineStateChange (
293
257
onlineState ,
294
258
OnlineStateSource . RemoteStore
295
259
) ,
296
- this . platform . newConnectivityMonitor ( )
260
+ cfg . platform . newConnectivityMonitor ( )
297
261
) ;
298
262
}
299
263
300
- protected createSharedClientState ( ) : SharedClientState {
264
+ createSharedClientState ( cfg : ComponentConfiguration ) : SharedClientState {
301
265
return new MemorySharedClientState ( ) ;
302
266
}
303
267
304
- protected createSyncEngine ( ) : SyncEngine {
268
+ createSyncEngine ( cfg : ComponentConfiguration ) : SyncEngine {
305
269
return new SyncEngine (
306
270
this . localStore ,
307
271
this . remoteStore ,
308
272
this . sharedClientState ,
309
- this . initialUser ,
310
- this . maxConcurrentLimboResolutions
273
+ cfg . initialUser ,
274
+ cfg . maxConcurrentLimboResolutions
311
275
) ;
312
276
}
313
277
@@ -318,3 +282,42 @@ export class MemoryComponentProvider extends ComponentProvider {
318
282
) ;
319
283
}
320
284
}
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