public void Update_Single_Field_WithPrecondition() { var db = FirestoreDb.Create("project", "db", new FakeFirestoreClient()); var batch = db.StartBatch(); var doc = db.Document("col/doc"); batch.Update(doc, "x", "y", Precondition.LastUpdated(new Timestamp(1, 2))); var expectedWrite = new Write { CurrentDocument = new V1.Precondition { UpdateTime = CreateProtoTimestamp(1, 2) }, Update = new Document { Name = doc.Path, Fields = { { "x", CreateValue("y") } } }, UpdateMask = new DocumentMask { FieldPaths = { "x" } } }; AssertSingleWrite(batch, expectedWrite); }
public void Update_StringKeyedDictionary_WithPrecondition() { var db = FirestoreDb.Create("project", "db", new FakeFirestoreClient()); var batch = db.StartBatch(); var doc = db.Document("col/doc"); var updates = new Dictionary <string, object> { { "x", "y" } }; batch.Update(doc, updates, Precondition.LastUpdated(new Timestamp(1, 2))); var expectedWrite = new Write { CurrentDocument = new V1Beta1.Precondition { UpdateTime = CreateProtoTimestamp(1, 2) }, Update = new Document { Name = doc.Path, Fields = { { "x", CreateValue("y") } } }, UpdateMask = new DocumentMask { FieldPaths = { "x" } } }; AssertWrites(batch, (expectedWrite, true)); }
public void Equality() { // Note: timestamp choice can give false test failures, due to proto hash code computation. var timestamp1 = new Timestamp(10, 0); var timestamp2 = new Timestamp(10, 1); EqualityTester.AssertEqual(Precondition.None, equal: new[] { Precondition.None }, unequal: new[] { Precondition.MustExist, Precondition.MustNotExist, Precondition.LastUpdated(timestamp1) } ); EqualityTester.AssertEqual(Precondition.MustExist, equal: new[] { Precondition.MustExist }, unequal: new[] { Precondition.MustNotExist, Precondition.LastUpdated(timestamp1) } ); EqualityTester.AssertEqual(Precondition.MustNotExist, equal: new[] { Precondition.MustNotExist }, unequal: new[] { Precondition.LastUpdated(timestamp1) } ); EqualityTester.AssertEqual(Precondition.LastUpdated(timestamp1), equal: new[] { Precondition.LastUpdated(timestamp1) }, unequal: new[] { Precondition.LastUpdated(timestamp2) } ); }
public void LastUpdated() { var timestamp = new Timestamp(1, 5); var precondition = Precondition.LastUpdated(timestamp); Assert.Null(precondition.Exists); Assert.Equal(timestamp, precondition.LastUpdateTime); Assert.Equal(new V1.Precondition { UpdateTime = CreateProtoTimestamp(1, 5) }, precondition.Proto); }
public void Delete_WithPrecondition() { var db = FirestoreDb.Create("project", "db", new FakeFirestoreClient()); var batch = db.StartBatch(); var doc = db.Document("col/doc"); batch.Delete(doc, Precondition.LastUpdated(new Timestamp(1, 2))); var expectedWrite = new Write { Delete = doc.Path, CurrentDocument = new V1.Precondition { UpdateTime = CreateProtoTimestamp(1, 2) } }; AssertSingleWrite(batch, expectedWrite); }
/// <summary> /// Scans the Firestore collection for expired cache entries and /// deletes them. /// </summary> /// <param name="token">A cancellation token.</param> public async Task CollectGarbageAsync(CancellationToken token) { _logger.LogTrace("Begin garbage collection."); // Purge entries whose AbsoluteExpiration has passed. const int pageSize = 40; int batchSize; // Batches of cache entries to be deleted. var now = _clock.GetCurrentDateTimeUtc(); do { QuerySnapshot querySnapshot = await _cacheEntries.OrderByDescending("AbsoluteExpiration") .StartAfter(now) .Limit(pageSize) .GetSnapshotAsync(token) .ConfigureAwait(false); batchSize = 0; WriteBatch writeBatch = _cacheEntries.Database.StartBatch(); foreach (DocumentSnapshot docSnapshot in querySnapshot.Documents) { if (docSnapshot.ConvertTo <CacheDoc>().AbsoluteExpiration.HasValue) { writeBatch.Delete(docSnapshot.Reference, Precondition.LastUpdated( docSnapshot.UpdateTime.GetValueOrDefault())); batchSize += 1; } } if (batchSize > 0) { _logger.LogDebug("Collecting {0} cache entries.", batchSize); await writeBatch.CommitAsync(token).ConfigureAwait(false); } token.ThrowIfCancellationRequested(); } while (batchSize == pageSize); // Purge entries whose SlidingExpiration has passed. do { QuerySnapshot querySnapshot = await _cacheEntries.OrderBy("LastRefresh") .Limit(pageSize) .GetSnapshotAsync(token) .ConfigureAwait(false); batchSize = 0; WriteBatch writeBatch = _cacheEntries.Database.StartBatch(); foreach (DocumentSnapshot docSnapshot in querySnapshot.Documents) { CacheDoc doc = docSnapshot.ConvertTo <CacheDoc>(); if (doc.SlidingExpirationSeconds.HasValue) { var slidingExpiration = doc.LastRefresh.GetValueOrDefault() + TimeSpan.FromSeconds(doc.SlidingExpirationSeconds.Value); if (slidingExpiration < now) { writeBatch.Delete(docSnapshot.Reference, Precondition.LastUpdated( docSnapshot.UpdateTime.GetValueOrDefault())); batchSize += 1; } } } if (batchSize > 0) { _logger.LogDebug("Collecting {batchSize} cache entries.", batchSize); await writeBatch.CommitAsync(token).ConfigureAwait(false); } token.ThrowIfCancellationRequested(); } while (batchSize > 0); _logger.LogTrace("End garbage collection."); }