Skip to content

Commit 0ff7ae7

Browse files
committed
Ugly fix fixes
1 parent 18e361d commit 0ff7ae7

File tree

7 files changed

+38
-7
lines changed

7 files changed

+38
-7
lines changed

firebase-firestore/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ by opting into a release at
1616
- [fixed] Fixed an AppCheck issue that caused Firestore listeners to stop
1717
working and receive a "Permission Denied" error. This issue only occurred for
1818
AppCheck users that set their expiration time to under an hour.
19-
- [fixed] Fixed a potential problem during Firestore's shutdown that prevented
19+
- [fixed] Fixed a potential problem during Firestore's shutdown that prevented
2020
the shutdown from proceeding if a network connection was opened right before.
2121
- [changed] Queries are now send to the backend before the SDK starts local
2222
processing, which reduces overall Query latency.

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/QueryTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,7 @@ public void testCollectionGroupQueriesWithWhereFiltersOnArbitraryDocumentIds() {
886886
}
887887

888888
// See: https://github.com/firebase/firebase-android-sdk/issues/3528
889+
// TODO(Overlay): These two tests should be part of local store tests instead.
889890
@Test
890891
public void testAddThenUpdatesWhileOffline() {
891892
CollectionReference collection = testCollection();

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,19 @@ ImmutableSortedMap<DocumentKey, Document> getLocalViewOfDocuments(
122122
return computeViews(docs, overlays, existenceStateChanged);
123123
}
124124

125+
/**
126+
* Similar to {@link #getDocuments}, but creates the local view from the given {@code baseDocs}
127+
* without retrieving documents from the local store.
128+
*
129+
* @param docs The documents to apply local mutations to get the local views.
130+
*/
131+
ImmutableSortedMap<DocumentKey, Document> getLocalViewOfDocuments(
132+
Map<DocumentKey, MutableDocument> docs) {
133+
Map<DocumentKey, Overlay> overlays = new HashMap<>();
134+
populateOverlays(overlays, docs.keySet());
135+
return computeViews(docs, overlays, new HashSet<>());
136+
}
137+
125138
/*Computes the local view for doc */
126139
private ImmutableSortedMap<DocumentKey, Document> computeViews(
127140
Map<DocumentKey, MutableDocument> docs,

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,22 @@ public LocalDocumentsResult writeLocally(List<Mutation> mutations) {
244244
return persistence.runTransaction(
245245
"Locally write mutations",
246246
() -> {
247+
// Figure out which keys do not have a remote version in the cache, this is needed to
248+
// create the right overlay mutation: if no remote version presents, we do not need to
249+
// create overlays as patch mutations.
250+
// TODO(Overlay): Is there a better way to determine this? Document version does not work
251+
// because local mutations set them back to 0.
252+
Map<DocumentKey, MutableDocument> remoteDocs = remoteDocuments.getAll(keys);
253+
Set<DocumentKey> docsWithoutRemoteVersion = new HashSet<>();
254+
for (Map.Entry<DocumentKey, MutableDocument> entry : remoteDocs.entrySet()) {
255+
if (!entry.getValue().isValidDocument()) {
256+
docsWithoutRemoteVersion.add(entry.getKey());
257+
}
258+
}
247259
// Load and apply all existing mutations. This lets us compute the current base state for
248260
// all non-idempotent transforms before applying any additional user-provided writes.
249-
ImmutableSortedMap<DocumentKey, Document> documents = localDocuments.getDocuments(keys);
261+
ImmutableSortedMap<DocumentKey, Document> documents =
262+
localDocuments.getLocalViewOfDocuments(remoteDocs);
250263

251264
// For non-idempotent mutations (such as `FieldValue.increment()`), we record the base
252265
// state in a separate patch mutation. This is later used to guarantee consistent values
@@ -270,7 +283,8 @@ public LocalDocumentsResult writeLocally(List<Mutation> mutations) {
270283

271284
MutationBatch batch =
272285
mutationQueue.addMutationBatch(localWriteTime, baseMutations, mutations);
273-
Map<DocumentKey, Mutation> overlays = batch.applyToLocalDocumentSet(documents);
286+
Map<DocumentKey, Mutation> overlays =
287+
batch.applyToLocalDocumentSet(documents, docsWithoutRemoteVersion);
274288
documentOverlayCache.saveOverlays(batch.getBatchId(), overlays);
275289
return new LocalDocumentsResult(batch.getBatchId(), documents);
276290
});

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.google.firebase.firestore.model.FieldPath;
2424
import com.google.firebase.firestore.model.MutableDocument;
2525
import com.google.firebase.firestore.model.ObjectValue;
26-
import com.google.firebase.firestore.model.SnapshotVersion;
2726
import com.google.firestore.v1.Value;
2827
import java.util.ArrayList;
2928
import java.util.HashMap;
@@ -94,7 +93,7 @@ public static Mutation calculateOverlayMutation(MutableDocument doc, @Nullable F
9493
}
9594

9695
// mask == null when there are Set or Delete being applied to get to the current document.
97-
if (mask == null || doc.getVersion().equals(SnapshotVersion.NONE)) {
96+
if (mask == null) {
9897
if (doc.isNoDocument()) {
9998
return new DeleteMutation(doc.getKey(), Precondition.NONE);
10099
} else {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ public FieldMask applyToLocalView(MutableDocument document, @Nullable FieldMask
136136
* applications.
137137
*/
138138
public Map<DocumentKey, Mutation> applyToLocalDocumentSet(
139-
ImmutableSortedMap<DocumentKey, Document> documentMap) {
139+
ImmutableSortedMap<DocumentKey, Document> documentMap,
140+
Set<DocumentKey> documentsWithoutRemoteVersion) {
140141
// TODO(mrschmidt): This implementation is O(n^2). If we iterate through the mutations first
141142
// (as done in `applyToLocalView(MutableDocument d)`), we can reduce the complexity to
142143
// O(n).
@@ -146,6 +147,9 @@ public Map<DocumentKey, Mutation> applyToLocalDocumentSet(
146147
// remove this cast.
147148
MutableDocument document = (MutableDocument) documentMap.get(key);
148149
FieldMask mutatedFields = applyToLocalView(document);
150+
// Set mutationFields to null if the document is only from local mutations, this creates
151+
// a Set(or Delete) mutation, instead of trying to create a patch mutation as the overlay.
152+
mutatedFields = documentsWithoutRemoteVersion.contains(key) ? null : mutatedFields;
149153
Mutation overlay = Mutation.calculateOverlayMutation(document, mutatedFields);
150154
overlays.put(key, overlay);
151155
if (!document.isValidDocument()) {

firebase-firestore/src/test/java/com/google/firebase/firestore/local/LocalStoreTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ public void testHandlesDeleteMutationThenPatchMutationThenAckThenAck() {
759759

760760
acknowledgeMutation(2); // delete mutation
761761
assertRemoved("foo/bar");
762-
assertContains(deletedDoc("foo/bar", 2).setHasCommittedMutations());
762+
assertContains(deletedDoc("foo/bar", 0).setHasLocalMutations());
763763

764764
acknowledgeMutation(3); // patch mutation
765765
assertChanged(unknownDoc("foo/bar", 3));

0 commit comments

Comments
 (0)