Skip to content

Commit a52abec

Browse files
authored
Stop persisting last acknowledged batch ID (#2243)
After #2029, acknowledged batches are always immediately removed, so persisting the last acknowledged batch ID is no longer necessary.
1 parent 09e49e8 commit a52abec

File tree

9 files changed

+60
-110
lines changed

9 files changed

+60
-110
lines changed

Firestore/Example/Tests/Local/FSTMutationQueueTests.mm

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131
#include "Firestore/core/src/firebase/firestore/auth/user.h"
3232
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
3333
#include "Firestore/core/src/firebase/firestore/model/document_key_set.h"
34+
#include "Firestore/core/src/firebase/firestore/model/mutation_batch.h"
3435
#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
3536

3637
namespace testutil = firebase::firestore::testutil;
3738
using firebase::firestore::auth::User;
3839
using firebase::firestore::model::DocumentKey;
3940
using firebase::firestore::model::DocumentKeySet;
41+
using firebase::firestore::model::kBatchIdUnknown;
4042
using firebase::firestore::testutil::Key;
4143

4244
NS_ASSUME_NONNULL_BEGIN
@@ -83,32 +85,30 @@ - (void)testCountBatches {
8385
- (void)testAcknowledgeBatchID {
8486
if ([self isTestBaseClass]) return;
8587

86-
// Initial state of an empty queue
87-
XCTAssertEqual([self.mutationQueue highestAcknowledgedBatchID], kFSTBatchIDUnknown);
88-
89-
// Adding mutation batches should not change the highest acked batchID.
9088
self.persistence.run("testAcknowledgeBatchID", [&]() {
89+
XCTAssertEqual([self batchCount], 0);
90+
9191
FSTMutationBatch *batch1 = [self addMutationBatch];
9292
FSTMutationBatch *batch2 = [self addMutationBatch];
9393
FSTMutationBatch *batch3 = [self addMutationBatch];
94-
XCTAssertGreaterThan(batch1.batchID, kFSTBatchIDUnknown);
94+
XCTAssertGreaterThan(batch1.batchID, kBatchIdUnknown);
9595
XCTAssertGreaterThan(batch2.batchID, batch1.batchID);
9696
XCTAssertGreaterThan(batch3.batchID, batch2.batchID);
9797

98-
XCTAssertEqual([self.mutationQueue highestAcknowledgedBatchID], kFSTBatchIDUnknown);
98+
XCTAssertEqual([self batchCount], 3);
9999

100100
[self.mutationQueue acknowledgeBatch:batch1 streamToken:nil];
101101
[self.mutationQueue removeMutationBatch:batch1];
102+
XCTAssertEqual([self batchCount], 2);
102103

103104
[self.mutationQueue acknowledgeBatch:batch2 streamToken:nil];
104-
XCTAssertEqual([self.mutationQueue highestAcknowledgedBatchID], batch2.batchID);
105+
XCTAssertEqual([self batchCount], 2);
105106

106107
[self.mutationQueue removeMutationBatch:batch2];
107-
XCTAssertEqual([self.mutationQueue highestAcknowledgedBatchID], batch2.batchID);
108+
XCTAssertEqual([self batchCount], 1);
108109

109-
// Batch 3 never acknowledged.
110110
[self.mutationQueue removeMutationBatch:batch3];
111-
XCTAssertEqual([self.mutationQueue highestAcknowledgedBatchID], batch2.batchID);
111+
XCTAssertEqual([self batchCount], 0);
112112
});
113113
}
114114

@@ -122,7 +122,6 @@ - (void)testAcknowledgeThenRemove {
122122
[self.mutationQueue removeMutationBatch:batch1];
123123

124124
XCTAssertEqual([self batchCount], 0);
125-
XCTAssertEqual([self.mutationQueue highestAcknowledgedBatchID], batch1.batchID);
126125
});
127126
}
128127

@@ -186,28 +185,6 @@ - (void)testNextMutationBatchAfterBatchID {
186185
});
187186
}
188187

189-
- (void)testNextMutationBatchAfterBatchIDSkipsAcknowledgedBatches {
190-
if ([self isTestBaseClass]) return;
191-
192-
NSMutableArray<FSTMutationBatch *> *batches = self.persistence.run(
193-
"testNextMutationBatchAfterBatchIDSkipsAcknowledgedBatches newBatches",
194-
[&]() -> NSMutableArray<FSTMutationBatch *> * {
195-
NSMutableArray<FSTMutationBatch *> *newBatches = [self createBatches:3];
196-
XCTAssertEqualObjects([self.mutationQueue nextMutationBatchAfterBatchID:kFSTBatchIDUnknown],
197-
newBatches[0]);
198-
return newBatches;
199-
});
200-
self.persistence.run("testNextMutationBatchAfterBatchIDSkipsAcknowledgedBatches", [&]() {
201-
[self.mutationQueue acknowledgeBatch:batches[0] streamToken:nil];
202-
XCTAssertEqualObjects([self.mutationQueue nextMutationBatchAfterBatchID:kFSTBatchIDUnknown],
203-
batches[1]);
204-
XCTAssertEqualObjects([self.mutationQueue nextMutationBatchAfterBatchID:batches[0].batchID],
205-
batches[1]);
206-
XCTAssertEqualObjects([self.mutationQueue nextMutationBatchAfterBatchID:batches[1].batchID],
207-
batches[2]);
208-
});
209-
}
210-
211188
- (void)testAllMutationBatchesAffectingDocumentKey {
212189
if ([self isTestBaseClass]) return;
213190

@@ -406,7 +383,6 @@ - (void)testStreamToken {
406383
XCTAssertEqualObjects([self.mutationQueue lastStreamToken], streamToken1);
407384

408385
[self.mutationQueue acknowledgeBatch:batch1 streamToken:streamToken2];
409-
XCTAssertEqual(self.mutationQueue.highestAcknowledgedBatchID, batch1.batchID);
410386
XCTAssertEqualObjects([self.mutationQueue lastStreamToken], streamToken2);
411387
});
412388
}

Firestore/Source/Local/FSTLevelDBMutationQueue.mm

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "Firestore/core/src/firebase/firestore/local/leveldb_key.h"
3434
#include "Firestore/core/src/firebase/firestore/local/leveldb_transaction.h"
3535
#include "Firestore/core/src/firebase/firestore/local/leveldb_util.h"
36+
#include "Firestore/core/src/firebase/firestore/model/mutation_batch.h"
3637
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
3738
#include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
3839
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
@@ -52,6 +53,7 @@
5253
using firebase::firestore::local::LevelDbTransaction;
5354
using firebase::firestore::local::MakeStringView;
5455
using firebase::firestore::model::BatchId;
56+
using firebase::firestore::model::kBatchIdUnknown;
5557
using firebase::firestore::model::DocumentKey;
5658
using firebase::firestore::model::DocumentKeySet;
5759
using firebase::firestore::model::ResourcePath;
@@ -115,31 +117,13 @@ - (instancetype)initWithUserID:(std::string)userID
115117
}
116118

117119
- (void)start {
118-
BatchId nextBatchID = [FSTLevelDBMutationQueue loadNextBatchIDFromDB:_db.ptr];
120+
self.nextBatchID = [FSTLevelDBMutationQueue loadNextBatchIDFromDB:_db.ptr];
119121

120-
// On restart, nextBatchId may end up lower than lastAcknowledgedBatchId since it's computed from
121-
// the queue contents, and there may be no mutations in the queue. In this case, we need to reset
122-
// lastAcknowledgedBatchId (which is safe since the queue must be empty).
123122
std::string key = [self keyForCurrentMutationQueue];
124123
FSTPBMutationQueue *metadata = [self metadataForKey:key];
125124
if (!metadata) {
126125
metadata = [FSTPBMutationQueue message];
127-
128-
// proto3's default value for lastAcknowledgedBatchId is zero, but that would consider the first
129-
// entry in the queue to be acknowledged without that acknowledgement actually happening.
130-
metadata.lastAcknowledgedBatchId = kFSTBatchIDUnknown;
131-
} else {
132-
BatchId lastAcked = metadata.lastAcknowledgedBatchId;
133-
if (lastAcked >= nextBatchID) {
134-
HARD_ASSERT([self isEmpty], "Reset nextBatchID is only possible when the queue is empty");
135-
lastAcked = kFSTBatchIDUnknown;
136-
137-
metadata.lastAcknowledgedBatchId = lastAcked;
138-
_db.currentTransaction->Put([self keyForCurrentMutationQueue], metadata);
139-
}
140126
}
141-
142-
self.nextBatchID = nextBatchID;
143127
self.metadata = metadata;
144128
}
145129

@@ -151,7 +135,7 @@ + (BatchId)loadNextBatchIDFromDB:(DB *)db {
151135
auto tableKey = LevelDbMutationKey::KeyPrefix();
152136

153137
LevelDbMutationKey rowKey;
154-
BatchId maxBatchID = kFSTBatchIDUnknown;
138+
BatchId maxBatchID = kBatchIdUnknown;
155139

156140
BOOL moreUserIDs = NO;
157141
std::string nextUserID;
@@ -220,17 +204,8 @@ - (BOOL)isEmpty {
220204
return empty;
221205
}
222206

223-
- (BatchId)highestAcknowledgedBatchID {
224-
return self.metadata.lastAcknowledgedBatchId;
225-
}
226-
227207
- (void)acknowledgeBatch:(FSTMutationBatch *)batch streamToken:(nullable NSData *)streamToken {
228-
BatchId batchID = batch.batchID;
229-
HARD_ASSERT(batchID > self.highestAcknowledgedBatchID,
230-
"Mutation batchIDs must be acknowledged in order");
231-
232208
FSTPBMutationQueue *metadata = self.metadata;
233-
metadata.lastAcknowledgedBatchId = batchID;
234209
metadata.lastStreamToken = streamToken;
235210

236211
_db.currentTransaction->Put([self keyForCurrentMutationQueue], metadata);
@@ -304,10 +279,7 @@ - (nullable FSTMutationBatch *)lookupMutationBatch:(BatchId)batchID {
304279
}
305280

306281
- (nullable FSTMutationBatch *)nextMutationBatchAfterBatchID:(BatchId)batchID {
307-
// All batches with batchID <= self.metadata.lastAcknowledgedBatchId have been acknowledged so
308-
// the first unacknowledged batch after batchID will have a batchID larger than both of these
309-
// values.
310-
BatchId nextBatchID = MAX(batchID, self.metadata.lastAcknowledgedBatchId) + 1;
282+
BatchId nextBatchID = batchID + 1;
311283

312284
std::string key = [self mutationKeyForBatchID:nextBatchID];
313285
auto it = _db.currentTransaction->NewIterator();

Firestore/Source/Local/FSTLocalStore.mm

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,6 @@ - (MaybeDocumentMap)rejectBatchID:(BatchId)batchID {
189189
FSTMutationBatch *toReject = [self.mutationQueue lookupMutationBatch:batchID];
190190
HARD_ASSERT(toReject, "Attempt to reject nonexistent batch!");
191191

192-
BatchId lastAcked = [self.mutationQueue highestAcknowledgedBatchID];
193-
HARD_ASSERT(batchID > lastAcked, "Acknowledged batches can't be rejected.");
194-
195192
[self.mutationQueue removeMutationBatch:toReject];
196193
[self.mutationQueue performConsistencyCheck];
197194

Firestore/Source/Local/FSTMemoryMutationQueue.mm

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ @interface FSTMemoryMutationQueue ()
6868
/** The next value to use when assigning sequential IDs to each mutation batch. */
6969
@property(nonatomic, assign) BatchId nextBatchID;
7070

71-
/** The highest acknowledged mutation in the queue. */
72-
@property(nonatomic, assign) BatchId highestAcknowledgedBatchID;
73-
7471
/**
7572
* The last received stream token from the server, used to acknowledge which responses the client
7673
* has processed. Stream tokens are opaque checkpoint markers whose only real value is their
@@ -94,7 +91,6 @@ - (instancetype)initWithPersistence:(FSTMemoryPersistence *)persistence {
9491
_queue = [NSMutableArray array];
9592

9693
_nextBatchID = 1;
97-
_highestAcknowledgedBatchID = kFSTBatchIDUnknown;
9894
}
9995
return self;
10096
}
@@ -105,13 +101,10 @@ - (void)start {
105101
// Note: The queue may be shutdown / started multiple times, since we maintain the queue for the
106102
// duration of the app session in case a user logs out / back in. To behave like the
107103
// LevelDB-backed MutationQueue (and accommodate tests that expect as much), we reset nextBatchID
108-
// and highestAcknowledgedBatchID if the queue is empty.
104+
// if the queue is empty.
109105
if (self.isEmpty) {
110106
self.nextBatchID = 1;
111-
self.highestAcknowledgedBatchID = kFSTBatchIDUnknown;
112107
}
113-
HARD_ASSERT(self.highestAcknowledgedBatchID < self.nextBatchID,
114-
"highestAcknowledgedBatchID must be less than the nextBatchID");
115108
}
116109

117110
- (BOOL)isEmpty {
@@ -120,16 +113,10 @@ - (BOOL)isEmpty {
120113
return self.queue.count == 0;
121114
}
122115

123-
- (BatchId)highestAcknowledgedBatchID {
124-
return _highestAcknowledgedBatchID;
125-
}
126-
127116
- (void)acknowledgeBatch:(FSTMutationBatch *)batch streamToken:(nullable NSData *)streamToken {
128117
NSMutableArray<FSTMutationBatch *> *queue = self.queue;
129118

130119
BatchId batchID = batch.batchID;
131-
HARD_ASSERT(batchID > self.highestAcknowledgedBatchID,
132-
"Mutation batchIDs must be acknowledged in order");
133120

134121
NSInteger batchIndex = [self indexOfExistingBatchID:batchID action:@"acknowledged"];
135122
HARD_ASSERT(batchIndex == 0, "Can only acknowledge the first batch in the mutation queue");
@@ -139,7 +126,6 @@ - (void)acknowledgeBatch:(FSTMutationBatch *)batch streamToken:(nullable NSData
139126
HARD_ASSERT(batchID == check.batchID, "Queue ordering failure: expected batch %s, got batch %s",
140127
batchID, check.batchID);
141128

142-
self.highestAcknowledgedBatchID = batchID;
143129
self.lastStreamToken = streamToken;
144130
}
145131

@@ -186,9 +172,7 @@ - (nullable FSTMutationBatch *)lookupMutationBatch:(BatchId)batchID {
186172
- (nullable FSTMutationBatch *)nextMutationBatchAfterBatchID:(BatchId)batchID {
187173
NSMutableArray<FSTMutationBatch *> *queue = self.queue;
188174

189-
// All batches with batchID <= self.highestAcknowledgedBatchID have been acknowledged so the
190-
// first unacknowledged batch after batchID will have a batchID larger than both of these values.
191-
BatchId nextBatchID = MAX(batchID, self.highestAcknowledgedBatchID) + 1;
175+
BatchId nextBatchID = batchID + 1;
192176

193177
// The requested batchID may still be out of range so normalize it to the start of the queue.
194178
NSInteger rawIndex = [self indexOfBatchID:nextBatchID];

Firestore/Source/Local/FSTMutationQueue.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,12 @@ NS_ASSUME_NONNULL_BEGIN
3535
/**
3636
* Starts the mutation queue, performing any initial reads that might be required to establish
3737
* invariants, etc.
38-
*
39-
* After starting, the mutation queue must guarantee that the highestAcknowledgedBatchID is less
40-
* than nextBatchID. This prevents the local store from creating new batches that the mutation
41-
* queue would consider erroneously acknowledged.
4238
*/
4339
- (void)start;
4440

4541
/** Returns YES if this queue contains no mutation batches. */
4642
- (BOOL)isEmpty;
4743

48-
/**
49-
* Returns the highest batchID that has been acknowledged. If no batches have been acknowledged
50-
* or if there are no batches in the queue this can return kFSTBatchIDUnknown.
51-
*/
52-
- (firebase::firestore::model::BatchId)highestAcknowledgedBatchID;
53-
5444
/** Acknowledges the given batch. */
5545
- (void)acknowledgeBatch:(FSTMutationBatch *)batch streamToken:(nullable NSData *)streamToken;
5646

@@ -71,7 +61,7 @@ NS_ASSUME_NONNULL_BEGIN
7161
* Gets the first unacknowledged mutation batch after the passed in batchId in the mutation queue
7262
* or nil if empty.
7363
*
74-
* @param batchID The batch to search after, or kFSTBatchIDUnknown for the first mutation in the
64+
* @param batchID The batch to search after, or kBatchIdUnknown for the first mutation in the
7565
* queue.
7666
*
7767
* @return the next mutation or nil if there wasn't one.

Firestore/Source/Model/FSTMutationBatch.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,6 @@ using DocumentVersionMap = std::unordered_map<DocumentKey, SnapshotVersion, Docu
4242

4343
NS_ASSUME_NONNULL_BEGIN
4444

45-
/**
46-
* A BatchID that was searched for and not found or a batch ID value known to be before all known
47-
* batches.
48-
*
49-
* BatchId values from the local store are non-negative so this value is before all batches.
50-
*/
51-
extern const firebase::firestore::model::BatchId kFSTBatchIDUnknown;
52-
5345
/**
5446
* A batch of mutations that will be sent as one unit to the backend. Batches can be marked as a
5547
* tombstone if the mutation queue does not remove them immediately. When a batch is a tombstone

Firestore/Source/Model/FSTMutationBatch.mm

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434

3535
NS_ASSUME_NONNULL_BEGIN
3636

37-
const BatchId kFSTBatchIDUnknown = -1;
38-
3937
@implementation FSTMutationBatch
4038

4139
- (instancetype)initWithBatchID:(BatchId)batchID

Firestore/Source/Remote/FSTRemoteStore.mm

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
#include "Firestore/core/src/firebase/firestore/auth/user.h"
3737
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
38+
#include "Firestore/core/src/firebase/firestore/model/mutation_batch.h"
3839
#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
3940
#include "Firestore/core/src/firebase/firestore/remote/stream.h"
4041
#include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
@@ -45,6 +46,7 @@
4546
namespace util = firebase::firestore::util;
4647
using firebase::firestore::auth::User;
4748
using firebase::firestore::model::BatchId;
49+
using firebase::firestore::model::kBatchIdUnknown;
4850
using firebase::firestore::model::DocumentKey;
4951
using firebase::firestore::model::DocumentKeySet;
5052
using firebase::firestore::model::OnlineState;
@@ -464,7 +466,7 @@ - (void)startWriteStream {
464466
*/
465467
- (void)fillWritePipeline {
466468
BatchId lastBatchIDRetrieved =
467-
self.writePipeline.count == 0 ? kFSTBatchIDUnknown : self.writePipeline.lastObject.batchID;
469+
self.writePipeline.count == 0 ? kBatchIdUnknown : self.writePipeline.lastObject.batchID;
468470
while ([self canAddToWritePipeline]) {
469471
FSTMutationBatch *batch = [self.localStore nextMutationBatchAfterBatchID:lastBatchIDRetrieved];
470472
if (!batch) {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2019 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_MUTATION_BATCH_H_
18+
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_MUTATION_BATCH_H_
19+
20+
#include "Firestore/core/src/firebase/firestore/model/types.h"
21+
22+
namespace firebase {
23+
namespace firestore {
24+
namespace model {
25+
26+
/**
27+
* A BatchID that was searched for and not found or a batch ID value known to be
28+
* before all known batches.
29+
*
30+
* BatchId values from the local store are non-negative so this value is before
31+
* all batches.
32+
*/
33+
constexpr BatchId kBatchIdUnknown = -1;
34+
35+
} // namespace model
36+
} // namespace firestore
37+
} // namespace firebase
38+
39+
#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_MUTATION_BATCH_H_

0 commit comments

Comments
 (0)