Skip to content

Port Mutation Batch API from Android/Web #1963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 18 additions & 28 deletions Firestore/Example/Tests/Model/FSTMutationTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ - (void)testAppliesSetsToDocuments {
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);

FSTMutation *set = FSTTestSetMutation(@"collection/key", @{@"bar" : @"bar-value"});
FSTMaybeDocument *setDoc = [set applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
FSTMaybeDocument *setDoc =
[set applyToLocalDocument:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];

NSDictionary *expectedData = @{@"bar" : @"bar-value"};
XCTAssertEqualObjects(setDoc, FSTTestDoc("collection/key", 0, expectedData, YES));
Expand All @@ -72,7 +73,7 @@ - (void)testAppliesPatchesToDocuments {

FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo.bar" : @"new-bar-value"}, {});
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
[patch applyToLocalDocument:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];

NSDictionary *expectedData = @{@"foo" : @{@"bar" : @"new-bar-value"}, @"baz" : @"baz-value"};
XCTAssertEqualObjects(patchedDoc, FSTTestDoc("collection/key", 0, expectedData, YES));
Expand All @@ -88,7 +89,7 @@ - (void)testDeletesValuesFromTheFieldMask {
value:[FSTObjectValue objectValue]
precondition:Precondition::None()];
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
[patch applyToLocalDocument:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];

NSDictionary *expectedData = @{@"foo" : @{@"baz" : @"baz-value"}};
XCTAssertEqualObjects(patchedDoc, FSTTestDoc("collection/key", 0, expectedData, YES));
Expand All @@ -100,7 +101,7 @@ - (void)testPatchesPrimitiveValue {

FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo.bar" : @"new-bar-value"}, {});
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
[patch applyToLocalDocument:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];

NSDictionary *expectedData = @{@"foo" : @{@"bar" : @"new-bar-value"}, @"baz" : @"baz-value"};
XCTAssertEqualObjects(patchedDoc, FSTTestDoc("collection/key", 0, expectedData, YES));
Expand All @@ -110,7 +111,7 @@ - (void)testPatchingDeletedDocumentsDoesNothing {
FSTMaybeDocument *baseDoc = FSTTestDeletedDoc("collection/key", 0);
FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo" : @"bar"}, {});
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
[patch applyToLocalDocument:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
XCTAssertEqualObjects(patchedDoc, baseDoc);
}

Expand All @@ -121,7 +122,7 @@ - (void)testAppliesLocalServerTimestampTransformToDocuments {
FSTMutation *transform = FSTTestTransformMutation(
@"collection/key", @{@"foo.bar" : [FIRFieldValue fieldValueForServerTimestamp]});
FSTMaybeDocument *transformedDoc =
[transform applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
[transform applyToLocalDocument:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];

// Server timestamps aren't parsed, so we manually insert it.
FSTObjectValue *expectedData = FSTTestObjectValue(
Expand Down Expand Up @@ -297,7 +298,7 @@ - (void)transformBaseDoc:(NSDictionary<NSString *, id> *)baseData
FSTMutation *transform = FSTTestTransformMutation(@"collection/key", transformData);

FSTMaybeDocument *transformedDoc =
[transform applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
[transform applyToLocalDocument:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];

FSTDocument *expectedDoc = [FSTDocument documentWithData:FSTTestObjectValue(expectedData)
key:FSTTestDocKey(@"collection/key")
Expand All @@ -318,10 +319,8 @@ - (void)testAppliesServerAckedServerTimestampTransformToDocuments {
initWithVersion:testutil::Version(1)
transformResults:@[ [FSTTimestampValue timestampValue:_timestamp] ]];

FSTMaybeDocument *transformedDoc = [transform applyTo:baseDoc
baseDocument:baseDoc
localWriteTime:_timestamp
mutationResult:mutationResult];
FSTMaybeDocument *transformedDoc =
[transform applyToRemoteDocument:baseDoc mutationResult:mutationResult];

NSDictionary *expectedData = @{@"foo" : @{@"bar" : _timestamp.dateValue}, @"baz" : @"baz-value"};
XCTAssertEqualObjects(transformedDoc, FSTTestDoc("collection/key", 0, expectedData, NO));
Expand All @@ -341,10 +340,8 @@ - (void)testAppliesServerAckedArrayTransformsToDocuments {
initWithVersion:testutil::Version(1)
transformResults:@[ [FSTNullValue nullValue], [FSTNullValue nullValue] ]];

FSTMaybeDocument *transformedDoc = [transform applyTo:baseDoc
baseDocument:baseDoc
localWriteTime:_timestamp
mutationResult:mutationResult];
FSTMaybeDocument *transformedDoc =
[transform applyToRemoteDocument:baseDoc mutationResult:mutationResult];

NSDictionary *expectedData = @{@"array_1" : @[ @1, @2, @3 ], @"array_2" : @[ @"b" ]};
XCTAssertEqualObjects(transformedDoc, FSTTestDoc("collection/key", 0, expectedData, NO));
Expand All @@ -356,7 +353,7 @@ - (void)testDeleteDeletes {

FSTMutation *mutation = FSTTestDeleteMutation(@"collection/key");
FSTMaybeDocument *result =
[mutation applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
[mutation applyToLocalDocument:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
XCTAssertEqualObjects(result, FSTTestDeletedDoc("collection/key", 0));
}

Expand All @@ -367,10 +364,7 @@ - (void)testSetWithMutationResult {
FSTMutation *set = FSTTestSetMutation(@"collection/key", @{@"foo" : @"new-bar"});
FSTMutationResult *mutationResult =
[[FSTMutationResult alloc] initWithVersion:testutil::Version(4) transformResults:nil];
FSTMaybeDocument *setDoc = [set applyTo:baseDoc
baseDocument:baseDoc
localWriteTime:_timestamp
mutationResult:mutationResult];
FSTMaybeDocument *setDoc = [set applyToRemoteDocument:baseDoc mutationResult:mutationResult];

NSDictionary *expectedData = @{@"foo" : @"new-bar"};
XCTAssertEqualObjects(setDoc, FSTTestDoc("collection/key", 0, expectedData, NO));
Expand All @@ -383,10 +377,8 @@ - (void)testPatchWithMutationResult {
FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo" : @"new-bar"}, {});
FSTMutationResult *mutationResult =
[[FSTMutationResult alloc] initWithVersion:testutil::Version(4) transformResults:nil];
FSTMaybeDocument *patchedDoc = [patch applyTo:baseDoc
baseDocument:baseDoc
localWriteTime:_timestamp
mutationResult:mutationResult];
FSTMaybeDocument *patchedDoc =
[patch applyToRemoteDocument:baseDoc mutationResult:mutationResult];

NSDictionary *expectedData = @{@"foo" : @"new-bar"};
XCTAssertEqualObjects(patchedDoc, FSTTestDoc("collection/key", 0, expectedData, NO));
Expand All @@ -396,10 +388,8 @@ - (void)testPatchWithMutationResult {
do { \
FSTMutationResult *mutationResult = \
[[FSTMutationResult alloc] initWithVersion:testutil::Version(0) transformResults:nil]; \
FSTMaybeDocument *actual = [mutation applyTo:base \
baseDocument:base \
localWriteTime:_timestamp \
mutationResult:mutationResult]; \
FSTMaybeDocument *actual = \
[mutation applyToRemoteDocument:base mutationResult:mutationResult]; \
XCTAssertEqualObjects(actual, expected); \
} while (0);

Expand Down
7 changes: 4 additions & 3 deletions Firestore/Source/Local/FSTLocalDocumentsView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ - (nullable FSTMaybeDocument *)documentForKey:(const DocumentKey &)key
inBatches:(NSArray<FSTMutationBatch *> *)batches {
FSTMaybeDocument *_Nullable document = [self.remoteDocumentCache entryForKey:key];
for (FSTMutationBatch *batch in batches) {
document = [batch applyTo:document documentKey:key];
document = [batch applyToLocalDocument:document documentKey:key];
}

return document;
Expand Down Expand Up @@ -129,8 +129,9 @@ - (FSTDocumentDictionary *)documentsMatchingCollectionQuery:(FSTQuery *)query {
FSTDocumentKey *key = static_cast<FSTDocumentKey *>(mutation.key);
// baseDoc may be nil for the documents that weren't yet written to the backend.
FSTMaybeDocument *baseDoc = results[key];
FSTMaybeDocument *mutatedDoc =
[mutation applyTo:baseDoc baseDocument:baseDoc localWriteTime:batch.localWriteTime];
FSTMaybeDocument *mutatedDoc = [mutation applyToLocalDocument:baseDoc
baseDocument:baseDoc
localWriteTime:batch.localWriteTime];

if (!mutatedDoc || [mutatedDoc isKindOfClass:[FSTDeletedDocument class]]) {
results = [results dictionaryByRemovingObjectForKey:key];
Expand Down
2 changes: 1 addition & 1 deletion Firestore/Source/Local/FSTLocalStore.mm
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ - (void)applyBatchResult:(FSTMutationBatchResult *)batchResult {
"docVersions should contain every doc in the write.");
const SnapshotVersion &ackVersion = ackVersionIter->second;
if (!doc || doc.version < ackVersion) {
doc = [batch applyTo:doc documentKey:docKey mutationBatchResult:batchResult];
doc = [batch applyToRemoteDocument:doc documentKey:docKey mutationBatchResult:batchResult];
if (!doc) {
HARD_ASSERT(!remoteDoc, "Mutation batch %s applied to document %s resulted in nil.", batch,
remoteDoc);
Expand Down
31 changes: 16 additions & 15 deletions Firestore/Source/Model/FSTMutation.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,11 @@ NS_ASSUME_NONNULL_BEGIN
NS_DESIGNATED_INITIALIZER;

/**
* Applies this mutation to the given FSTDocument, FSTDeletedDocument or nil, if we don't have
* information about this document. Both the input and returned documents can be nil.
* Applies this mutation to the given FSTDocument, FSTDeletedDocument or nil for the purposes of
* computing a new remote document. Both the input and returned documents can be nil.
*
* @param maybeDoc The current state of the document to mutate. The input document should be nil if
* it does not currently exist.
* @param baseDoc The state of the document prior to this mutation batch. The input document should
* be nil if it the document did not exist.
* @param localWriteTime A timestamp indicating the local write time of the batch this mutation is
* a part of.
* @param mutationResult Optional result info from the backend. If omitted, it's assumed that
* this is merely a local (latency-compensated) application, and the resulting document will
* have its hasLocalMutations flag set.
Expand Down Expand Up @@ -122,18 +118,23 @@ NS_ASSUME_NONNULL_BEGIN
* apply the transform if the prior mutation resulted in an FSTDocument (always true for an
* FSTSetMutation, but not necessarily for an FSTPatchMutation).
*/
- (nullable FSTMaybeDocument *)applyTo:(nullable FSTMaybeDocument *)maybeDoc
baseDocument:(nullable FSTMaybeDocument *)baseDoc
localWriteTime:(FIRTimestamp *)localWriteTime
mutationResult:(nullable FSTMutationResult *)mutationResult;
- (nullable FSTMaybeDocument *)applyToRemoteDocument:(nullable FSTMaybeDocument *)maybeDoc
mutationResult:(FSTMutationResult *)mutationResult;

/**
* A helper version of applyTo for applying mutations locally (without a mutation result from the
* backend).
* Applies this mutation to the given MaybeDocument for the purposes of computing the new local view
* of a document. Both the input and returned documents can be null.
*
* @param maybeDoc The current state of the document to mutate. The input document should be nil if
* it does not currently exist.
* @param baseDoc The state of the document prior to this mutation batch. The input document should
* be nil if it the document did not exist.
* @param localWriteTime A timestamp indicating the local write time of the batch this mutation is
* a part of.
*/
- (nullable FSTMaybeDocument *)applyTo:(nullable FSTMaybeDocument *)maybeDoc
baseDocument:(nullable FSTMaybeDocument *)baseDoc
localWriteTime:(nullable FIRTimestamp *)localWriteTime;
- (nullable FSTMaybeDocument *)applyToLocalDocument:(nullable FSTMaybeDocument *)maybeDoc
baseDocument:(nullable FSTMaybeDocument *)baseDoc
localWriteTime:(FIRTimestamp *)localWriteTime;

- (const firebase::firestore::model::DocumentKey &)key;

Expand Down
Loading