@@ -40,10 +40,26 @@ 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
+
52
+ export interface ComponentConfiguration {
53
+ asyncQueue : AsyncQueue ;
54
+ databaseInfo : DatabaseInfo ;
55
+ platform : Platform ;
56
+ datastore : Datastore ;
57
+ clientId : ClientId ;
58
+ initialUser : User ;
59
+ maxConcurrentLimboResolutions : number ;
60
+ persistenceSettings : PersistenceSettings ;
61
+ }
62
+
47
63
/**
48
64
* Initializes and wires up all core components for Firestore. Implementations
49
65
* override `initialize()` to provide all components.
@@ -57,115 +73,39 @@ export interface ComponentProvider {
57
73
remoteStore : RemoteStore ;
58
74
eventManager : EventManager ;
59
75
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 > ;
76
+ initialize ( cfg : ComponentConfiguration ) : Promise < void > ;
70
77
71
78
clearPersistence ( databaseId : DatabaseInfo ) : Promise < void > ;
72
79
}
73
80
74
81
/**
75
- * 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.
76
84
*/
77
- export class IndexedDbComponentProvider implements ComponentProvider {
78
- persistence ! : IndexedDbPersistence ;
85
+ export class MemoryComponentProvider {
86
+ persistence ! : Persistence ;
79
87
sharedClientState ! : SharedClientState ;
80
88
localStore ! : LocalStore ;
81
89
syncEngine ! : SyncEngine ;
82
90
gcScheduler ! : GarbageCollectionScheduler | null ;
83
91
remoteStore ! : RemoteStore ;
84
92
eventManager ! : EventManager ;
85
93
86
- async initialize (
87
- asyncQueue : AsyncQueue ,
88
- databaseInfo : DatabaseInfo ,
89
- platform : Platform ,
90
- datastore : Datastore ,
91
- clientId : ClientId ,
92
- initialUser : User ,
93
- maxConcurrentLimboResolutions : number ,
94
- persistenceSettings : PersistenceSettings
95
- ) : Promise < void > {
96
- debugAssert (
97
- persistenceSettings . durable ,
98
- 'IndexedDbComponentProvider can only provide durable persistence'
99
- ) ;
100
- debugAssert ( ! this . sharedClientState , 'initialize() already called' ) ;
101
-
102
- const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
103
- databaseInfo
104
- ) ;
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 ) ;
105
103
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
- }
113
-
114
- this . sharedClientState = persistenceSettings . synchronizeTabs
115
- ? new WebStorageSharedClientState (
116
- asyncQueue ,
117
- platform ,
118
- persistenceKey ,
119
- clientId ,
120
- initialUser
121
- )
122
- : new MemorySharedClientState ( ) ;
123
104
this . sharedClientState . onlineStateHandler = onlineState =>
124
105
this . syncEngine . applyOnlineStateChange (
125
106
onlineState ,
126
107
OnlineStateSource . SharedClientState
127
108
) ;
128
-
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
138
- } ) ;
139
-
140
- const garbageCollector = this . persistence . referenceDelegate
141
- . garbageCollector ;
142
-
143
- this . gcScheduler = new LruScheduler ( garbageCollector , asyncQueue ) ;
144
- this . localStore = new LocalStore (
145
- this . persistence ,
146
- new IndexFreeQueryEngine ( ) ,
147
- initialUser
148
- ) ;
149
- this . remoteStore = new RemoteStore (
150
- this . localStore ,
151
- datastore ,
152
- asyncQueue ,
153
- onlineState =>
154
- this . syncEngine . applyOnlineStateChange (
155
- onlineState ,
156
- OnlineStateSource . RemoteStore
157
- ) ,
158
- platform . newConnectivityMonitor ( )
159
- ) ;
160
- this . syncEngine = new SyncEngine (
161
- this . localStore ,
162
- this . remoteStore ,
163
- this . sharedClientState ,
164
- initialUser ,
165
- maxConcurrentLimboResolutions
166
- ) ;
167
- this . eventManager = new EventManager ( this . syncEngine ) ;
168
-
169
109
this . remoteStore . syncEngine = this . syncEngine ;
170
110
this . sharedClientState . syncEngine = this . syncEngine ;
171
111
@@ -177,104 +117,166 @@ export class IndexedDbComponentProvider implements ComponentProvider {
177
117
// set it after localStore / remoteStore are started.
178
118
await this . persistence . setPrimaryStateListener ( async isPrimary => {
179
119
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 ( ) ;
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
+ }
184
126
}
185
127
} ) ;
186
128
}
187
129
188
- clearPersistence ( databaseInfo : DatabaseInfo ) : Promise < void > {
189
- const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
190
- databaseInfo
191
- ) ;
192
- return IndexedDbPersistence . clearPersistence ( persistenceKey ) ;
130
+ createEventManager ( cfg : ComponentConfiguration ) : EventManager {
131
+ return new EventManager ( this . syncEngine ) ;
193
132
}
194
- }
195
-
196
- const MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE =
197
- 'You are using the memory-only build of Firestore. Persistence support is ' +
198
- 'only available via the @firebase/firestore bundle or the ' +
199
- 'firebase-firestore.js build.' ;
200
-
201
- /**
202
- * Provides all components needed for Firestore with in-memory persistence.
203
- */
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
-
213
- constructor (
214
- readonly referenceDelegateFactory : (
215
- p : MemoryPersistence
216
- ) => MemoryReferenceDelegate = MemoryEagerDelegate . factory
217
- ) { }
218
133
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
- }
134
+ createGarbageCollectionScheduler (
135
+ cfg : ComponentConfiguration
136
+ ) : GarbageCollectionScheduler | null {
137
+ return null ;
138
+ }
235
139
236
- this . persistence = new MemoryPersistence (
237
- clientId ,
238
- this . referenceDelegateFactory
239
- ) ;
240
- this . gcScheduler = null ;
241
- this . sharedClientState = new MemorySharedClientState ( ) ;
242
- this . localStore = new LocalStore (
140
+ createLocalStore ( cfg : ComponentConfiguration ) : LocalStore {
141
+ return new LocalStore (
243
142
this . persistence ,
244
143
new IndexFreeQueryEngine ( ) ,
245
- initialUser
144
+ cfg . initialUser
246
145
) ;
247
- this . remoteStore = new RemoteStore (
146
+ }
147
+
148
+ createPersistence ( cfg : ComponentConfiguration ) : Persistence {
149
+ debugAssert (
150
+ ! cfg . persistenceSettings . durable ,
151
+ 'Can only start memory persistence'
152
+ ) ;
153
+ return new MemoryPersistence ( cfg . clientId , MemoryEagerDelegate . factory ) ;
154
+ }
155
+
156
+ createRemoteStore ( cfg : ComponentConfiguration ) : RemoteStore {
157
+ return new RemoteStore (
248
158
this . localStore ,
249
- datastore ,
250
- asyncQueue ,
159
+ cfg . datastore ,
160
+ cfg . asyncQueue ,
251
161
onlineState =>
252
162
this . syncEngine . applyOnlineStateChange (
253
163
onlineState ,
254
164
OnlineStateSource . RemoteStore
255
165
) ,
256
- platform . newConnectivityMonitor ( )
166
+ cfg . platform . newConnectivityMonitor ( )
257
167
) ;
258
- this . syncEngine = new SyncEngine (
168
+ }
169
+
170
+ createSharedClientState ( cfg : ComponentConfiguration ) : SharedClientState {
171
+ return new MemorySharedClientState ( ) ;
172
+ }
173
+
174
+ createSyncEngine ( cfg : ComponentConfiguration ) : SyncEngine {
175
+ return new SyncEngine (
259
176
this . localStore ,
260
177
this . remoteStore ,
261
178
this . sharedClientState ,
262
- initialUser ,
263
- maxConcurrentLimboResolutions
179
+ cfg . initialUser ,
180
+ cfg . maxConcurrentLimboResolutions
264
181
) ;
265
- this . eventManager = new EventManager ( this . syncEngine ) ;
266
-
267
- this . remoteStore . syncEngine = this . syncEngine ;
268
-
269
- await this . remoteStore . start ( ) ;
270
- await this . remoteStore . applyPrimaryState ( true ) ;
271
- await this . syncEngine . applyPrimaryState ( true ) ;
272
182
}
273
183
274
- clearPersistence ( ) : never {
184
+ clearPersistence ( databaseInfo : DatabaseInfo ) : Promise < void > {
275
185
throw new FirestoreError (
276
186
Code . FAILED_PRECONDITION ,
277
187
MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE
278
188
) ;
279
189
}
280
190
}
191
+
192
+ /**
193
+ * Provides all components needed for Firestore with in-memory persistence.
194
+ * Uses LRU garbage collection.
195
+ */
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
+ ) ;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Provides all components needed for Firestore with IndexedDB persistence.
211
+ */
212
+ export class IndexedDbComponentProvider extends MemoryComponentProvider {
213
+ createGarbageCollectionScheduler (
214
+ cfg : ComponentConfiguration
215
+ ) : GarbageCollectionScheduler | null {
216
+ debugAssert (
217
+ this . persistence instanceof IndexedDbPersistence ,
218
+ 'IndexedDbComponentProvider should provide IndexedDBPersistence'
219
+ ) ;
220
+ const garbageCollector = this . persistence . referenceDelegate
221
+ . garbageCollector ;
222
+ return new LruScheduler ( garbageCollector , cfg . asyncQueue ) ;
223
+ }
224
+
225
+ createPersistence ( cfg : ComponentConfiguration ) : Persistence {
226
+ debugAssert (
227
+ cfg . persistenceSettings . durable ,
228
+ 'Can only start durable persistence'
229
+ ) ;
230
+
231
+ const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
232
+ cfg . databaseInfo
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
+ } ) ;
247
+ }
248
+
249
+ createSharedClientState ( cfg : ComponentConfiguration ) : SharedClientState {
250
+ debugAssert (
251
+ cfg . persistenceSettings . durable ,
252
+ 'Can only start durable persistence'
253
+ ) ;
254
+
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 ( ) ;
274
+ }
275
+
276
+ clearPersistence ( databaseInfo : DatabaseInfo ) : Promise < void > {
277
+ const persistenceKey = IndexedDbPersistence . buildStoragePrefix (
278
+ databaseInfo
279
+ ) ;
280
+ return IndexedDbPersistence . clearPersistence ( persistenceKey ) ;
281
+ }
282
+ }
0 commit comments