@@ -48,34 +48,17 @@ import {
48
48
* Initializes and wires up all core components for Firestore. Implementations
49
49
* override `initialize()` to provide all components.
50
50
*/
51
- export interface ComponentProvider {
52
- persistence : Persistence ;
53
- sharedClientState : SharedClientState ;
54
- localStore : LocalStore ;
55
- syncEngine : SyncEngine ;
56
- gcScheduler : GarbageCollectionScheduler | null ;
57
- remoteStore : RemoteStore ;
58
- eventManager : EventManager ;
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 ;
59
60
60
- initialize (
61
- asyncQueue : AsyncQueue ,
62
- databaseInfo : DatabaseInfo ,
63
- platform : Platform ,
64
- datastore : Datastore ,
65
- clientId : ClientId ,
66
- initialUser : User ,
67
- maxConcurrentLimboResolutions : number ,
68
- persistenceSettings : PersistenceSettings
69
- ) : Promise < void > ;
70
-
71
- clearPersistence ( databaseId : DatabaseInfo ) : Promise < void > ;
72
- }
73
-
74
- /**
75
- * Provides all components needed for Firestore with IndexedDB persistence.
76
- */
77
- export class IndexedDbComponentProvider implements ComponentProvider {
78
- persistence ! : IndexedDbPersistence ;
61
+ persistence ! : Persistence ;
79
62
sharedClientState ! : SharedClientState ;
80
63
localStore ! : LocalStore ;
81
64
syncEngine ! : SyncEngine ;
@@ -93,96 +76,162 @@ export class IndexedDbComponentProvider implements ComponentProvider {
93
76
maxConcurrentLimboResolutions : number ,
94
77
persistenceSettings : PersistenceSettings
95
78
) : Promise < void > {
96
- debugAssert (
97
- persistenceSettings . durable ,
98
- 'IndexedDbComponentProvider can only provide durable persistence'
99
- ) ;
100
- debugAssert ( ! this . sharedClientState , 'initialize() already called' ) ;
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 ;
101
87
102
- const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
103
- databaseInfo
104
- ) ;
105
-
106
- const serializer = platform . newSerializer ( databaseInfo . databaseId ) ;
107
- if ( ! WebStorageSharedClientState . isAvailable ( platform ) ) {
108
- throw new FirestoreError (
109
- Code . UNIMPLEMENTED ,
110
- 'IndexedDB persistence is only available on platforms that support LocalStorage.'
111
- ) ;
112
- }
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 ( ) ;
113
96
114
- this . sharedClientState = persistenceSettings . synchronizeTabs
115
- ? new WebStorageSharedClientState (
116
- asyncQueue ,
117
- platform ,
118
- persistenceKey ,
119
- clientId ,
120
- initialUser
121
- )
122
- : new MemorySharedClientState ( ) ;
123
97
this . sharedClientState . onlineStateHandler = onlineState =>
124
98
this . syncEngine . applyOnlineStateChange (
125
99
onlineState ,
126
100
OnlineStateSource . SharedClientState
127
101
) ;
102
+ this . remoteStore . syncEngine = this . syncEngine ;
103
+ this . sharedClientState . syncEngine = this . syncEngine ;
128
104
129
- this . persistence = await IndexedDbPersistence . createIndexedDbPersistence ( {
130
- allowTabSynchronization : persistenceSettings . synchronizeTabs ,
131
- persistenceKey,
132
- clientId,
133
- platform,
134
- queue : asyncQueue ,
135
- serializer,
136
- lruParams : LruParams . withCacheSize ( persistenceSettings . cacheSizeBytes ) ,
137
- sequenceNumberSyncer : this . sharedClientState
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
+ }
138
120
} ) ;
121
+ }
122
+
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 {
139
+ return new EventManager ( this . syncEngine ) ;
140
+ }
139
141
142
+ protected createGarbageCollectionScheduler ( ) : GarbageCollectionScheduler | null {
143
+ debugAssert (
144
+ this . persistence instanceof IndexedDbPersistence ,
145
+ 'Expected persistence to be of type IndexedDbPersistence'
146
+ ) ;
140
147
const garbageCollector = this . persistence . referenceDelegate
141
148
. garbageCollector ;
149
+ return new LruScheduler ( garbageCollector , this . asyncQueue ) ;
150
+ }
142
151
143
- this . gcScheduler = new LruScheduler ( garbageCollector , asyncQueue ) ;
144
- this . localStore = new LocalStore (
152
+ protected createLocalStore ( ) : LocalStore {
153
+ return new LocalStore (
145
154
this . persistence ,
146
155
new IndexFreeQueryEngine ( ) ,
147
- initialUser
156
+ this . initialUser
148
157
) ;
149
- this . remoteStore = new RemoteStore (
158
+ }
159
+
160
+ protected createPersistence ( ) : Persistence {
161
+ debugAssert (
162
+ this . persistenceSettings . durable ,
163
+ 'Can only start durable persistence'
164
+ ) ;
165
+
166
+ const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
167
+ this . databaseInfo
168
+ ) ;
169
+ const serializer = this . platform . newSerializer (
170
+ this . databaseInfo . databaseId
171
+ ) ;
172
+ return IndexedDbPersistence . createIndexedDbPersistence ( {
173
+ allowTabSynchronization : this . persistenceSettings . synchronizeTabs ,
174
+ persistenceKey,
175
+ clientId : this . clientId ,
176
+ platform : this . platform ,
177
+ queue : this . asyncQueue ,
178
+ serializer,
179
+ lruParams : LruParams . withCacheSize (
180
+ this . persistenceSettings . cacheSizeBytes
181
+ ) ,
182
+ sequenceNumberSyncer : this . sharedClientState
183
+ } ) ;
184
+ }
185
+
186
+ protected createRemoteStore ( ) : RemoteStore {
187
+ return new RemoteStore (
150
188
this . localStore ,
151
- datastore ,
152
- asyncQueue ,
189
+ this . datastore ,
190
+ this . asyncQueue ,
153
191
onlineState =>
154
192
this . syncEngine . applyOnlineStateChange (
155
193
onlineState ,
156
194
OnlineStateSource . RemoteStore
157
195
) ,
158
- platform . newConnectivityMonitor ( )
196
+ this . platform . newConnectivityMonitor ( )
159
197
) ;
160
- this . syncEngine = new SyncEngine (
198
+ }
199
+
200
+ protected createSharedClientState ( ) : SharedClientState {
201
+ debugAssert (
202
+ this . persistenceSettings . durable ,
203
+ 'Can only start durable persistence'
204
+ ) ;
205
+
206
+ if ( this . persistenceSettings . synchronizeTabs ) {
207
+ if ( ! WebStorageSharedClientState . isAvailable ( this . platform ) ) {
208
+ throw new FirestoreError (
209
+ Code . UNIMPLEMENTED ,
210
+ 'IndexedDB persistence is only available on platforms that support LocalStorage.'
211
+ ) ;
212
+ }
213
+ const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
214
+ this . databaseInfo
215
+ ) ;
216
+ return new WebStorageSharedClientState (
217
+ this . asyncQueue ,
218
+ this . platform ,
219
+ persistenceKey ,
220
+ this . clientId ,
221
+ this . initialUser
222
+ ) ;
223
+ }
224
+ return new MemorySharedClientState ( ) ;
225
+ }
226
+
227
+ protected createSyncEngine ( ) : SyncEngine {
228
+ return new SyncEngine (
161
229
this . localStore ,
162
230
this . remoteStore ,
163
231
this . sharedClientState ,
164
- initialUser ,
165
- maxConcurrentLimboResolutions
232
+ this . initialUser ,
233
+ this . maxConcurrentLimboResolutions
166
234
) ;
167
- this . eventManager = new EventManager ( this . syncEngine ) ;
168
-
169
- this . remoteStore . syncEngine = this . syncEngine ;
170
- this . sharedClientState . syncEngine = this . syncEngine ;
171
-
172
- await this . sharedClientState . start ( ) ;
173
- await this . remoteStore . start ( ) ;
174
- await this . localStore . start ( ) ;
175
-
176
- // NOTE: This will immediately call the listener, so we make sure to
177
- // set it after localStore / remoteStore are started.
178
- await this . persistence . setPrimaryStateListener ( async isPrimary => {
179
- await this . syncEngine . applyPrimaryState ( isPrimary ) ;
180
- if ( isPrimary && ! this . gcScheduler ! . started ) {
181
- this . gcScheduler ! . start ( this . localStore ) ;
182
- } else if ( ! isPrimary ) {
183
- this . gcScheduler ! . stop ( ) ;
184
- }
185
- } ) ;
186
235
}
187
236
188
237
clearPersistence ( databaseInfo : DatabaseInfo ) : Promise < void > {
@@ -201,80 +250,71 @@ const MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE =
201
250
/**
202
251
* Provides all components needed for Firestore with in-memory persistence.
203
252
*/
204
- export class MemoryComponentProvider implements ComponentProvider {
205
- persistence ! : Persistence ;
206
- sharedClientState ! : SharedClientState ;
207
- localStore ! : LocalStore ;
208
- syncEngine ! : SyncEngine ;
209
- gcScheduler ! : GarbageCollectionScheduler | null ;
210
- remoteStore ! : RemoteStore ;
211
- eventManager ! : EventManager ;
212
-
253
+ export class MemoryComponentProvider extends ComponentProvider {
213
254
constructor (
214
255
readonly referenceDelegateFactory : (
215
256
p : MemoryPersistence
216
257
) => MemoryReferenceDelegate = MemoryEagerDelegate . factory
217
- ) { }
218
-
219
- async initialize (
220
- asyncQueue : AsyncQueue ,
221
- databaseInfo : DatabaseInfo ,
222
- platform : Platform ,
223
- datastore : Datastore ,
224
- clientId : ClientId ,
225
- initialUser : User ,
226
- maxConcurrentLimboResolutions : number ,
227
- persistenceSettings : PersistenceSettings
228
- ) : Promise < void > {
229
- if ( persistenceSettings . durable ) {
230
- throw new FirestoreError (
231
- Code . FAILED_PRECONDITION ,
232
- MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE
233
- ) ;
234
- }
258
+ ) {
259
+ super ( ) ;
260
+ }
235
261
236
- this . persistence = new MemoryPersistence (
237
- clientId ,
238
- this . referenceDelegateFactory
262
+ clearPersistence ( ) : never {
263
+ throw new FirestoreError (
264
+ Code . FAILED_PRECONDITION ,
265
+ MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE
239
266
) ;
240
- this . gcScheduler = null ;
241
- this . sharedClientState = new MemorySharedClientState ( ) ;
242
- this . localStore = new LocalStore (
267
+ }
268
+
269
+ protected createEventManager ( ) : EventManager {
270
+ return new EventManager ( this . syncEngine ) ;
271
+ }
272
+
273
+ protected createGarbageCollectionScheduler ( ) : GarbageCollectionScheduler | null {
274
+ return null ;
275
+ }
276
+
277
+ protected createLocalStore ( ) : LocalStore {
278
+ return new LocalStore (
243
279
this . persistence ,
244
280
new IndexFreeQueryEngine ( ) ,
245
- initialUser
281
+ this . initialUser
282
+ ) ;
283
+ }
284
+
285
+ protected createPersistence ( ) : Persistence {
286
+ debugAssert (
287
+ ! this . persistenceSettings . durable ,
288
+ 'Can only start memory persistence'
246
289
) ;
247
- this . remoteStore = new RemoteStore (
290
+ return new MemoryPersistence ( this . clientId , this . referenceDelegateFactory ) ;
291
+ }
292
+
293
+ protected createRemoteStore ( ) : RemoteStore {
294
+ return new RemoteStore (
248
295
this . localStore ,
249
- datastore ,
250
- asyncQueue ,
296
+ this . datastore ,
297
+ this . asyncQueue ,
251
298
onlineState =>
252
299
this . syncEngine . applyOnlineStateChange (
253
300
onlineState ,
254
301
OnlineStateSource . RemoteStore
255
302
) ,
256
- platform . newConnectivityMonitor ( )
303
+ this . platform . newConnectivityMonitor ( )
257
304
) ;
258
- this . syncEngine = new SyncEngine (
259
- this . localStore ,
260
- this . remoteStore ,
261
- this . sharedClientState ,
262
- initialUser ,
263
- maxConcurrentLimboResolutions
264
- ) ;
265
- this . eventManager = new EventManager ( this . syncEngine ) ;
266
-
267
- this . remoteStore . syncEngine = this . syncEngine ;
305
+ }
268
306
269
- await this . remoteStore . start ( ) ;
270
- await this . remoteStore . applyPrimaryState ( true ) ;
271
- await this . syncEngine . applyPrimaryState ( true ) ;
307
+ protected createSharedClientState ( ) : SharedClientState {
308
+ return new MemorySharedClientState ( ) ;
272
309
}
273
310
274
- clearPersistence ( ) : never {
275
- throw new FirestoreError (
276
- Code . FAILED_PRECONDITION ,
277
- MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE
311
+ protected createSyncEngine ( ) : SyncEngine {
312
+ return new SyncEngine (
313
+ this . localStore ,
314
+ this . remoteStore ,
315
+ this . sharedClientState ,
316
+ this . initialUser ,
317
+ this . maxConcurrentLimboResolutions
278
318
) ;
279
319
}
280
320
}
0 commit comments