Skip to content

Commit 6b62a5b

Browse files
Removing held write batch handling from LocalStore (#1997)
1 parent 6791505 commit 6b62a5b

File tree

3 files changed

+11
-125
lines changed

3 files changed

+11
-125
lines changed

Firestore/Example/Tests/Core/FSTViewTests.mm

+1-2
Original file line numberDiff line numberDiff line change
@@ -601,8 +601,7 @@ - (void)testRemovesKeysFromMutatedKeysWhenNewDocHasNoLocalChanges {
601601
[view applyChangesToDocuments:changes];
602602
XCTAssertEqual(changes.mutatedKeys, (DocumentKeySet{doc2.key}));
603603

604-
FSTDocument *doc2Prime =
605-
FSTTestDoc("rooms/eros/messages/1", 0, @{}, FSTDocumentStateSynced);
604+
FSTDocument *doc2Prime = FSTTestDoc("rooms/eros/messages/1", 0, @{}, FSTDocumentStateSynced);
606605
changes = [view computeChangesWithDocuments:FSTTestDocUpdates(@[ doc2Prime ])];
607606
[view applyChangesToDocuments:changes];
608607
XCTAssertEqual(changes.mutatedKeys, DocumentKeySet{});

Firestore/Source/Local/FSTLocalStore.mm

+10-122
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,6 @@ @interface FSTLocalStore ()
8686
/** Maps a targetID to data about its query. */
8787
@property(nonatomic, strong) NSMutableDictionary<NSNumber *, FSTQueryData *> *targetIDs;
8888

89-
/**
90-
* A heldBatchResult is a mutation batch result (from a write acknowledgement) that arrived before
91-
* the watch stream got notified of a snapshot that includes the write.  So we "hold" it until
92-
* the watch stream catches up. It ensures that the local write remains visible (latency
93-
* compensation) and doesn't temporarily appear reverted because the watch stream is slower than
94-
* the write stream and so wasn't reflecting it.
95-
*
96-
* NOTE: Eventually we want to move this functionality into the remote store.
97-
*/
98-
@property(nonatomic, strong) NSMutableArray<FSTMutationBatchResult *> *heldBatchResults;
99-
10089
@end
10190

10291
@implementation FSTLocalStore {
@@ -117,7 +106,6 @@ - (instancetype)initWithPersistence:(id<FSTPersistence>)persistence
117106
[_persistence.referenceDelegate addInMemoryPins:_localViewReferences];
118107

119108
_targetIDs = [NSMutableDictionary dictionary];
120-
_heldBatchResults = [NSMutableArray array];
121109

122110
_targetIDGenerator = TargetIdGenerator::LocalStoreTargetIdGenerator(0);
123111
}
@@ -131,27 +119,7 @@ - (void)start {
131119
}
132120

133121
- (void)startMutationQueue {
134-
self.persistence.run("Start MutationQueue", [&]() {
135-
[self.mutationQueue start];
136-
137-
// If we have any leftover mutation batch results from a prior run, just drop them.
138-
// TODO(http://b/33446471): We probably need to repopulate heldBatchResults or similar instead,
139-
// but that is not straightforward since we're not persisting the write ack versions.
140-
[self.heldBatchResults removeAllObjects];
141-
142-
// TODO(mikelehen): This is the only usage of getAllMutationBatchesThroughBatchId:. Consider
143-
// removing it in favor of a getAcknowledgedBatches method.
144-
BatchId highestAck = [self.mutationQueue highestAcknowledgedBatchID];
145-
if (highestAck != kFSTBatchIDUnknown) {
146-
NSArray<FSTMutationBatch *> *batches =
147-
[self.mutationQueue allMutationBatchesThroughBatchID:highestAck];
148-
if (batches.count > 0) {
149-
// NOTE: This could be more efficient if we had a removeBatchesThroughBatchID, but this set
150-
// should be very small and this code should go away eventually.
151-
[self removeMutationBatches:batches];
152-
}
153-
}
154-
});
122+
self.persistence.run("Start MutationQueue", [&]() { [self.mutationQueue start]; });
155123
}
156124

157125
- (FSTMaybeDocumentDictionary *)userDidChange:(const User &)user {
@@ -202,18 +170,12 @@ - (FSTMaybeDocumentDictionary *)acknowledgeBatchWithResult:(FSTMutationBatchResu
202170
return self.persistence.run("Acknowledge batch", [&]() -> FSTMaybeDocumentDictionary * {
203171
id<FSTMutationQueue> mutationQueue = self.mutationQueue;
204172

205-
[mutationQueue acknowledgeBatch:batchResult.batch streamToken:batchResult.streamToken];
206-
207-
DocumentKeySet affected;
208-
if ([self shouldHoldBatchResultWithVersion:batchResult.commitVersion]) {
209-
[self.heldBatchResults addObject:batchResult];
210-
} else {
211-
affected = [self releaseBatchResults:@[ batchResult ]];
212-
}
213-
173+
FSTMutationBatch *batch = batchResult.batch;
174+
[mutationQueue acknowledgeBatch:batch streamToken:batchResult.streamToken];
175+
[self applyBatchResult:batchResult];
214176
[self.mutationQueue performConsistencyCheck];
215177

216-
return [self.localDocuments documentsForKeys:affected];
178+
return [self.localDocuments documentsForKeys:batch.keys];
217179
});
218180
}
219181

@@ -225,11 +187,10 @@ - (FSTMaybeDocumentDictionary *)rejectBatchID:(BatchId)batchID {
225187
BatchId lastAcked = [self.mutationQueue highestAcknowledgedBatchID];
226188
HARD_ASSERT(batchID > lastAcked, "Acknowledged batches can't be rejected.");
227189

228-
DocumentKeySet affected = [self removeMutationBatch:toReject];
229-
190+
[self.mutationQueue removeMutationBatch:toReject];
230191
[self.mutationQueue performConsistencyCheck];
231192

232-
return [self.localDocuments documentsForKeys:affected];
193+
return [self.localDocuments documentsForKeys:toReject.keys];
233194
});
234195
}
235196

@@ -341,15 +302,7 @@ - (FSTMaybeDocumentDictionary *)applyRemoteEvent:(FSTRemoteEvent *)remoteEvent {
341302
[self.queryCache setLastRemoteSnapshotVersion:remoteVersion];
342303
}
343304

344-
DocumentKeySet releasedWriteKeys = [self releaseHeldBatchResults];
345-
346-
// Union the two key sets.
347-
DocumentKeySet keysToRecalc = changedDocKeys;
348-
for (const DocumentKey &key : releasedWriteKeys) {
349-
keysToRecalc = keysToRecalc.insert(key);
350-
}
351-
352-
return [self.localDocuments documentsForKeys:keysToRecalc];
305+
return [self.localDocuments documentsForKeys:changedDocKeys];
353306
});
354307
}
355308

@@ -458,12 +411,6 @@ - (void)releaseQuery:(FSTQuery *)query {
458411
[self.localViewReferences removeReferencesForID:targetID];
459412
[self.targetIDs removeObjectForKey:boxedTargetID];
460413
[self.persistence.referenceDelegate removeTarget:queryData];
461-
462-
// If this was the last watch target, then we won't get any more watch snapshots, so we should
463-
// release any held batch results.
464-
if ([self.targetIDs count] == 0) {
465-
[self releaseHeldBatchResults];
466-
}
467414
});
468415
}
469416

@@ -479,67 +426,6 @@ - (DocumentKeySet)remoteDocumentKeysForTarget:(TargetId)targetID {
479426
});
480427
}
481428

482-
/**
483-
* Releases all the held mutation batches up to the current remote version received, and
484-
* applies their mutations to the docs in the remote documents cache.
485-
*
486-
* @return the set of keys of docs that were modified by those writes.
487-
*/
488-
- (DocumentKeySet)releaseHeldBatchResults {
489-
NSMutableArray<FSTMutationBatchResult *> *toRelease = [NSMutableArray array];
490-
for (FSTMutationBatchResult *batchResult in self.heldBatchResults) {
491-
if (![self isRemoteUpToVersion:batchResult.commitVersion]) {
492-
break;
493-
}
494-
[toRelease addObject:batchResult];
495-
}
496-
497-
if (toRelease.count == 0) {
498-
return DocumentKeySet{};
499-
} else {
500-
[self.heldBatchResults removeObjectsInRange:NSMakeRange(0, toRelease.count)];
501-
return [self releaseBatchResults:toRelease];
502-
}
503-
}
504-
505-
- (BOOL)isRemoteUpToVersion:(const SnapshotVersion &)version {
506-
// If there are no watch targets, then we won't get remote snapshots, and are always "up-to-date."
507-
return version <= self.queryCache.lastRemoteSnapshotVersion || self.targetIDs.count == 0;
508-
}
509-
510-
- (BOOL)shouldHoldBatchResultWithVersion:(const SnapshotVersion &)version {
511-
// Check if watcher isn't up to date or prior results are already held.
512-
return ![self isRemoteUpToVersion:version] || self.heldBatchResults.count > 0;
513-
}
514-
515-
- (DocumentKeySet)releaseBatchResults:(NSArray<FSTMutationBatchResult *> *)batchResults {
516-
NSMutableArray<FSTMutationBatch *> *batches = [NSMutableArray array];
517-
for (FSTMutationBatchResult *batchResult in batchResults) {
518-
[self applyBatchResult:batchResult];
519-
[batches addObject:batchResult.batch];
520-
}
521-
522-
return [self removeMutationBatches:batches];
523-
}
524-
525-
- (DocumentKeySet)removeMutationBatch:(FSTMutationBatch *)batch {
526-
return [self removeMutationBatches:@[ batch ]];
527-
}
528-
529-
/** Removes all the mutation batches named in the given array. */
530-
- (DocumentKeySet)removeMutationBatches:(NSArray<FSTMutationBatch *> *)batches {
531-
DocumentKeySet affectedDocs;
532-
for (FSTMutationBatch *batch in batches) {
533-
for (FSTMutation *mutation in batch.mutations) {
534-
const DocumentKey &key = mutation.key;
535-
affectedDocs = affectedDocs.insert(key);
536-
}
537-
[self.mutationQueue removeMutationBatch:batch];
538-
}
539-
540-
return affectedDocs;
541-
}
542-
543429
- (void)applyBatchResult:(FSTMutationBatchResult *)batchResult {
544430
FSTMutationBatch *batch = batchResult.batch;
545431
DocumentKeySet docKeys = batch.keys;
@@ -562,6 +448,8 @@ - (void)applyBatchResult:(FSTMutationBatchResult *)batchResult {
562448
}
563449
}
564450
}
451+
452+
[self.mutationQueue removeMutationBatch:batch];
565453
}
566454

567455
@end

Firestore/Source/Model/FSTDocument.mm

-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ + (instancetype)documentWithKey:(DocumentKey)key
163163
return deletedDocument;
164164
}
165165

166-
167166
- (BOOL)hasCommittedMutations {
168167
return _hasCommittedMutations;
169168
}

0 commit comments

Comments
 (0)