Skip to content

Commit 9815e45

Browse files
authored
Overlay on top of mutation list (#2962)
1 parent cf7680d commit 9815e45

File tree

9 files changed

+486
-60
lines changed

9 files changed

+486
-60
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalDocumentsView.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.firebase.firestore.model.MutableDocument;
2626
import com.google.firebase.firestore.model.ResourcePath;
2727
import com.google.firebase.firestore.model.SnapshotVersion;
28+
import com.google.firebase.firestore.model.mutation.FieldMask;
2829
import com.google.firebase.firestore.model.mutation.Mutation;
2930
import com.google.firebase.firestore.model.mutation.MutationBatch;
3031
import com.google.firebase.firestore.model.mutation.PatchMutation;
@@ -209,7 +210,9 @@ private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollection
209210
document = MutableDocument.newInvalidDocument(key);
210211
remoteDocuments = remoteDocuments.insert(key, document);
211212
}
212-
mutation.applyToLocalView(document, batch.getLocalWriteTime());
213+
// TODO(Overlay): Here we should be reading overlay mutation and apply that instead.
214+
mutation.applyToLocalView(
215+
document, FieldMask.fromSet(new HashSet<>()), batch.getLocalWriteTime());
213216
if (!document.isFoundDocument()) {
214217
remoteDocuments = remoteDocuments.remove(key);
215218
}

firebase-firestore/src/main/java/com/google/firebase/firestore/model/ObjectValue.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ public int hashCode() {
261261
@Override
262262
@NonNull
263263
public String toString() {
264-
return "ObjectValue{" + "internalValue=" + buildProto() + '}';
264+
return "ObjectValue{" + "internalValue=" + Values.canonicalId(buildProto()) + '}';
265265
}
266266

267267
@NonNull

firebase-firestore/src/main/java/com/google/firebase/firestore/model/mutation/DeleteMutation.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import static com.google.firebase.firestore.util.Assert.hardAssert;
1818

19+
import androidx.annotation.Nullable;
1920
import com.google.firebase.Timestamp;
2021
import com.google.firebase.firestore.model.DocumentKey;
2122
import com.google.firebase.firestore.model.MutableDocument;
@@ -67,11 +68,15 @@ public void applyToRemoteDocument(MutableDocument document, MutationResult mutat
6768
}
6869

6970
@Override
70-
public void applyToLocalView(MutableDocument document, Timestamp localWriteTime) {
71+
public @Nullable FieldMask applyToLocalView(
72+
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime) {
7173
verifyKeyMatches(document);
7274

7375
if (getPrecondition().isValidFor(document)) {
7476
document.convertToNoDocument(document.getVersion()).setHasLocalMutations();
77+
return null;
7578
}
79+
80+
return previousMask;
7681
}
7782
}

firebase-firestore/src/main/java/com/google/firebase/firestore/model/mutation/Mutation.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import static com.google.firebase.firestore.util.Assert.hardAssert;
1818

19+
import androidx.annotation.Nullable;
1920
import com.google.firebase.Timestamp;
2021
import com.google.firebase.firestore.model.Document;
2122
import com.google.firebase.firestore.model.DocumentKey;
@@ -109,10 +110,13 @@ public abstract void applyToRemoteDocument(
109110
* modified.
110111
*
111112
* @param document The document to mutate.
113+
* @param previousMask The fields that have been updated before applying this mutation.
112114
* @param localWriteTime A timestamp indicating the local write time of the batch this mutation is
113115
* a part of.
116+
* @return A {@code FieldMask} representing the fields that are changed by applying this mutation.
114117
*/
115-
public abstract void applyToLocalView(MutableDocument document, Timestamp localWriteTime);
118+
public abstract @Nullable FieldMask applyToLocalView(
119+
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime);
116120

117121
/** Helper for derived classes to implement .equals(). */
118122
boolean hasSameKeyAndPrecondition(Mutation other) {
@@ -169,7 +173,7 @@ protected Map<FieldPath, Value> serverTransformResults(
169173
* result of applying a transform) for use when applying a transform locally.
170174
*
171175
* @param localWriteTime The local time of the mutation (used to generate ServerTimestampValues).
172-
* @param mutableDocument The current state of the document after applying all previous mutations.
176+
* @param mutableDocument The document to apply transforms on.
173177
* @return A map of fields to transform results.
174178
*/
175179
protected Map<FieldPath, Value> localTransformResults(

firebase-firestore/src/main/java/com/google/firebase/firestore/model/mutation/MutationBatch.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,22 +99,25 @@ public void applyToRemoteDocument(MutableDocument document, MutationBatchResult
9999

100100
/** Computes the local view of a document given all the mutations in this batch. */
101101
public void applyToLocalView(MutableDocument document) {
102+
FieldMask mutatedFields = FieldMask.fromSet(new HashSet<>());
102103
// First, apply the base state. This allows us to apply non-idempotent transform against a
103104
// consistent set of values.
104105
for (int i = 0; i < baseMutations.size(); i++) {
105106
Mutation mutation = baseMutations.get(i);
106107
if (mutation.getKey().equals(document.getKey())) {
107-
mutation.applyToLocalView(document, localWriteTime);
108+
mutatedFields = mutation.applyToLocalView(document, mutatedFields, localWriteTime);
108109
}
109110
}
110111

111112
// Second, apply all user-provided mutations.
112113
for (int i = 0; i < mutations.size(); i++) {
113114
Mutation mutation = mutations.get(i);
114115
if (mutation.getKey().equals(document.getKey())) {
115-
mutation.applyToLocalView(document, localWriteTime);
116+
mutatedFields = mutation.applyToLocalView(document, mutatedFields, localWriteTime);
116117
}
117118
}
119+
120+
// TODO(Overlay): Calculate overlay mutation here.
118121
}
119122

120123
/** Computes the local view for all provided documents given the mutations in this batch. */

firebase-firestore/src/main/java/com/google/firebase/firestore/model/mutation/PatchMutation.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.firebase.firestore.model.mutation;
1616

17+
import androidx.annotation.Nullable;
1718
import com.google.firebase.Timestamp;
1819
import com.google.firebase.firestore.model.DocumentKey;
1920
import com.google.firebase.firestore.model.FieldPath;
@@ -22,6 +23,7 @@
2223
import com.google.firestore.v1.Value;
2324
import java.util.ArrayList;
2425
import java.util.HashMap;
26+
import java.util.HashSet;
2527
import java.util.List;
2628
import java.util.Map;
2729

@@ -126,20 +128,39 @@ public void applyToRemoteDocument(MutableDocument document, MutationResult mutat
126128
}
127129

128130
@Override
129-
public void applyToLocalView(MutableDocument document, Timestamp localWriteTime) {
131+
public @Nullable FieldMask applyToLocalView(
132+
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime) {
130133
verifyKeyMatches(document);
131134

132135
if (!getPrecondition().isValidFor(document)) {
133-
return;
136+
return previousMask;
134137
}
135138

136139
Map<FieldPath, Value> transformResults = localTransformResults(localWriteTime, document);
140+
Map<FieldPath, Value> patches = getPatch();
137141
ObjectValue value = document.getData();
138-
value.setAll(getPatch());
142+
value.setAll(patches);
139143
value.setAll(transformResults);
140144
document
141145
.convertToFoundDocument(document.getVersion(), document.getData())
142146
.setHasLocalMutations();
147+
148+
if (previousMask == null) {
149+
return null;
150+
}
151+
152+
HashSet<FieldPath> mergedMaskSet = new HashSet<>(previousMask.getMask());
153+
mergedMaskSet.addAll(this.mask.getMask());
154+
mergedMaskSet.addAll(getFieldTransformPaths());
155+
return FieldMask.fromSet(mergedMaskSet);
156+
}
157+
158+
private List<FieldPath> getFieldTransformPaths() {
159+
List<FieldPath> result = new ArrayList<>();
160+
for (FieldTransform fieldTransform : getFieldTransforms()) {
161+
result.add(fieldTransform.getFieldPath());
162+
}
163+
return result;
143164
}
144165

145166
private Map<FieldPath, Value> getPatch() {

firebase-firestore/src/main/java/com/google/firebase/firestore/model/mutation/SetMutation.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.firebase.firestore.model.mutation;
1616

17+
import androidx.annotation.Nullable;
1718
import com.google.firebase.Timestamp;
1819
import com.google.firebase.firestore.model.DocumentKey;
1920
import com.google.firebase.firestore.model.FieldPath;
@@ -86,17 +87,20 @@ public void applyToRemoteDocument(MutableDocument document, MutationResult mutat
8687
}
8788

8889
@Override
89-
public void applyToLocalView(MutableDocument document, Timestamp localWriteTime) {
90+
public FieldMask applyToLocalView(
91+
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime) {
9092
verifyKeyMatches(document);
9193

9294
if (!this.getPrecondition().isValidFor(document)) {
93-
return;
95+
return previousMask;
9496
}
9597

9698
Map<FieldPath, Value> transformResults = localTransformResults(localWriteTime, document);
9799
ObjectValue localValue = value.clone();
98100
localValue.setAll(transformResults);
99101
document.convertToFoundDocument(document.getVersion(), localValue).setHasLocalMutations();
102+
// SetMutation overwrites all fields.
103+
return null;
100104
}
101105

102106
/** Returns the object value to use when setting the document. */

firebase-firestore/src/main/java/com/google/firebase/firestore/model/mutation/VerifyMutation.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.firebase.firestore.model.mutation;
1616

17+
import androidx.annotation.Nullable;
1718
import com.google.firebase.Timestamp;
1819
import com.google.firebase.firestore.model.DocumentKey;
1920
import com.google.firebase.firestore.model.MutableDocument;
@@ -60,7 +61,9 @@ public void applyToRemoteDocument(MutableDocument document, MutationResult mutat
6061
throw Assert.fail("VerifyMutation should only be used in Transactions.");
6162
}
6263

63-
public void applyToLocalView(MutableDocument document, Timestamp localWriteTime) {
64+
@Override
65+
public FieldMask applyToLocalView(
66+
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime) {
6467
throw Assert.fail("VerifyMutation should only be used in Transactions.");
6568
}
6669
}

0 commit comments

Comments
 (0)