예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #5
0
        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.");
        }