use of com.google.firebase.firestore.model.mutation.PatchMutation in project firebase-android-sdk by firebase.
the class LocalStore method writeLocally.
/**
* Accepts locally generated Mutations and commits them to storage.
*/
public LocalDocumentsResult writeLocally(List<Mutation> mutations) {
Timestamp localWriteTime = Timestamp.now();
// TODO: Call queryEngine.handleDocumentChange() appropriately.
Set<DocumentKey> keys = new HashSet<>();
for (Mutation mutation : mutations) {
keys.add(mutation.getKey());
}
return persistence.runTransaction("Locally write mutations", () -> {
// Load and apply all existing mutations. This lets us compute the current base state for
// all non-idempotent transforms before applying any additional user-provided writes.
ImmutableSortedMap<DocumentKey, Document> documents = localDocuments.getDocuments(keys);
// For non-idempotent mutations (such as `FieldValue.increment()`), we record the base
// state in a separate patch mutation. This is later used to guarantee consistent values
// and prevents flicker even if the backend sends us an update that already includes our
// transform.
List<Mutation> baseMutations = new ArrayList<>();
for (Mutation mutation : mutations) {
ObjectValue baseValue = mutation.extractTransformBaseValue(documents.get(mutation.getKey()));
if (baseValue != null) {
// NOTE: The base state should only be applied if there's some existing
// document to override, so use a Precondition of exists=true
baseMutations.add(new PatchMutation(mutation.getKey(), baseValue, baseValue.getFieldMask(), Precondition.exists(true)));
}
}
MutationBatch batch = mutationQueue.addMutationBatch(localWriteTime, baseMutations, mutations);
Map<DocumentKey, Mutation> overlays = batch.applyToLocalDocumentSet(documents);
documentOverlayCache.saveOverlays(batch.getBatchId(), overlays);
return new LocalDocumentsResult(batch.getBatchId(), documents);
});
}
use of com.google.firebase.firestore.model.mutation.PatchMutation in project firebase-android-sdk by firebase.
the class TestUtil method patchMutationHelper.
private static PatchMutation patchMutationHelper(String path, Map<String, Object> values, Precondition precondition, @Nullable List<FieldPath> updateMask) {
// Replace '<DELETE>' from JSON
for (Entry<String, Object> entry : values.entrySet()) {
if (entry.getValue().equals(DELETE_SENTINEL)) {
values.put(entry.getKey(), FieldValue.delete());
}
}
UserDataReader dataReader = new UserDataReader(DatabaseId.forProject("project"));
ParsedUpdateData parsed = dataReader.parseUpdateData(values);
// `mergeMutation()` provides an update mask for the merged fields, whereas `patchMutation()`
// requires the update mask to be parsed from the values.
Collection<FieldPath> mask = updateMask != null ? updateMask : parsed.getFieldMask().getMask();
// We sort the fieldMaskPaths to make the order deterministic in tests. (Otherwise, when we
// flatten a Set to a proto repeated field, we'll end up comparing in iterator order and
// possibly consider {foo,bar} != {bar,foo}.)
SortedSet<FieldPath> fieldMaskPaths = new TreeSet<>(mask);
// The order of the transforms doesn't matter, but we sort them so tests can assume a particular
// order.
ArrayList<FieldTransform> fieldTransforms = new ArrayList<>(parsed.getFieldTransforms());
Collections.sort(fieldTransforms, (ft1, ft2) -> ft1.getFieldPath().compareTo(ft2.getFieldPath()));
return new PatchMutation(key(path), parsed.getData(), FieldMask.fromSet(fieldMaskPaths), precondition, fieldTransforms);
}
use of com.google.firebase.firestore.model.mutation.PatchMutation in project firebase-android-sdk by firebase.
the class RemoteSerializer method decodeMutation.
public Mutation decodeMutation(com.google.firestore.v1.Write mutation) {
Precondition precondition = mutation.hasCurrentDocument() ? decodePrecondition(mutation.getCurrentDocument()) : Precondition.NONE;
List<FieldTransform> fieldTransforms = new ArrayList<>();
for (DocumentTransform.FieldTransform fieldTransform : mutation.getUpdateTransformsList()) {
fieldTransforms.add(decodeFieldTransform(fieldTransform));
}
switch(mutation.getOperationCase()) {
case UPDATE:
if (mutation.hasUpdateMask()) {
return new PatchMutation(decodeKey(mutation.getUpdate().getName()), ObjectValue.fromMap(mutation.getUpdate().getFieldsMap()), decodeDocumentMask(mutation.getUpdateMask()), precondition, fieldTransforms);
} else {
return new SetMutation(decodeKey(mutation.getUpdate().getName()), ObjectValue.fromMap(mutation.getUpdate().getFieldsMap()), precondition, fieldTransforms);
}
case DELETE:
return new DeleteMutation(decodeKey(mutation.getDelete()), precondition);
case VERIFY:
return new VerifyMutation(decodeKey(mutation.getVerify()), precondition);
default:
throw fail("Unknown mutation operation: %d", mutation.getOperationCase());
}
}
use of com.google.firebase.firestore.model.mutation.PatchMutation in project firebase-android-sdk by firebase.
the class LocalSerializerTest method testMultipleMutationsAreSquashed.
// TODO(b/174608374): Remove these tests once we perform a schema migration.
@Test
public void testMultipleMutationsAreSquashed() {
// INPUT:
// SetMutation -> SetMutation -> TransformMutation -> DeleteMutation -> PatchMutation ->
// TransformMutation -> PatchMutation
// OUTPUT (squashed):
// SetMutation -> SetMutation -> DeleteMutation -> PatchMutation -> PatchMutation
WriteBatch batchProto = com.google.firebase.firestore.proto.WriteBatch.newBuilder().setBatchId(42).addAllWrites(asList(setProto, setProto, transformProto, deleteProto, patchProto, transformProto, patchProto)).setLocalWriteTime(writeTimeProto).build();
MutationBatch decoded = serializer.decodeMutationBatch(batchProto);
assertEquals(5, decoded.getMutations().size());
List<Write> allExpected = asList(new TestWriteBuilder().addSet().build(), new TestWriteBuilder().addSet().addUpdateTransforms().build(), new TestWriteBuilder().addDelete().build(), new TestWriteBuilder().addPatch().addUpdateTransforms().build(), new TestWriteBuilder().addPatch().build());
for (int i = 0; i < decoded.getMutations().size(); i++) {
Mutation mutation = decoded.getMutations().get(i);
Write encoded = remoteSerializer.encodeMutation(mutation);
assertEquals(allExpected.get(i), encoded);
}
}
use of com.google.firebase.firestore.model.mutation.PatchMutation in project firebase-android-sdk by firebase.
the class LocalDocumentsView method computeViews.
/*Computes the local view for doc */
private ImmutableSortedMap<DocumentKey, Document> computeViews(Map<DocumentKey, MutableDocument> docs, Map<DocumentKey, Overlay> overlays, Set<DocumentKey> existenceStateChanged) {
ImmutableSortedMap<DocumentKey, Document> results = emptyDocumentMap();
Map<DocumentKey, MutableDocument> recalculateDocuments = new HashMap<>();
for (MutableDocument doc : docs.values()) {
Overlay overlay = overlays.get(doc.getKey());
// but would now match.
if (existenceStateChanged.contains(doc.getKey()) && (overlay == null || overlay.getMutation() instanceof PatchMutation)) {
recalculateDocuments.put(doc.getKey(), doc);
} else if (overlay != null) {
overlay.getMutation().applyToLocalView(doc, null, Timestamp.now());
}
}
recalculateAndSaveOverlays(recalculateDocuments);
for (Map.Entry<DocumentKey, MutableDocument> entry : docs.entrySet()) {
results = results.insert(entry.getKey(), entry.getValue());
}
return results;
}
Aggregations