use of com.google.firebase.Timestamp 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.Timestamp in project firebase-android-sdk by firebase.
the class LocalSerializer method decodeMutationBatch.
/**
* Decodes a WriteBatch proto into a MutationBatch model.
*/
MutationBatch decodeMutationBatch(com.google.firebase.firestore.proto.WriteBatch batch) {
int batchId = batch.getBatchId();
Timestamp localWriteTime = rpcSerializer.decodeTimestamp(batch.getLocalWriteTime());
int baseMutationsCount = batch.getBaseWritesCount();
List<Mutation> baseMutations = new ArrayList<>(baseMutationsCount);
for (int i = 0; i < baseMutationsCount; i++) {
baseMutations.add(rpcSerializer.decodeMutation(batch.getBaseWrites(i)));
}
List<Mutation> mutations = new ArrayList<>(batch.getWritesCount());
// TODO(b/174608374): Remove this code once we perform a schema migration.
for (int i = 0; i < batch.getWritesCount(); ++i) {
Write currentMutation = batch.getWrites(i);
boolean hasTransform = i + 1 < batch.getWritesCount() && batch.getWrites(i + 1).hasTransform();
if (hasTransform) {
hardAssert(batch.getWrites(i).hasUpdate(), "TransformMutation should be preceded by a patch or set mutation");
Builder newMutationBuilder = Write.newBuilder(currentMutation);
Write transformMutation = batch.getWrites(i + 1);
for (FieldTransform fieldTransform : transformMutation.getTransform().getFieldTransformsList()) {
newMutationBuilder.addUpdateTransforms(fieldTransform);
}
mutations.add(rpcSerializer.decodeMutation(newMutationBuilder.build()));
++i;
} else {
mutations.add(rpcSerializer.decodeMutation(currentMutation));
}
}
return new MutationBatch(batchId, localWriteTime, baseMutations, mutations);
}
use of com.google.firebase.Timestamp in project firebase-android-sdk by firebase.
the class SQLiteIndexManager method start.
@Override
public void start() {
Map<Integer, FieldIndex.IndexState> indexStates = new HashMap<>();
// Fetch all index states if persisted for the user. These states contain per user information
// on how up to date the index is.
db.query("SELECT index_id, sequence_number, read_time_seconds, read_time_nanos, document_key, " + "largest_batch_id FROM index_state WHERE uid = ?").binding(uid).forEach(row -> {
int indexId = row.getInt(0);
long sequenceNumber = row.getLong(1);
SnapshotVersion readTime = new SnapshotVersion(new Timestamp(row.getLong(2), row.getInt(3)));
DocumentKey documentKey = DocumentKey.fromPath(EncodedPath.decodeResourcePath(row.getString(4)));
int largestBatchId = row.getInt(5);
indexStates.put(indexId, FieldIndex.IndexState.create(sequenceNumber, readTime, documentKey, largestBatchId));
});
// Fetch all indices and combine with user's index state if available.
db.query("SELECT index_id, collection_group, index_proto FROM index_configuration").forEach(row -> {
try {
int indexId = row.getInt(0);
String collectionGroup = row.getString(1);
List<FieldIndex.Segment> segments = serializer.decodeFieldIndexSegments(Index.parseFrom(row.getBlob(2)));
// If we fetched an index state for the user above, combine it with this index.
// We use the default state if we don't have an index state (e.g. the index was
// created while a different user as logged in).
FieldIndex.IndexState indexState = indexStates.containsKey(indexId) ? indexStates.get(indexId) : FieldIndex.INITIAL_STATE;
FieldIndex fieldIndex = FieldIndex.create(indexId, collectionGroup, segments, indexState);
// Store the index and update `memoizedMaxIndexId` and `memoizedMaxSequenceNumber`.
memoizeIndex(fieldIndex);
} catch (InvalidProtocolBufferException e) {
throw fail("Failed to decode index: " + e);
}
});
started = true;
}
use of com.google.firebase.Timestamp in project firebase-android-sdk by firebase.
the class ServerTimestampTest method testPOJOSupport.
@Test
public void testPOJOSupport() {
DocumentReference ref = testDocument();
// Write empty pojo (nulls should turn into timestamps)
TimestampPOJO pojo = new TimestampPOJO();
waitFor(ref.set(pojo));
// Read it back (timestamps should have been populated).
pojo = waitFor(ref.get()).toObject(TimestampPOJO.class);
assertNull(pojo.a);
Timestamp resolvedTimestamp = pojo.timestamp1;
assertNotNull(resolvedTimestamp);
assertEquals(resolvedTimestamp, pojo.timestamp2);
// Write it back; timestamps shouldn't change since they're non-null.
pojo.a = 42L;
waitFor(ref.set(pojo));
// And read it back again; make sure the timestamps stayed the same.
pojo = waitFor(ref.get()).toObject(TimestampPOJO.class);
assertEquals((Long) 42L, pojo.a);
assertEquals(resolvedTimestamp, pojo.timestamp1);
assertEquals(resolvedTimestamp, pojo.timestamp2);
}
use of com.google.firebase.Timestamp in project firebase-android-sdk by firebase.
the class ServerTimestampTest method verifyTimestampsUsePreviousValue.
/**
* Verifies a snapshot containing setData but using the previous field value for the timestamps.
*/
private void verifyTimestampsUsePreviousValue(DocumentSnapshot current, @Nullable DocumentSnapshot previous) {
assertTrue(current.exists());
if (previous != null) {
Timestamp when = previous.getTimestamp("when");
assertNotNull(when);
assertEquals(expectedDataWithTimestamp(when), current.getData(ServerTimestampBehavior.PREVIOUS));
} else {
assertEquals(expectedDataWithTimestamp(null), current.getData(ServerTimestampBehavior.PREVIOUS));
}
}
Aggregations