Skip to content

Overlay on top of mutation list #2962

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 14 commits into from
Sep 22, 2021
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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.google.firebase.firestore.model.MutableDocument;
import com.google.firebase.firestore.model.ResourcePath;
import com.google.firebase.firestore.model.SnapshotVersion;
import com.google.firebase.firestore.model.mutation.FieldMask;
import com.google.firebase.firestore.model.mutation.Mutation;
import com.google.firebase.firestore.model.mutation.MutationBatch;
import com.google.firebase.firestore.model.mutation.PatchMutation;
Expand Down Expand Up @@ -209,7 +210,9 @@ private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollection
document = MutableDocument.newInvalidDocument(key);
remoteDocuments = remoteDocuments.insert(key, document);
}
mutation.applyToLocalView(document, batch.getLocalWriteTime());
// TODO(Overlay): Here we should be reading overlay mutation and apply that instead.
mutation.applyToLocalView(
document, FieldMask.fromSet(new HashSet<>()), batch.getLocalWriteTime());
if (!document.isFoundDocument()) {
remoteDocuments = remoteDocuments.remove(key);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ public int hashCode() {
@Override
@NonNull
public String toString() {
return "ObjectValue{" + "internalValue=" + buildProto() + '}';
return "ObjectValue{" + "internalValue=" + Values.canonicalId(buildProto()) + '}';
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

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

import androidx.annotation.Nullable;
import com.google.firebase.Timestamp;
import com.google.firebase.firestore.model.DocumentKey;
import com.google.firebase.firestore.model.MutableDocument;
Expand Down Expand Up @@ -67,11 +68,15 @@ public void applyToRemoteDocument(MutableDocument document, MutationResult mutat
}

@Override
public void applyToLocalView(MutableDocument document, Timestamp localWriteTime) {
public @Nullable FieldMask applyToLocalView(
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime) {
verifyKeyMatches(document);

if (getPrecondition().isValidFor(document)) {
document.convertToNoDocument(document.getVersion()).setHasLocalMutations();
return null;
}

return previousMask;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

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

import androidx.annotation.Nullable;
import com.google.firebase.Timestamp;
import com.google.firebase.firestore.model.Document;
import com.google.firebase.firestore.model.DocumentKey;
Expand Down Expand Up @@ -109,10 +110,13 @@ public abstract void applyToRemoteDocument(
* modified.
*
* @param document The document to mutate.
* @param previousMask The fields that have been updated before applying this mutation.
* @param localWriteTime A timestamp indicating the local write time of the batch this mutation is
* a part of.
* @return A {@code FieldMask} representing the fields that are changed by applying this mutation.
*/
public abstract void applyToLocalView(MutableDocument document, Timestamp localWriteTime);
public abstract @Nullable FieldMask applyToLocalView(
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime);

/** Helper for derived classes to implement .equals(). */
boolean hasSameKeyAndPrecondition(Mutation other) {
Expand Down Expand Up @@ -169,7 +173,7 @@ protected Map<FieldPath, Value> serverTransformResults(
* result of applying a transform) for use when applying a transform locally.
*
* @param localWriteTime The local time of the mutation (used to generate ServerTimestampValues).
* @param mutableDocument The current state of the document after applying all previous mutations.
* @param mutableDocument The document to apply transforms on.
* @return A map of fields to transform results.
*/
protected Map<FieldPath, Value> localTransformResults(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,25 @@ public void applyToRemoteDocument(MutableDocument document, MutationBatchResult

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

// Second, apply all user-provided mutations.
for (int i = 0; i < mutations.size(); i++) {
Mutation mutation = mutations.get(i);
if (mutation.getKey().equals(document.getKey())) {
mutation.applyToLocalView(document, localWriteTime);
mutatedFields = mutation.applyToLocalView(document, mutatedFields, localWriteTime);
}
}

// TODO(Overlay): Calculate overlay mutation here.
}

/** Computes the local view for all provided documents given the mutations in this batch. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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

import androidx.annotation.Nullable;
import com.google.firebase.Timestamp;
import com.google.firebase.firestore.model.DocumentKey;
import com.google.firebase.firestore.model.FieldPath;
Expand All @@ -22,6 +23,7 @@
import com.google.firestore.v1.Value;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -126,20 +128,39 @@ public void applyToRemoteDocument(MutableDocument document, MutationResult mutat
}

@Override
public void applyToLocalView(MutableDocument document, Timestamp localWriteTime) {
public @Nullable FieldMask applyToLocalView(
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime) {
verifyKeyMatches(document);

if (!getPrecondition().isValidFor(document)) {
return;
return previousMask;
}

Map<FieldPath, Value> transformResults = localTransformResults(localWriteTime, document);
Map<FieldPath, Value> patches = getPatch();
ObjectValue value = document.getData();
value.setAll(getPatch());
value.setAll(patches);
value.setAll(transformResults);
document
.convertToFoundDocument(document.getVersion(), document.getData())
.setHasLocalMutations();

if (previousMask == null) {
return null;
}

HashSet<FieldPath> mergedMaskSet = new HashSet<>(previousMask.getMask());
mergedMaskSet.addAll(this.mask.getMask());
mergedMaskSet.addAll(getFieldTransformPaths());
return FieldMask.fromSet(mergedMaskSet);
}

private List<FieldPath> getFieldTransformPaths() {
List<FieldPath> result = new ArrayList<>();
for (FieldTransform fieldTransform : getFieldTransforms()) {
result.add(fieldTransform.getFieldPath());
}
return result;
}

private Map<FieldPath, Value> getPatch() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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

import androidx.annotation.Nullable;
import com.google.firebase.Timestamp;
import com.google.firebase.firestore.model.DocumentKey;
import com.google.firebase.firestore.model.FieldPath;
Expand Down Expand Up @@ -86,17 +87,20 @@ public void applyToRemoteDocument(MutableDocument document, MutationResult mutat
}

@Override
public void applyToLocalView(MutableDocument document, Timestamp localWriteTime) {
public FieldMask applyToLocalView(
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime) {
verifyKeyMatches(document);

if (!this.getPrecondition().isValidFor(document)) {
return;
return previousMask;
}

Map<FieldPath, Value> transformResults = localTransformResults(localWriteTime, document);
ObjectValue localValue = value.clone();
localValue.setAll(transformResults);
document.convertToFoundDocument(document.getVersion(), localValue).setHasLocalMutations();
// SetMutation overwrites all fields.
return null;
}

/** Returns the object value to use when setting the document. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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

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

public void applyToLocalView(MutableDocument document, Timestamp localWriteTime) {
@Override
public FieldMask applyToLocalView(
MutableDocument document, @Nullable FieldMask previousMask, Timestamp localWriteTime) {
throw Assert.fail("VerifyMutation should only be used in Transactions.");
}
}
Loading