@@ -40,10 +40,15 @@ import { IndexFreeQueryEngine } from '../local/index_free_query_engine';
40
40
import { IndexedDbPersistence } from '../local/indexeddb_persistence' ;
41
41
import {
42
42
MemoryEagerDelegate ,
43
- MemoryPersistence ,
44
- MemoryReferenceDelegate
43
+ MemoryLruDelegate ,
44
+ MemoryPersistence
45
45
} from '../local/memory_persistence' ;
46
46
47
+ const MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE =
48
+ 'You are using the memory-only build of Firestore. Persistence support is ' +
49
+ 'only available via the @firebase/firestore bundle or the ' +
50
+ 'firebase-firestore.js build.' ;
51
+
47
52
export interface ComponentConfiguration {
48
53
asyncQueue : AsyncQueue ;
49
54
databaseInfo : DatabaseInfo ;
@@ -74,19 +79,52 @@ export interface ComponentProvider {
74
79
}
75
80
76
81
/**
77
- * Provides all components needed for Firestore with IndexedDB persistence.
82
+ * Provides all components needed for Firestore with in-memory persistence.
83
+ * Uses EagerGC garbage collection.
78
84
*/
79
- export class IndexedDbComponentProvider implements ComponentProvider {
80
- persistence ! : IndexedDbPersistence ;
85
+ export class MemoryComponentProvider {
86
+ persistence ! : Persistence ;
81
87
sharedClientState ! : SharedClientState ;
82
88
localStore ! : LocalStore ;
83
89
syncEngine ! : SyncEngine ;
84
- gcScheduler ! : GarbageCollectionScheduler ;
90
+ gcScheduler ! : GarbageCollectionScheduler | null ;
85
91
remoteStore ! : RemoteStore ;
86
92
eventManager ! : EventManager ;
87
93
88
- initialize ( cfg : ComponentConfiguration ) : Promise < void > {
89
- return initializeComponentProvider ( this , cfg ) ;
94
+ async initialize ( cfg : ComponentConfiguration ) : Promise < void > {
95
+ this . sharedClientState = this . createSharedClientState ( cfg ) ;
96
+ this . persistence = this . createPersistence ( cfg ) ;
97
+ await this . persistence . start ( ) ;
98
+ this . gcScheduler = this . createGarbageCollectionScheduler ( cfg ) ;
99
+ this . localStore = this . createLocalStore ( cfg ) ;
100
+ this . remoteStore = this . createRemoteStore ( cfg ) ;
101
+ this . syncEngine = this . createSyncEngine ( cfg ) ;
102
+ this . eventManager = this . createEventManager ( cfg ) ;
103
+
104
+ this . sharedClientState . onlineStateHandler = onlineState =>
105
+ this . syncEngine . applyOnlineStateChange (
106
+ onlineState ,
107
+ OnlineStateSource . SharedClientState
108
+ ) ;
109
+ this . remoteStore . syncEngine = this . syncEngine ;
110
+ this . sharedClientState . syncEngine = this . syncEngine ;
111
+
112
+ await this . sharedClientState . start ( ) ;
113
+ await this . remoteStore . start ( ) ;
114
+ await this . localStore . start ( ) ;
115
+
116
+ // NOTE: This will immediately call the listener, so we make sure to
117
+ // set it after localStore / remoteStore are started.
118
+ await this . persistence . setPrimaryStateListener ( async isPrimary => {
119
+ await this . syncEngine . applyPrimaryState ( isPrimary ) ;
120
+ if ( this . gcScheduler ) {
121
+ if ( isPrimary && ! this . gcScheduler . started ) {
122
+ this . gcScheduler . start ( this . localStore ) ;
123
+ } else if ( ! isPrimary ) {
124
+ this . gcScheduler . stop ( ) ;
125
+ }
126
+ }
127
+ } ) ;
90
128
}
91
129
92
130
createEventManager ( cfg : ComponentConfiguration ) : EventManager {
@@ -96,9 +134,7 @@ export class IndexedDbComponentProvider implements ComponentProvider {
96
134
createGarbageCollectionScheduler (
97
135
cfg : ComponentConfiguration
98
136
) : GarbageCollectionScheduler | null {
99
- const garbageCollector = this . persistence . referenceDelegate
100
- . garbageCollector ;
101
- return new LruScheduler ( garbageCollector , cfg . asyncQueue ) ;
137
+ return null ;
102
138
}
103
139
104
140
createLocalStore ( cfg : ComponentConfiguration ) : LocalStore {
@@ -111,26 +147,10 @@ export class IndexedDbComponentProvider implements ComponentProvider {
111
147
112
148
createPersistence ( cfg : ComponentConfiguration ) : Persistence {
113
149
debugAssert (
114
- cfg . persistenceSettings . durable ,
115
- 'Can only start durable persistence'
116
- ) ;
117
-
118
- const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
119
- cfg . databaseInfo
150
+ ! cfg . persistenceSettings . durable ,
151
+ 'Can only start memory persistence'
120
152
) ;
121
- const serializer = cfg . platform . newSerializer ( cfg . databaseInfo . databaseId ) ;
122
- return IndexedDbPersistence . createIndexedDbPersistence ( {
123
- allowTabSynchronization : cfg . persistenceSettings . synchronizeTabs ,
124
- persistenceKey,
125
- clientId : cfg . clientId ,
126
- platform : cfg . platform ,
127
- queue : cfg . asyncQueue ,
128
- serializer,
129
- lruParams : LruParams . withCacheSize (
130
- cfg . persistenceSettings . cacheSizeBytes
131
- ) ,
132
- sequenceNumberSyncer : this . sharedClientState
133
- } ) ;
153
+ return new MemoryPersistence ( cfg . clientId , MemoryEagerDelegate . factory ) ;
134
154
}
135
155
136
156
createRemoteStore ( cfg : ComponentConfiguration ) : RemoteStore {
@@ -148,29 +168,6 @@ export class IndexedDbComponentProvider implements ComponentProvider {
148
168
}
149
169
150
170
createSharedClientState ( cfg : ComponentConfiguration ) : SharedClientState {
151
- debugAssert (
152
- cfg . persistenceSettings . durable ,
153
- 'Can only start durable persistence'
154
- ) ;
155
-
156
- if ( cfg . persistenceSettings . synchronizeTabs ) {
157
- if ( ! WebStorageSharedClientState . isAvailable ( cfg . platform ) ) {
158
- throw new FirestoreError (
159
- Code . UNIMPLEMENTED ,
160
- 'IndexedDB persistence is only available on platforms that support LocalStorage.'
161
- ) ;
162
- }
163
- const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
164
- cfg . databaseInfo
165
- ) ;
166
- return new WebStorageSharedClientState (
167
- cfg . asyncQueue ,
168
- cfg . platform ,
169
- persistenceKey ,
170
- cfg . clientId ,
171
- cfg . initialUser
172
- ) ;
173
- }
174
171
return new MemorySharedClientState ( ) ;
175
172
}
176
173
@@ -185,137 +182,101 @@ export class IndexedDbComponentProvider implements ComponentProvider {
185
182
}
186
183
187
184
clearPersistence ( databaseInfo : DatabaseInfo ) : Promise < void > {
188
- const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
189
- databaseInfo
185
+ throw new FirestoreError (
186
+ Code . FAILED_PRECONDITION ,
187
+ MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE
190
188
) ;
191
- return IndexedDbPersistence . clearPersistence ( persistenceKey ) ;
192
189
}
193
190
}
194
191
195
- const MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE =
196
- 'You are using the memory-only build of Firestore. Persistence support is ' +
197
- 'only available via the @firebase/firestore bundle or the ' +
198
- 'firebase-firestore.js build.' ;
199
-
200
192
/**
201
193
* Provides all components needed for Firestore with in-memory persistence.
194
+ * Uses LRU garbage collection.
202
195
*/
203
- export class MemoryComponentProvider implements ComponentProvider {
204
- persistence ! : Persistence ;
205
- sharedClientState ! : SharedClientState ;
206
- localStore ! : LocalStore ;
207
- syncEngine ! : SyncEngine ;
208
- gcScheduler ! : null ;
209
- remoteStore ! : RemoteStore ;
210
- eventManager ! : EventManager ;
211
-
212
- constructor (
213
- readonly referenceDelegateFactory : (
214
- p : MemoryPersistence
215
- ) => MemoryReferenceDelegate = MemoryEagerDelegate . factory
216
- ) { }
217
-
218
- initialize ( cfg : ComponentConfiguration ) : Promise < void > {
219
- return initializeComponentProvider ( this , cfg ) ;
220
- }
221
-
222
- createEventManager ( cfg : ComponentConfiguration ) : EventManager {
223
- return new EventManager ( this . syncEngine ) ;
196
+ export class MemoryLruComponentProvider extends MemoryComponentProvider {
197
+ createPersistence ( cfg : ComponentConfiguration ) : Persistence {
198
+ debugAssert (
199
+ ! cfg . persistenceSettings . durable ,
200
+ 'Can only start memory persistence'
201
+ ) ;
202
+ return new MemoryPersistence (
203
+ cfg . clientId ,
204
+ p => new MemoryLruDelegate ( p , LruParams . DEFAULT )
205
+ ) ;
224
206
}
207
+ }
225
208
209
+ /**
210
+ * Provides all components needed for Firestore with IndexedDB persistence.
211
+ */
212
+ export class IndexedDbComponentProvider extends MemoryComponentProvider {
226
213
createGarbageCollectionScheduler (
227
214
cfg : ComponentConfiguration
228
215
) : GarbageCollectionScheduler | null {
229
- return null ;
230
- }
231
-
232
- createLocalStore ( cfg : ComponentConfiguration ) : LocalStore {
233
- return new LocalStore (
234
- this . persistence ,
235
- new IndexFreeQueryEngine ( ) ,
236
- cfg . initialUser
216
+ debugAssert (
217
+ this . persistence instanceof IndexedDbPersistence ,
218
+ 'IndexedDbComponentProvider should provide IndexedDBPersistence'
237
219
) ;
220
+ const garbageCollector = this . persistence . referenceDelegate
221
+ . garbageCollector ;
222
+ return new LruScheduler ( garbageCollector , cfg . asyncQueue ) ;
238
223
}
239
224
240
225
createPersistence ( cfg : ComponentConfiguration ) : Persistence {
241
226
debugAssert (
242
- ! cfg . persistenceSettings . durable ,
243
- 'Can only start memory persistence'
227
+ cfg . persistenceSettings . durable ,
228
+ 'Can only start durable persistence'
244
229
) ;
245
- return new MemoryPersistence ( cfg . clientId , this . referenceDelegateFactory ) ;
246
- }
247
230
248
- createRemoteStore ( cfg : ComponentConfiguration ) : RemoteStore {
249
- return new RemoteStore (
250
- this . localStore ,
251
- cfg . datastore ,
252
- cfg . asyncQueue ,
253
- onlineState =>
254
- this . syncEngine . applyOnlineStateChange (
255
- onlineState ,
256
- OnlineStateSource . RemoteStore
257
- ) ,
258
- cfg . platform . newConnectivityMonitor ( )
231
+ const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
232
+ cfg . databaseInfo
259
233
) ;
234
+ const serializer = cfg . platform . newSerializer ( cfg . databaseInfo . databaseId ) ;
235
+ return IndexedDbPersistence . createIndexedDbPersistence ( {
236
+ allowTabSynchronization : cfg . persistenceSettings . synchronizeTabs ,
237
+ persistenceKey,
238
+ clientId : cfg . clientId ,
239
+ platform : cfg . platform ,
240
+ queue : cfg . asyncQueue ,
241
+ serializer,
242
+ lruParams : LruParams . withCacheSize (
243
+ cfg . persistenceSettings . cacheSizeBytes
244
+ ) ,
245
+ sequenceNumberSyncer : this . sharedClientState
246
+ } ) ;
260
247
}
261
248
262
249
createSharedClientState ( cfg : ComponentConfiguration ) : SharedClientState {
263
- return new MemorySharedClientState ( ) ;
264
- }
265
-
266
- createSyncEngine ( cfg : ComponentConfiguration ) : SyncEngine {
267
- return new SyncEngine (
268
- this . localStore ,
269
- this . remoteStore ,
270
- this . sharedClientState ,
271
- cfg . initialUser ,
272
- cfg . maxConcurrentLimboResolutions
250
+ debugAssert (
251
+ cfg . persistenceSettings . durable ,
252
+ 'Can only start durable persistence'
273
253
) ;
274
- }
275
254
276
- clearPersistence ( ) : never {
277
- throw new FirestoreError (
278
- Code . FAILED_PRECONDITION ,
279
- MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE
280
- ) ;
255
+ if ( cfg . persistenceSettings . synchronizeTabs ) {
256
+ if ( ! WebStorageSharedClientState . isAvailable ( cfg . platform ) ) {
257
+ throw new FirestoreError (
258
+ Code . UNIMPLEMENTED ,
259
+ 'IndexedDB persistence is only available on platforms that support LocalStorage.'
260
+ ) ;
261
+ }
262
+ const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
263
+ cfg . databaseInfo
264
+ ) ;
265
+ return new WebStorageSharedClientState (
266
+ cfg . asyncQueue ,
267
+ cfg . platform ,
268
+ persistenceKey ,
269
+ cfg . clientId ,
270
+ cfg . initialUser
271
+ ) ;
272
+ }
273
+ return new MemorySharedClientState ( ) ;
281
274
}
282
- }
283
-
284
- async function initializeComponentProvider (
285
- target : MemoryComponentProvider | IndexedDbComponentProvider ,
286
- cfg : ComponentConfiguration
287
- ) : Promise < void > {
288
- target . sharedClientState = target . createSharedClientState ( cfg ) ;
289
- target . persistence = target . createPersistence ( cfg ) ;
290
- await target . persistence . start ( ) ;
291
- target . gcScheduler = target . createGarbageCollectionScheduler ( cfg ) ;
292
- target . localStore = target . createLocalStore ( cfg ) ;
293
- target . remoteStore = target . createRemoteStore ( cfg ) ;
294
- target . syncEngine = target . createSyncEngine ( cfg ) ;
295
- target . eventManager = target . createEventManager ( cfg ) ;
296
275
297
- target . sharedClientState . onlineStateHandler = onlineState =>
298
- target . syncEngine . applyOnlineStateChange (
299
- onlineState ,
300
- OnlineStateSource . SharedClientState
276
+ clearPersistence ( databaseInfo : DatabaseInfo ) : Promise < void > {
277
+ const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
278
+ databaseInfo
301
279
) ;
302
- target . remoteStore . syncEngine = target . syncEngine ;
303
- target . sharedClientState . syncEngine = target . syncEngine ;
304
-
305
- await target . sharedClientState . start ( ) ;
306
- await target . remoteStore . start ( ) ;
307
- await target . localStore . start ( ) ;
308
-
309
- // NOTE: This will immediately call the listener, so we make sure to
310
- // set it after localStore / remoteStore are started.
311
- await target . persistence . setPrimaryStateListener ( async isPrimary => {
312
- await target . syncEngine . applyPrimaryState ( isPrimary ) ;
313
- if ( target . gcScheduler ) {
314
- if ( isPrimary && ! target . gcScheduler . started ) {
315
- target . gcScheduler . start ( target . localStore ) ;
316
- } else if ( ! isPrimary ) {
317
- target . gcScheduler . stop ( ) ;
318
- }
319
- }
320
- } ) ;
280
+ return IndexedDbPersistence . clearPersistence ( persistenceKey ) ;
281
+ }
321
282
}
0 commit comments