@@ -37,7 +37,7 @@ import {
37
37
MutationBatchResult
38
38
} from '../model/mutation_batch' ;
39
39
import { RemoteEvent , TargetChange } from '../remote/remote_event' ;
40
- import { hardAssert , debugAssert } from '../util/assert' ;
40
+ import { debugAssert , hardAssert } from '../util/assert' ;
41
41
import { Code , FirestoreError } from '../util/error' ;
42
42
import { logDebug } from '../util/log' ;
43
43
import { primitiveComparator } from '../util/misc' ;
@@ -139,7 +139,142 @@ export interface QueryResult {
139
139
* (unexpected) failure (e.g. failed assert) and always represent an
140
140
* unrecoverable error (should be caught / reported by the async_queue).
141
141
*/
142
- export class LocalStore {
142
+ export interface LocalStore {
143
+ /** Starts the LocalStore. */
144
+ start ( ) : Promise < void > ;
145
+
146
+ /**
147
+ * Tells the LocalStore that the currently authenticated user has changed.
148
+ *
149
+ * In response the local store switches the mutation queue to the new user and
150
+ * returns any resulting document changes.
151
+ */
152
+ // PORTING NOTE: Android and iOS only return the documents affected by the
153
+ // change.
154
+ handleUserChange ( user : User ) : Promise < UserChangeResult > ;
155
+
156
+ localWrite ( mutations : Mutation [ ] ) : Promise < LocalWriteResult > ;
157
+
158
+ /**
159
+ * Acknowledge the given batch.
160
+ *
161
+ * On the happy path when a batch is acknowledged, the local store will
162
+ *
163
+ * + remove the batch from the mutation queue;
164
+ * + apply the changes to the remote document cache;
165
+ * + recalculate the latency compensated view implied by those changes (there
166
+ * may be mutations in the queue that affect the documents but haven't been
167
+ * acknowledged yet); and
168
+ * + give the changed documents back the sync engine
169
+ *
170
+ * @returns The resulting (modified) documents.
171
+ */
172
+ acknowledgeBatch ( batchResult : MutationBatchResult ) : Promise < MaybeDocumentMap > ;
173
+
174
+ /**
175
+ * Remove mutations from the MutationQueue for the specified batch;
176
+ * LocalDocuments will be recalculated.
177
+ *
178
+ * @returns The resulting modified documents.
179
+ */
180
+ rejectBatch ( batchId : BatchId ) : Promise < MaybeDocumentMap > ;
181
+
182
+ /**
183
+ * Returns the largest (latest) batch id in mutation queue that is pending server response.
184
+ * Returns `BATCHID_UNKNOWN` if the queue is empty.
185
+ */
186
+ getHighestUnacknowledgedBatchId ( ) : Promise < BatchId > ;
187
+
188
+ /**
189
+ * Returns the last consistent snapshot processed (used by the RemoteStore to
190
+ * determine whether to buffer incoming snapshots from the backend).
191
+ */
192
+ getLastRemoteSnapshotVersion ( ) : Promise < SnapshotVersion > ;
193
+
194
+ /**
195
+ * Update the "ground-state" (remote) documents. We assume that the remote
196
+ * event reflects any write batches that have been acknowledged or rejected
197
+ * (i.e. we do not re-apply local mutations to updates from this event).
198
+ *
199
+ * LocalDocuments are re-calculated if there are remaining mutations in the
200
+ * queue.
201
+ */
202
+ applyRemoteEvent ( remoteEvent : RemoteEvent ) : Promise < MaybeDocumentMap > ;
203
+
204
+ /**
205
+ * Notify local store of the changed views to locally pin documents.
206
+ */
207
+ notifyLocalViewChanges ( viewChanges : LocalViewChanges [ ] ) : Promise < void > ;
208
+
209
+ /**
210
+ * Gets the mutation batch after the passed in batchId in the mutation queue
211
+ * or null if empty.
212
+ * @param afterBatchId If provided, the batch to search after.
213
+ * @returns The next mutation or null if there wasn't one.
214
+ */
215
+ nextMutationBatch ( afterBatchId ?: BatchId ) : Promise < MutationBatch | null > ;
216
+
217
+ /**
218
+ * Read the current value of a Document with a given key or null if not
219
+ * found - used for testing.
220
+ */
221
+ readDocument ( key : DocumentKey ) : Promise < MaybeDocument | null > ;
222
+
223
+ /**
224
+ * Assigns the given target an internal ID so that its results can be pinned so
225
+ * they don't get GC'd. A target must be allocated in the local store before
226
+ * the store can be used to manage its view.
227
+ *
228
+ * Allocating an already allocated `Target` will return the existing `TargetData`
229
+ * for that `Target`.
230
+ */
231
+ allocateTarget ( target : Target ) : Promise < TargetData > ;
232
+
233
+ /**
234
+ * Returns the TargetData as seen by the LocalStore, including updates that may
235
+ * have not yet been persisted to the TargetCache.
236
+ */
237
+ // Visible for testing.
238
+ getTargetData (
239
+ transaction : PersistenceTransaction ,
240
+ target : Target
241
+ ) : PersistencePromise < TargetData | null > ;
242
+
243
+ /**
244
+ * Unpin all the documents associated with the given target. If
245
+ * `keepPersistedTargetData` is set to false and Eager GC enabled, the method
246
+ * directly removes the associated target data from the target cache.
247
+ *
248
+ * Releasing a non-existing `Target` is a no-op.
249
+ */
250
+ // PORTING NOTE: `keepPersistedTargetData` is multi-tab only.
251
+ releaseTarget (
252
+ targetId : number ,
253
+ keepPersistedTargetData : boolean
254
+ ) : Promise < void > ;
255
+
256
+ /**
257
+ * Runs the specified query against the local store and returns the results,
258
+ * potentially taking advantage of query data from previous executions (such
259
+ * as the set of remote keys).
260
+ *
261
+ * @param usePreviousResults Whether results from previous executions can
262
+ * be used to optimize this query execution.
263
+ */
264
+ executeQuery ( query : Query , usePreviousResults : boolean ) : Promise < QueryResult > ;
265
+
266
+ collectGarbage ( garbageCollector : LruGarbageCollector ) : Promise < LruResults > ;
267
+ }
268
+
269
+ /**
270
+ * Implements `LocalStore` interface.
271
+ *
272
+ * Note: some field defined in this class might have public access level, but
273
+ * the class is not exported so they are only accessible from this file. This is
274
+ * useful to implement optional features (like bundles) in free functions, such
275
+ * that they are tree-shakeable.
276
+ */
277
+ class LocalStoreImpl implements LocalStore {
143
278
/**
144
279
* The maximum time to leave a resume token buffered without writing it out.
145
280
* This value is arbitrary: it's long enough to avoid several writes
@@ -502,7 +637,7 @@ export class LocalStore {
502
637
// Update the target data if there are target changes (or if
503
638
// sufficient time has passed since the last update).
504
639
if (
505
- LocalStore . shouldPersistTargetData (
640
+ LocalStoreImpl . shouldPersistTargetData (
506
641
oldTargetData ,
507
642
newTargetData ,
508
643
change
@@ -979,12 +1114,59 @@ export class LocalStore {
979
1114
}
980
1115
}
981
1116
1117
+ export function newLocalStore (
1118
+ /** Manages our in-memory or durable persistence. */
1119
+ persistence : Persistence ,
1120
+ queryEngine : QueryEngine ,
1121
+ initialUser : User
1122
+ ) : LocalStore {
1123
+ return new LocalStoreImpl ( persistence , queryEngine , initialUser ) ;
1124
+ }
1125
+
1126
+ /**
1127
+ * An interface on top of LocalStore that provides additional functionality
1128
+ * for MultiTabSyncEngine.
1129
+ */
1130
+ export interface MultiTabLocalStore extends LocalStore {
1131
+ /** Returns the local view of the documents affected by a mutation batch. */
1132
+ lookupMutationDocuments ( batchId : BatchId ) : Promise < MaybeDocumentMap | null > ;
1133
+
1134
+ removeCachedMutationBatchMetadata ( batchId : BatchId ) : void ;
1135
+
1136
+ setNetworkEnabled ( networkEnabled : boolean ) : void ;
1137
+
1138
+ getActiveClients ( ) : Promise < ClientId [ ] > ;
1139
+
1140
+ getTarget ( targetId : TargetId ) : Promise < Target | null > ;
1141
+
1142
+ /**
1143
+ * Returns the set of documents that have been updated since the last call.
1144
+ * If this is the first call, returns the set of changes since client
1145
+ * initialization. Further invocations will return document changes since
1146
+ * the point of rejection.
1147
+ */
1148
+ getNewDocumentChanges ( ) : Promise < MaybeDocumentMap > ;
1149
+
1150
+ /**
1151
+ * Reads the newest document change from persistence and forwards the internal
1152
+ * synchronization marker so that calls to `getNewDocumentChanges()`
1153
+ * only return changes that happened after client initialization.
1154
+ */
1155
+ synchronizeLastDocumentChangeReadTime ( ) : Promise < void > ;
1156
+ }
1157
+
982
1158
/**
983
1159
* An implementation of LocalStore that provides additional functionality
984
1160
* for MultiTabSyncEngine.
1161
+ *
1162
+ * Note: some field defined in this class might have public access level, but
1163
+ * the class is not exported so they are only accessible from this file. This is
1164
+ * useful to implement optional features (like bundles) in free functions, such
1165
+ * that they are tree-shakeable.
985
1166
*/
986
1167
// PORTING NOTE: Web only.
987
- export class MultiTabLocalStore extends LocalStore {
1168
+ class MultiTabLocalStoreImpl extends LocalStoreImpl
1169
+ implements MultiTabLocalStore {
988
1170
protected mutationQueue : IndexedDbMutationQueue ;
989
1171
protected remoteDocuments : IndexedDbRemoteDocumentCache ;
990
1172
protected targetCache : IndexedDbTargetCache ;
@@ -1092,6 +1274,15 @@ export class MultiTabLocalStore extends LocalStore {
1092
1274
}
1093
1275
}
1094
1276
1277
+ export function newMultiTabLocalStore (
1278
+ /** Manages our in-memory or durable persistence. */
1279
+ persistence : IndexedDbPersistence ,
1280
+ queryEngine : QueryEngine ,
1281
+ initialUser : User
1282
+ ) : MultiTabLocalStore {
1283
+ return new MultiTabLocalStoreImpl ( persistence , queryEngine , initialUser ) ;
1284
+ }
1285
+
1095
1286
/**
1096
1287
* Verifies the error thrown by a LocalStore operation. If a LocalStore
1097
1288
* operation fails because the primary lease has been taken by another client,
0 commit comments