Search in sources :

Example 1 with DocumentKey

use of com.google.firebase.firestore.model.DocumentKey in project firebase-android-sdk by firebase.

the class LocalDocumentsView method recalculateAndSaveOverlays.

private void recalculateAndSaveOverlays(Map<DocumentKey, MutableDocument> docs) {
    List<MutationBatch> batches = mutationQueue.getAllMutationBatchesAffectingDocumentKeys(docs.keySet());
    Map<DocumentKey, FieldMask> masks = new HashMap<>();
    // A reverse lookup map from batch id to the documents within that batch.
    TreeMap<Integer, Set<DocumentKey>> documentsByBatchId = new TreeMap<>();
    // along the way.
    for (MutationBatch batch : batches) {
        for (DocumentKey key : batch.getKeys()) {
            MutableDocument baseDoc = docs.get(key);
            if (baseDoc == null) {
                // If this batch has documents not included in passed in `docs`, skip them.
                continue;
            }
            FieldMask mask = masks.containsKey(key) ? masks.get(key) : FieldMask.EMPTY;
            mask = batch.applyToLocalView(baseDoc, mask);
            masks.put(key, mask);
            int batchId = batch.getBatchId();
            if (!documentsByBatchId.containsKey(batchId)) {
                documentsByBatchId.put(batchId, new HashSet<>());
            }
            documentsByBatchId.get(batchId).add(key);
        }
    }
    Set<DocumentKey> processed = new HashSet<>();
    // Iterate in descending order of batch ids, skip documents that are already saved.
    for (Map.Entry<Integer, Set<DocumentKey>> entry : documentsByBatchId.descendingMap().entrySet()) {
        Map<DocumentKey, Mutation> overlays = new HashMap<>();
        for (DocumentKey key : entry.getValue()) {
            if (!processed.contains(key)) {
                overlays.put(key, Mutation.calculateOverlayMutation(docs.get(key), masks.get(key)));
                processed.add(key);
            }
        }
        documentOverlayCache.saveOverlays(entry.getKey(), overlays);
    }
}
Also used : SortedSet(java.util.SortedSet) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) MutableDocument(com.google.firebase.firestore.model.MutableDocument) TreeMap(java.util.TreeMap) MutationBatch(com.google.firebase.firestore.model.mutation.MutationBatch) DocumentKey(com.google.firebase.firestore.model.DocumentKey) PatchMutation(com.google.firebase.firestore.model.mutation.PatchMutation) Mutation(com.google.firebase.firestore.model.mutation.Mutation) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) ImmutableSortedMap(com.google.firebase.database.collection.ImmutableSortedMap) DocumentCollections.emptyDocumentMap(com.google.firebase.firestore.model.DocumentCollections.emptyDocumentMap) FieldMask(com.google.firebase.firestore.model.mutation.FieldMask) HashSet(java.util.HashSet)

Example 2 with DocumentKey

use of com.google.firebase.firestore.model.DocumentKey in project firebase-android-sdk by firebase.

the class LocalDocumentsView method getNextDocuments.

/**
 * Given a collection group, returns the next documents that follow the provided offset, along
 * with an updated batch ID.
 *
 * <p>The documents returned by this method are ordered by remote version from the provided
 * offset. If there are no more remote documents after the provided offset, documents with
 * mutations in order of batch id from the offset are returned. Since all documents in a batch are
 * returned together, the total number of documents returned can exceed {@code count}.
 *
 * @param collectionGroup The collection group for the documents.
 * @param offset The offset to index into.
 * @param count The number of documents to return
 * @return A LocalDocumentsResult with the documents that follow the provided offset and the last
 *     processed batch id.
 */
LocalDocumentsResult getNextDocuments(String collectionGroup, IndexOffset offset, int count) {
    Map<DocumentKey, MutableDocument> docs = remoteDocumentCache.getAll(collectionGroup, offset, count);
    Map<DocumentKey, Overlay> overlays = count - docs.size() > 0 ? documentOverlayCache.getOverlays(collectionGroup, offset.getLargestBatchId(), count - docs.size()) : Collections.emptyMap();
    int largestBatchId = FieldIndex.INITIAL_LARGEST_BATCH_ID;
    for (Overlay overlay : overlays.values()) {
        if (!docs.containsKey(overlay.getKey())) {
            docs.put(overlay.getKey(), getBaseDocument(overlay.getKey(), overlay));
        }
        // The callsite will use the largest batch ID together with the latest read time to create
        // a new index offset. Since we only process batch IDs if all remote documents have been read,
        // no overlay will increase the overall read time. This is why we only need to special case
        // the batch id.
        largestBatchId = Math.max(largestBatchId, overlay.getLargestBatchId());
    }
    populateOverlays(overlays, docs.keySet());
    ImmutableSortedMap<DocumentKey, Document> localDocs = computeViews(docs, overlays, Collections.emptySet());
    return new LocalDocumentsResult(largestBatchId, localDocs);
}
Also used : DocumentKey(com.google.firebase.firestore.model.DocumentKey) MutableDocument(com.google.firebase.firestore.model.MutableDocument) Overlay(com.google.firebase.firestore.model.mutation.Overlay) Document(com.google.firebase.firestore.model.Document) MutableDocument(com.google.firebase.firestore.model.MutableDocument)

Example 3 with DocumentKey

use of com.google.firebase.firestore.model.DocumentKey in project firebase-android-sdk by firebase.

the class LocalStore method releaseTarget.

/**
 * Unpin all the documents associated with the given target.
 *
 * <p>Releasing a non-existing target is an error.
 */
public void releaseTarget(int targetId) {
    persistence.runTransaction("Release target", () -> {
        TargetData targetData = queryDataByTarget.get(targetId);
        hardAssert(targetData != null, "Tried to release nonexistent target: %s", targetId);
        // References for documents sent via Watch are automatically removed when we delete a
        // query's target data from the reference delegate. Since this does not remove references
        // for locally mutated documents, we have to remove the target associations for these
        // documents manually.
        ImmutableSortedSet<DocumentKey> removedReferences = localViewReferences.removeReferencesForId(targetId);
        for (DocumentKey key : removedReferences) {
            persistence.getReferenceDelegate().removeReference(key);
        }
        // Note: This also updates the query cache
        persistence.getReferenceDelegate().removeTarget(targetData);
        queryDataByTarget.remove(targetId);
        targetIdByTarget.remove(targetData.getTarget());
    });
}
Also used : DocumentKey(com.google.firebase.firestore.model.DocumentKey)

Example 4 with DocumentKey

use of com.google.firebase.firestore.model.DocumentKey in project firebase-android-sdk by firebase.

the class LocalStore method handleUserChange.

// PORTING NOTE: no shutdown for LocalStore or persistence components on Android.
public ImmutableSortedMap<DocumentKey, Document> handleUserChange(User user) {
    // Swap out the mutation queue, grabbing the pending mutation batches before and after.
    List<MutationBatch> oldBatches = mutationQueue.getAllMutationBatches();
    initializeUserComponents(user);
    startIndexManager();
    startMutationQueue();
    List<MutationBatch> newBatches = mutationQueue.getAllMutationBatches();
    // Union the old/new changed keys.
    ImmutableSortedSet<DocumentKey> changedKeys = DocumentKey.emptyKeySet();
    for (List<MutationBatch> batches : asList(oldBatches, newBatches)) {
        for (MutationBatch batch : batches) {
            for (Mutation mutation : batch.getMutations()) {
                changedKeys = changedKeys.insert(mutation.getKey());
            }
        }
    }
    // Return the set of all (potentially) changed documents as the result of the user change.
    return localDocuments.getDocuments(changedKeys);
}
Also used : MutationBatch(com.google.firebase.firestore.model.mutation.MutationBatch) DocumentKey(com.google.firebase.firestore.model.DocumentKey) PatchMutation(com.google.firebase.firestore.model.mutation.PatchMutation) Mutation(com.google.firebase.firestore.model.mutation.Mutation)

Example 5 with DocumentKey

use of com.google.firebase.firestore.model.DocumentKey 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);
    });
}
Also used : ArrayList(java.util.ArrayList) Document(com.google.firebase.firestore.model.Document) MutableDocument(com.google.firebase.firestore.model.MutableDocument) Timestamp(com.google.firebase.Timestamp) ObjectValue(com.google.firebase.firestore.model.ObjectValue) MutationBatch(com.google.firebase.firestore.model.mutation.MutationBatch) DocumentKey(com.google.firebase.firestore.model.DocumentKey) PatchMutation(com.google.firebase.firestore.model.mutation.PatchMutation) PatchMutation(com.google.firebase.firestore.model.mutation.PatchMutation) Mutation(com.google.firebase.firestore.model.mutation.Mutation) HashSet(java.util.HashSet)

Aggregations

DocumentKey (com.google.firebase.firestore.model.DocumentKey)134 MutableDocument (com.google.firebase.firestore.model.MutableDocument)52 Test (org.junit.Test)36 HashMap (java.util.HashMap)29 ArrayList (java.util.ArrayList)25 Document (com.google.firebase.firestore.model.Document)23 SnapshotVersion (com.google.firebase.firestore.model.SnapshotVersion)16 Mutation (com.google.firebase.firestore.model.mutation.Mutation)15 Map (java.util.Map)15 ResourcePath (com.google.firebase.firestore.model.ResourcePath)13 MutationBatch (com.google.firebase.firestore.model.mutation.MutationBatch)11 HashSet (java.util.HashSet)11 Overlay (com.google.firebase.firestore.model.mutation.Overlay)10 ImmutableSortedMap (com.google.firebase.database.collection.ImmutableSortedMap)9 TestUtil.patchMutation (com.google.firebase.firestore.testutil.TestUtil.patchMutation)7 TestUtil.setMutation (com.google.firebase.firestore.testutil.TestUtil.setMutation)7 ByteString (com.google.protobuf.ByteString)7 Query (com.google.firebase.firestore.core.Query)6 ObjectValue (com.google.firebase.firestore.model.ObjectValue)6 Timestamp (com.google.firebase.Timestamp)5