public async Task RapidRetentionAndRollup()
        {
            using (var store = GetDocumentStore())
            {
                var raw = new RawTimeSeriesPolicy(TimeValue.FromSeconds(15));

                var p1 = new TimeSeriesPolicy("By1", TimeValue.FromSeconds(1), raw.RetentionTime * 2);
                var p2 = new TimeSeriesPolicy("By2", TimeValue.FromSeconds(2), raw.RetentionTime * 3);
                var p3 = new TimeSeriesPolicy("By4", TimeValue.FromSeconds(4), raw.RetentionTime * 4);
                var p4 = new TimeSeriesPolicy("By8", TimeValue.FromSeconds(8), raw.RetentionTime * 5);

                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy>
                            {
                                p1, p2, p3, p4
                            }
                        },
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };

                var now      = DateTime.UtcNow;
                var baseline = now.AddSeconds(-15 * 3);
                var total    = ((TimeSpan)TimeValue.FromSeconds(15 * 3)).TotalMilliseconds;

                using (var session = store.OpenSession())
                {
                    session.Store(new User {
                        Name = "Karmel"
                    }, "users/karmel");

                    for (int i = 0; i <= total; i++)
                    {
                        session.TimeSeriesFor("users/karmel", "Heartrate")
                        .Append(baseline.AddMilliseconds(i), new[] { 29d * i, i }, "watches/fitbit");
                    }
                    session.SaveChanges();
                }

                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                WaitForUserToContinueTheTest(store);

                await Task.Delay((TimeSpan)(p4.RetentionTime + TimeValue.FromSeconds(10)));

                // nothing should be left

                using (var session = store.OpenSession())
                {
                    var user = session.Load <User>("users/karmel");
                    Assert.Equal(0, session.Advanced.GetTimeSeriesFor(user)?.Count ?? 0);
                }
            }
        }
Пример #2
0
 public RollupTimeSeriesCommandDto(TimeSeriesConfiguration configuration, DateTime now, List <RollupState> states, bool isFirstInTopology)
 {
     _configuration     = configuration;
     _now               = now;
     _states            = states;
     _isFirstInTopology = isFirstInTopology;
 }
Пример #3
0
 internal RollupTimeSeriesCommand(TimeSeriesConfiguration configuration, DateTime now, List <RollupState> states, bool isFirstInTopology)
 {
     _configuration     = configuration;
     _now               = now;
     _states            = states;
     _isFirstInTopology = isFirstInTopology;
     _logger            = LoggingSource.Instance.GetLogger <TimeSeriesRollups>(nameof(RollupTimeSeriesCommand));
 }
Пример #4
0
        public async Task TimeSeriesLinqQuery_CanUseSimpleCallExpressionInName()
        {
            using (var store = GetDocumentStore())
            {
                var timeSeries = "HeartRate";

                var retention = TimeValue.FromHours(48);
                var p         = new TimeSeriesPolicy("ByHour", TimeValue.FromHours(1), TimeValue.FromHours(24));

                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = new RawTimeSeriesPolicy(TimeValue.FromHours(96)),
                            Policies  = new List <TimeSeriesPolicy> {
                                p
                            }
                        }
                    }
                };
                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                var baseline = DateTime.UtcNow.Add(-retention * 2);

                using (var session = store.OpenSession())
                {
                    session.Store(new User(), DocId);
                    var timeSeriesFor = session.TimeSeriesFor(DocId, timeSeries);

                    for (int i = 0; i < 100; i++)
                    {
                        timeSeriesFor.Append(baseline.AddHours(i), 29 * i, "watches/fitbit");
                    }
                    session.SaveChanges();
                }

                var database = await Databases.GetDocumentDatabaseInstanceFor(store);

                await TimeSeries.WaitForPolicyRunnerAsync(database);


                using (var session = store.OpenSession())
                {
                    // todo aviv : remove the single quotes from name when RavenDB-15792 is fixed
                    var q = session.Query <User>()
                            .Where(u => u.Id == DocId)
                            .Select(u => RavenQuery.TimeSeries(u, $"'{p.GetTimeSeriesName(timeSeries)}'")
                                    .ToList());

                    var result = q.First();

                    Assert.Equal(24, result.Count);
                }
            }
        }
Пример #5
0
 private void WriteTimeSeries(TimeSeriesConfiguration timeSeries)
 {
     if (timeSeries == null)
     {
         _writer.WriteNull();
         return;
     }
     _context.Write(_writer, timeSeries.ToJson());
 }
Пример #6
0
        public async Task ValidateCorrectRetentionAndGet(int minutesOffset)
        {
            using (var store = GetDocumentStore())
            {
                var raw = new RawTimeSeriesPolicy(TimeSpan.FromHours(24));

                var p1 = new TimeSeriesPolicy("By6Hours", TimeSpan.FromHours(6), raw.RetentionTime * 4);
                var p2 = new TimeSeriesPolicy("By1Day", TimeSpan.FromDays(1), raw.RetentionTime * 5);
                var p3 = new TimeSeriesPolicy("By30Minutes", TimeSpan.FromMinutes(30), raw.RetentionTime * 2);
                var p4 = new TimeSeriesPolicy("By1Hour", TimeSpan.FromMinutes(60), raw.RetentionTime * 3);

                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy>
                            {
                                p1, p2, p3, p4
                            }
                        },
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };
                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                var database = await GetDocumentDatabaseInstanceFor(store);

                var now = new DateTime(2020, 4, 2).AddMinutes(minutesOffset);
                database.Time.UtcDateTime = () => now.AddMilliseconds(1);

                var baseline = now.AddDays(-12);
                var total    = TimeSpan.FromDays(12).TotalMinutes;

                using (var session = store.OpenSession())
                {
                    session.Store(new Core.Utils.Entities.User {
                        Name = "Karmel"
                    }, "users/karmel");
                    for (int i = 0; i <= total; i++)
                    {
                        session.TimeSeriesFor("users/karmel", "Heartrate")
                        .Append(baseline.AddMinutes(i), i, "watches/fitbit");
                    }
                    session.SaveChanges();
                }

                await database.TimeSeriesPolicyRunner.RunRollups();

                await database.TimeSeriesPolicyRunner.DoRetention();

                await QueryFromMultipleTimeSeries.VerifyFullPolicyExecution(store, config.Collections["Users"]);
            }
        }
Пример #7
0
        public TimeSeriesPolicyRunner(DocumentDatabase database, TimeSeriesConfiguration configuration) : base(database.Name, database.DatabaseShutdown)
        {
            _database = database;
            Configuration = configuration;
            if (configuration.Collections != null)
                Configuration.Collections =
                    new Dictionary<string, TimeSeriesCollectionConfiguration>(Configuration.Collections, StringComparer.OrdinalIgnoreCase);

            Configuration.InitializeRollupAndRetention();

            _checkFrequency = Configuration.PolicyCheckFrequency ?? TimeSeriesConfiguration.DefaultPolicyCheckFrequency;
        }
Пример #8
0
        public StronglyTypedRavenSettings(NameValueCollection settings)
        {
            Replication = new ReplicationConfiguration();
            Voron       = new VoronConfiguration();
            Esent       = new EsentConfiguration();
            Prefetcher  = new PrefetcherConfiguration();
            FileSystem  = new FileSystemConfiguration();
            Counter     = new CounterConfiguration();
            TimeSeries  = new TimeSeriesConfiguration();
            Encryption  = new EncryptionConfiguration();
            Indexing    = new IndexingConfiguration();
            WebSockets  = new WebSocketsConfiguration();
            Cluster     = new ClusterConfiguration();
            Monitoring  = new MonitoringConfiguration();
            Studio      = new StudioConfiguration();

            this.settings = settings;
        }
Пример #9
0
        public RavenConfiguration()
        {
            Settings = new NameValueCollection(StringComparer.OrdinalIgnoreCase);

            Core = new CoreConfiguration(this);

            FileSystem = new FileSystemConfiguration(Core);
            Counter    = new CounterConfiguration(Core);
            TimeSeries = new TimeSeriesConfiguration(Core);

            Replication = new ReplicationConfiguration();
            Prefetcher  = new PrefetcherConfiguration();
            Storage     = new StorageConfiguration();
            Encryption  = new EncryptionConfiguration();
            Indexing    = new IndexingConfiguration();
            WebSockets  = new WebSocketsConfiguration();
            Cluster     = new ClusterConfiguration();
            Monitoring  = new MonitoringConfiguration();
            Queries     = new QueryConfiguration();
            Patching    = new PatchingConfiguration();
            BulkInsert  = new BulkInsertConfiguration();
            Server      = new ServerConfiguration();
            Memory      = new MemoryConfiguration();
            Expiration  = new ExpirationBundleConfiguration();
            Versioning  = new VersioningBundleConfiguration();
            Studio      = new StudioConfiguration();
            Tenants     = new TenantConfiguration();
            Licensing   = new LicenseConfiguration();
            Quotas      = new QuotasBundleConfiguration();

            IndexingClassifier = new DefaultIndexingClassifier();

            Catalog = new AggregateCatalog(CurrentAssemblyCatalog);

            Catalog.Changed += (sender, args) => ResetContainer();
        }
Пример #10
0
        public async Task CanIndexRollups()
        {
            using (var store = GetDocumentStore())
            {
                var raw = new RawTimeSeriesPolicy(TimeValue.FromHours(24));

                var p1 = new TimeSeriesPolicy("By6Hours", TimeValue.FromHours(6), raw.RetentionTime * 4);
                var p2 = new TimeSeriesPolicy("By1Day", TimeValue.FromDays(1), raw.RetentionTime * 5);
                var p3 = new TimeSeriesPolicy("By30Minutes", TimeValue.FromMinutes(30), raw.RetentionTime * 2);
                var p4 = new TimeSeriesPolicy("By1Hour", TimeValue.FromMinutes(60), raw.RetentionTime * 3);

                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy>
                            {
                                p1, p2, p3, p4
                            }
                        },
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };
                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                var database = await Databases.GetDocumentDatabaseInstanceFor(store);

                var now        = DateTime.UtcNow;
                var nowSeconds = now.Second;
                now = now.AddSeconds(-nowSeconds);
                database.Time.UtcDateTime = () => DateTime.UtcNow.AddSeconds(-nowSeconds);

                var baseline = now.AddDays(-12);
                var total    = ((TimeSpan)TimeValue.FromDays(12)).TotalMinutes;

                await new TimeSeriesIndex().ExecuteAsync(store);

                using (var session = store.OpenSession())
                {
                    session.Store(new User {
                        Name = "Karmel"
                    }, "users/karmel");
                    for (int i = 0; i <= total; i++)
                    {
                        session.TimeSeriesFor("users/karmel", "Heartrate")
                        .Append(baseline.AddMinutes(i), new[] { 29d * i, i }, "watches/fitbit");
                    }
                    session.SaveChanges();
                }

                await TimeSeries.WaitForPolicyRunnerAsync(database);

                await TimeSeries.VerifyPolicyExecutionAsync(store, config.Collections["Users"], 4, policies : new List <TimeSeriesPolicy> {
                    p1
                });

                await TimeSeries.VerifyPolicyExecutionAsync(store, config.Collections["Users"], 5, policies : new List <TimeSeriesPolicy> {
                    p2
                });

                await TimeSeries.VerifyPolicyExecutionAsync(store, config.Collections["Users"], 2, policies : new List <TimeSeriesPolicy> {
                    p3
                });

                await TimeSeries.VerifyPolicyExecutionAsync(store, config.Collections["Users"], 3, policies : new List <TimeSeriesPolicy> {
                    p4
                });

                Indexes.WaitForIndexing(store);
                RavenTestHelper.AssertNoIndexErrors(store);

                using (var session = store.OpenSession())
                {
                    var user = session.Load <User>("users/karmel");

                    var count = session
                                .TimeSeriesFor(user, "Heartrate")
                                .Get(DateTime.MinValue, DateTime.MaxValue)
                                .Count(entry => entry.IsRollup == false);

                    count += session
                             .TimeSeriesFor(user, "Heartrate@By6Hours")
                             .Get(DateTime.MinValue, DateTime.MaxValue)
                             .Count();

                    count += session
                             .TimeSeriesFor(user, "Heartrate@By1Day")
                             .Get(DateTime.MinValue, DateTime.MaxValue)
                             .Count();

                    count += session
                             .TimeSeriesFor(user, "Heartrate@By30Minutes")
                             .Get(DateTime.MinValue, DateTime.MaxValue)
                             .Count();

                    count += session
                             .TimeSeriesFor(user, "Heartrate@By1Hour")
                             .Get(DateTime.MinValue, DateTime.MaxValue)
                             .Count();

                    var results = session.Query <TimeSeriesIndex.Result, TimeSeriesIndex>()
                                  .ToList();

                    Assert.True(count == results.Count, $"Test time = {now}");
                }
            }
        }
Пример #11
0
        public async Task CanIncludeTypedTimeSeries_Rollup()
        {
            using (var store = GetDocumentStore())
            {
                var raw = new RawTimeSeriesPolicy(TimeSpan.FromHours(24));

                var p1 = new TimeSeriesPolicy("By6Hours", TimeSpan.FromHours(6), raw.RetentionTime * 4);
                var p2 = new TimeSeriesPolicy("By1Day", TimeSpan.FromDays(1), raw.RetentionTime * 5);
                var p3 = new TimeSeriesPolicy("By30Minutes", TimeSpan.FromMinutes(30), raw.RetentionTime * 2);
                var p4 = new TimeSeriesPolicy("By1Hour", TimeSpan.FromMinutes(60), raw.RetentionTime * 3);

                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy>
                            {
                                p1, p2, p3, p4
                            }
                        },
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };
                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                await store.TimeSeries.RegisterAsync <User, StockPrice>();

                var database = await Databases.GetDocumentDatabaseInstanceFor(store);

                var now        = DateTime.UtcNow;
                var nowMinutes = now.Minute;
                now = now.AddMinutes(-nowMinutes);
                database.Time.UtcDateTime = () => DateTime.UtcNow.AddMinutes(-nowMinutes);

                var baseline = now.AddDays(-12);
                var total    = TimeSpan.FromDays(12).TotalMinutes;

                using (var session = store.OpenSession())
                {
                    session.Store(new User {
                        Name = "Karmel"
                    }, "users/karmel");
                    var ts    = session.TimeSeriesFor <StockPrice>("users/karmel");
                    var entry = new StockPrice();
                    for (int i = 0; i <= total; i++)
                    {
                        entry.Open   = i;
                        entry.Close  = i + 100_000;
                        entry.High   = i + 200_000;
                        entry.Low    = i + 300_000;
                        entry.Volume = i + 400_000;
                        ts.Append(baseline.AddMinutes(i), entry, "watches/fitbit");
                    }
                    session.SaveChanges();
                }

                await database.TimeSeriesPolicyRunner.RunRollups();

                await database.TimeSeriesPolicyRunner.DoRetention();

                await TimeSeries.VerifyPolicyExecutionAsync(store, config.Collections["Users"], 12, rawName : "StockPrices");

                using (var session = store.OpenSession())
                {
                    var user = session.Query <User>()
                               .Include(x => x.IncludeTimeSeries($"StockPrices@{p1.Name}"))
                               .First();

                    // should not go to server
                    var ts  = session.TimeSeriesRollupFor <StockPrice>(user.Id, p1.Name);
                    var res = ts.Get().ToList();
                    Assert.Equal(16, res.Count);
                    Assert.Equal(1, session.Advanced.NumberOfRequests);
                }
            }
        }
Пример #12
0
        public async Task MarkPolicyAfterRollup()
        {
            DefaultClusterSettings[RavenConfiguration.GetKey(x => x.Tombstones.CleanupInterval)] = 1.ToString();
            var cluster = await CreateRaftCluster(3, watcherCluster : true);

            using (var store = GetDocumentStore(new Options {
                Server = cluster.Leader, ReplicationFactor = 3, RunInMemory = false
            }))
            {
                var raw    = new RawTimeSeriesPolicy();
                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy> {
                                new TimeSeriesPolicy("ByMinute", TimeSpan.FromMinutes(10))
                            }
                        }
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };

                var record = await store.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(store.Database));

                var firstNode = record.Topology.Members[0];
                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                var now = new DateTime(2021, 6, 1, 10, 7, 29, DateTimeKind.Utc);
                foreach (var server in Servers)
                {
                    var database = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                    database.Time.UtcDateTime = () => now;
                }

                var baseline = now.Add(-TimeSpan.FromMinutes(15));

                using (var session = store.OpenSession())
                {
                    var id = "users/karmel/0";
                    session.Store(new User {
                        Name = "Karmel"
                    }, id);
                    for (int i = 0; i < 15; i++)
                    {
                        session.TimeSeriesFor(id, "Heartrate")
                        .Append(baseline.AddMinutes(i), i);
                    }

                    session.SaveChanges();
                }

                using (var session = store.OpenSession())
                {
                    session.Store(new User(), "marker");
                    session.SaveChanges();
                    Assert.True(await WaitForDocumentInClusterAsync <User>(cluster.Nodes, store.Database, "marker", null, TimeSpan.FromSeconds(15)));
                }

                var res = new Dictionary <string, int>();
                foreach (var server in Servers)
                {
                    var database = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                    var tss = database.DocumentsStorage.TimeSeriesStorage;
                    await database.TimeSeriesPolicyRunner.RunRollups();

                    var name = config.Collections["Users"].Policies[0].GetTimeSeriesName("Heartrate");
                    WaitForValue(() =>
                    {
                        using (var session = store.OpenSession())
                        {
                            var val = session.TimeSeriesFor("users/karmel/0", name)
                                      .Get(DateTime.MinValue, DateTime.MaxValue);
                            return(val != null);
                        }
                    }, true);

                    using (var session = store.OpenSession())
                    {
                        var val = session.TimeSeriesFor("users/karmel/0", name)
                                  .Get(DateTime.MinValue, DateTime.MaxValue).Length;
                        res.Add(server.ServerStore.NodeTag, val);
                        Assert.True(val > 0);
                    }
                }

                record = await store.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(store.Database));

                var firstNode2 = record.Topology.Members[0];
                Assert.Equal(firstNode2, firstNode);

                record = store.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(store.Database)).Result;
                var list = record.Topology.Members;
                list.Reverse();
                await store.Maintenance.Server.SendAsync(new ReorderDatabaseMembersOperation(store.Database, list));

                record = await store.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(store.Database));

                firstNode2 = record.Topology.Members[0];
                Assert.NotEqual(firstNode2, firstNode);

                await Task.Delay(1000);

                foreach (var server in Servers)
                {
                    var database = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                    database.Time.UtcDateTime = () => now.AddMinutes(10);
                    await database.TimeSeriesPolicyRunner.RunRollups();
                }

                foreach (var server in Servers)
                {
                    WaitForValue(() =>
                    {
                        using (var session = store.OpenSession())
                        {
                            var name = config.Collections["Users"].Policies[0].GetTimeSeriesName("Heartrate");
                            var val  = session.TimeSeriesFor("users/karmel/0", name)
                                       .Get(DateTime.MinValue, DateTime.MaxValue);
                            return(val.Length > res[server.ServerStore.NodeTag]);
                        }
                    }, true);
                }

                using (var session = store.OpenSession())
                {
                    var name = config.Collections["Users"].Policies[0].GetTimeSeriesName("Heartrate");
                    var val  = session.TimeSeriesFor("users/karmel/0", name)
                               .Get(DateTime.MinValue, DateTime.MaxValue);

                    Assert.True(val.Length > res[Servers[0].ServerStore.NodeTag]);
                }

                record     = store.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(store.Database)).Result;
                firstNode2 = record.Topology.Members[0];
                Assert.NotEqual(firstNode2, firstNode);
            }
        }
        public async Task RapidRetentionAndRollupInACluster()
        {
            var cluster = await CreateRaftCluster(3, watcherCluster : true);

            using (var store = GetDocumentStore(new Options
            {
                Server = cluster.Leader,
                ReplicationFactor = 3
            }))
            {
                var raw = new RawTimeSeriesPolicy(TimeValue.FromSeconds(15));

                var p1 = new TimeSeriesPolicy("By1", TimeValue.FromSeconds(1), raw.RetentionTime * 2);
                var p2 = new TimeSeriesPolicy("By2", TimeValue.FromSeconds(2), raw.RetentionTime * 3);
                var p3 = new TimeSeriesPolicy("By4", TimeValue.FromSeconds(4), raw.RetentionTime * 4);
                var p4 = new TimeSeriesPolicy("By8", TimeValue.FromSeconds(8), raw.RetentionTime * 5);

                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy>
                            {
                                p1, p2, p3, p4
                            }
                        },
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };

                var now      = DateTime.UtcNow;
                var baseline = now.AddSeconds(-15 * 3);
                var total    = ((TimeSpan)TimeValue.FromSeconds(15 * 3)).TotalMilliseconds;

                using (var session = store.OpenSession())
                {
                    session.Store(new User {
                        Name = "Karmel"
                    }, "users/karmel");

                    for (int i = 0; i <= total; i++)
                    {
                        session.TimeSeriesFor("users/karmel", "Heartrate")
                        .Append(baseline.AddMilliseconds(i), new[] { 29d * i, i }, "watches/fitbit");
                    }
                    session.SaveChanges();

                    session.Store(new User {
                        Name = "Karmel"
                    }, "marker");
                    session.SaveChanges();

                    Assert.True(await WaitForDocumentInClusterAsync <User>((DocumentSession)session, "marker", null, TimeSpan.FromSeconds(15)));
                }

                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                await Task.Delay((TimeSpan)(p4.RetentionTime * 2));

                // nothing should be left

                foreach (var node in cluster.Nodes)
                {
                    using (var nodeStore = GetDocumentStore(new Options
                    {
                        Server = node,
                        CreateDatabase = false,
                        DeleteDatabaseOnDispose = false,
                        ModifyDocumentStore = s => s.Conventions = new DocumentConventions
                        {
                            DisableTopologyUpdates = true
                        },
                        ModifyDatabaseName = _ => store.Database
                    }))
                    {
                        using (var session = nodeStore.OpenSession())
                        {
                            var user = session.Load <User>("users/karmel");
                            Assert.Equal(0, session.Advanced.GetTimeSeriesFor(user)?.Count ?? 0);
                            var db = await node.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                            await TimeSeriesReplicationTests.AssertNoLeftOvers(db);
                        }
                    }
                }
            }
        }
Пример #14
0
        public async Task SingleResultTest()
        {
            DefaultClusterSettings[RavenConfiguration.GetKey(x => x.Tombstones.CleanupInterval)] = 1.ToString();
            var cluster = await CreateRaftCluster(3, watcherCluster : true);

            using (var store = GetDocumentStore(new Options {
                Server = cluster.Leader, ReplicationFactor = 3, RunInMemory = false
            }))
            {
                var raw    = new RawTimeSeriesPolicy();
                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy> {
                                new TimeSeriesPolicy("ByMinute", TimeSpan.FromSeconds(60))
                            }
                        }
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };

                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                var now = DateTime.UtcNow;

                var baseline = now.AddSeconds(-120);
                using (var session = store.OpenSession())
                {
                    var id = "users/karmel/0";
                    session.Store(new User {
                        Name = "Karmel"
                    }, id);
                    for (int i = 0; i < 120; i++)
                    {
                        session.TimeSeriesFor(id, "Heartrate")
                        .Append(baseline.AddSeconds(i), i);
                    }

                    session.SaveChanges();
                }

                using (var session = store.OpenSession())
                {
                    session.Store(new User(), "marker");
                    session.SaveChanges();
                    Assert.True(await WaitForDocumentInClusterAsync <User>(cluster.Nodes, store.Database, "marker", null, TimeSpan.FromSeconds(15)));
                }

                var database = await Servers[0].ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);
                using (database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                {
                    using (var tx = ctx.OpenReadTransaction())
                    {
                        var name   = config.Collections["Users"].Policies[0].GetTimeSeriesName("Heartrate");
                        var reader = database.DocumentsStorage.TimeSeriesStorage.GetReader(ctx, "users/karmel/0", "Heartrate", baseline.AddSeconds(120), DateTime.MaxValue);
                        Assert.True(reader.Last() == null);
                    }
                }
            }
        }
Пример #15
0
        public async Task PostCreateSampleData()
        {
            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
            {
                using (context.OpenReadTransaction())
                {
                    foreach (var collection in Database.DocumentsStorage.GetCollections(context))
                    {
                        if (collection.Count > 0)
                        {
                            throw new InvalidOperationException("You cannot create sample data in a database that already contains documents");
                        }
                    }
                }

                var operateOnTypesAsString = GetStringValuesQueryString("operateOnTypes", required: false);
                var operateOnTypes         = GetOperateOnTypes(operateOnTypesAsString);

                if (operateOnTypes.HasFlag(DatabaseItemType.RevisionDocuments))
                {
                    var editRevisions = new EditRevisionsConfigurationCommand(new RevisionsConfiguration
                    {
                        Collections = new Dictionary <string, RevisionsCollectionConfiguration>
                        {
                            ["Orders"] = new RevisionsCollectionConfiguration
                            {
                                Disabled = false
                            }
                        }
                    }, Database.Name, GetRaftRequestIdFromQuery() + "/revisions");
                    var(index, _) = await ServerStore.SendToLeaderAsync(editRevisions);

                    await Database.RachisLogIndexNotifications.WaitForIndexNotification(index, Database.ServerStore.Engine.OperationTimeout);
                }

                if (operateOnTypes.HasFlag(DatabaseItemType.TimeSeries))
                {
                    var tsConfig = new TimeSeriesConfiguration
                    {
                        NamedValues = new Dictionary <string, Dictionary <string, string[]> >
                        {
                            ["Companies"] = new Dictionary <string, string[]>
                            {
                                ["StockPrices"] = new[] { "Open", "Close", "High", "Low", "Volume" }
                            },
                            ["Employees"] = new Dictionary <string, string[]>
                            {
                                ["HeartRates"] = new[] { "BPM" }
                            }
                        }
                    };
                    var editTimeSeries = new EditTimeSeriesConfigurationCommand(tsConfig, Database.Name, GetRaftRequestIdFromQuery() + "/time-series");
                    var(index, _) = await ServerStore.SendToLeaderAsync(editTimeSeries);

                    await Database.RachisLogIndexNotifications.WaitForIndexNotification(index, Database.ServerStore.Engine.OperationTimeout);
                }

                await using (var sampleData = typeof(SampleDataHandler).Assembly
                                              .GetManifestResourceStream("Raven.Server.Web.Studio.EmbeddedData.Northwind.ravendbdump"))
                {
                    await using (var stream = new GZipStream(sampleData, CompressionMode.Decompress))
                        using (var source = new StreamSource(stream, context, Database))
                        {
                            var destination = new DatabaseDestination(Database);

                            var smuggler = new DatabaseSmuggler(Database, source, destination, Database.Time,
                                                                options: new DatabaseSmugglerOptionsServerSide
                            {
                                OperateOnTypes       = operateOnTypes,
                                SkipRevisionCreation = true
                            });

                            await smuggler.ExecuteAsync();
                        }
                }

                await NoContent();
            }
Пример #16
0
        public void Examples()
        {
            var store = new DocumentStore
            {
                Urls     = new[] { "http://*****:*****@DailyRollupForOneYear");

                //Create local instance of the rollup time-series - second method:
                //using the rollup policy itself and the raw time-series' name
                var rollupTimeSeries2 = session.TimeSeriesFor("sales/1",
                                                              dailyRollup.GetTimeSeriesName("rawSales"));

                //Retrieve all the data from both time-series
                var rawData    = rawTS.Get(DateTime.MinValue, DateTime.MaxValue).ToList();
                var rollupData = dailyRollupTS.Get(DateTime.MinValue, DateTime.MaxValue).ToList();
                #endregion
            }
        }
Пример #17
0
        public async Task CanWorkWithRollupTimeSeries2()
        {
            using (var store = GetDocumentStore())
            {
                var raw = new RawTimeSeriesPolicy(TimeSpan.FromHours(24));

                var p1 = new TimeSeriesPolicy("By6Hours", TimeSpan.FromHours(6), raw.RetentionTime * 4);
                var p2 = new TimeSeriesPolicy("By1Day", TimeSpan.FromDays(1), raw.RetentionTime * 5);
                var p3 = new TimeSeriesPolicy("By30Minutes", TimeSpan.FromMinutes(30), raw.RetentionTime * 2);
                var p4 = new TimeSeriesPolicy("By1Hour", TimeSpan.FromMinutes(60), raw.RetentionTime * 3);

                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy>
                            {
                                p1, p2, p3, p4
                            }
                        },
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };
                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                await store.TimeSeries.RegisterAsync <User, StockPrice>();

                var database = await Databases.GetDocumentDatabaseInstanceFor(store);

                var now      = DateTime.UtcNow;
                var baseline = now.AddDays(-12);
                var total    = TimeSpan.FromDays(12).TotalMinutes;

                using (var session = store.OpenSession())
                {
                    session.Store(new User {
                        Name = "Karmel"
                    }, "users/karmel");
                    var ts    = session.TimeSeriesFor <StockPrice>("users/karmel");
                    var entry = new StockPrice();
                    for (int i = 0; i <= total; i++)
                    {
                        entry.Open   = i;
                        entry.Close  = i + 100_000;
                        entry.High   = i + 200_000;
                        entry.Low    = i + 300_000;
                        entry.Volume = i + 400_000;
                        ts.Append(baseline.AddMinutes(i), entry, "watches/fitbit");
                    }
                    session.SaveChanges();
                }

                await database.TimeSeriesPolicyRunner.RunRollups();

                await database.TimeSeriesPolicyRunner.DoRetention();

                await TimeSeries.VerifyPolicyExecutionAsync(store, config.Collections["Users"], 12, rawName: "StockPrices");

                using (var session = store.OpenSession())
                {
                    var query = session.Query <User>()
                                .Select(u =>
                                        RavenQuery.TimeSeries <StockPrice>(u, "StockPrices").Select(x =>
                                                                                                    new {
                        First = x.First(),
                        Last  = x.Last(),
                        Min   = x.Min(),
                        Max   = x.Max(),
                        Sum   = x.Sum(),
                        Count = x.Count(),
                        Avg   = x.Average()
                    })
                                        .ToList());

                    var result = query.Single();

                    Assert.Equal(1, result.Results.Length);
                    var r = result.Results[0];
                    Assert.NotNull(r.First);
                    Assert.NotNull(r.Last);
                    Assert.NotNull(r.Min);
                    Assert.NotNull(r.Max);
                    Assert.NotNull(r.Sum);
                    Assert.NotNull(r.Count);
                    Assert.NotNull(r.Average);
                }

                using (var session = store.OpenSession())
                {
                    var query = session.Query <User>()
                                .Select(u =>
                                        RavenQuery.TimeSeries <StockPrice>(u, "StockPrices")
                                        .GroupBy(x => x.Hours(3))
                                        .Select(x =>
                                                new
                    {
                        First = x.First(),
                        Last  = x.Last(),
                        Min   = x.Min(),
                        Max   = x.Max(),
                        Sum   = x.Sum(),
                        Count = x.Count(),
                        Avg   = x.Average()
                    })
                                        .ToList());

                    var result = query.Single();
                    var r      = result.Results[0];
                    Assert.NotNull(r.First);
                    Assert.NotNull(r.Last);
                    Assert.NotNull(r.Min);
                    Assert.NotNull(r.Max);
                    Assert.NotNull(r.Sum);
                    Assert.NotNull(r.Count);
                    Assert.NotNull(r.Average);
                }

                using (var session = store.OpenSession())
                {
                    var ts1 = session.TimeSeriesRollupFor <StockPrice>("users/karmel", p1.Name);
                    var r   = ts1.Get().First();
                    Assert.NotNull(r.First);
                    Assert.NotNull(r.Last);
                    Assert.NotNull(r.Min);
                    Assert.NotNull(r.Max);
                    Assert.NotNull(r.Sum);
                    Assert.NotNull(r.Count);
                    Assert.NotNull(r.Average);
                }
            }
        }
Пример #18
0
        public async Task CanWorkWithRollupTimeSeries()
        {
            using (var store = GetDocumentStore())
            {
                var raw = new RawTimeSeriesPolicy(TimeSpan.FromHours(24));

                var p1 = new TimeSeriesPolicy("By6Hours", TimeSpan.FromHours(6), raw.RetentionTime * 4);
                var p2 = new TimeSeriesPolicy("By1Day", TimeSpan.FromDays(1), raw.RetentionTime * 5);
                var p3 = new TimeSeriesPolicy("By30Minutes", TimeSpan.FromMinutes(30), raw.RetentionTime * 2);
                var p4 = new TimeSeriesPolicy("By1Hour", TimeSpan.FromMinutes(60), raw.RetentionTime * 3);

                var config = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy>
                            {
                                p1, p2, p3, p4
                            }
                        },
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };
                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                await store.TimeSeries.RegisterAsync <User, StockPrice>();

                var database = await Databases.GetDocumentDatabaseInstanceFor(store);

                var now        = DateTime.UtcNow;
                var nowMinutes = now.Minute;
                now = now.AddMinutes(-nowMinutes);
                database.Time.UtcDateTime = () => DateTime.UtcNow.AddMinutes(-nowMinutes);

                var baseline = now.AddDays(-12);
                var total    = TimeSpan.FromDays(12).TotalMinutes;

                using (var session = store.OpenSession())
                {
                    session.Store(new User {
                        Name = "Karmel"
                    }, "users/karmel");
                    var ts    = session.TimeSeriesFor <StockPrice>("users/karmel");
                    var entry = new StockPrice();
                    for (int i = 0; i <= total; i++)
                    {
                        entry.Open   = i;
                        entry.Close  = i + 100_000;
                        entry.High   = i + 200_000;
                        entry.Low    = i + 300_000;
                        entry.Volume = i + 400_000;
                        ts.Append(baseline.AddMinutes(i), entry, "watches/fitbit");
                    }
                    session.SaveChanges();
                }

                await database.TimeSeriesPolicyRunner.RunRollups();

                await database.TimeSeriesPolicyRunner.DoRetention();

                await TimeSeries.VerifyPolicyExecutionAsync(store, config.Collections["Users"], 12, rawName: "StockPrices");

                using (var session = store.OpenSession())
                {
                    var query = session.Advanced.RawQuery <TimeSeriesRawResult <StockPrice> >(@"
declare timeseries out()
{
    from StockPrices
    between $start and $end
}
from Users as u
select out()
")
                                .AddParameter("start", baseline.AddDays(-1))
                                .AddParameter("end", now.AddDays(1));

                    var result = query.Single();
                    var count  = result.Results.Length;

                    Assert.Equal(5, result.Results[count - 1440].Values.Length);

                    foreach (var res in result.Results)
                    {
                        Assert.Equal(5, res.Values.Length);
                    }
                }

                using (var session = store.OpenSession())
                {
                    // test the same query using linq

                    var query = session.Query <User>()
                                .Select(u =>
                                        RavenQuery.TimeSeries <StockPrice>(u, "StockPrices", baseline.AddDays(-1), now.AddDays(1))
                                        .ToList());

                    var result = query.Single();
                    var count  = result.Results.Length;

                    Assert.Equal(5, result.Results[count - 1440].Values.Length);

                    foreach (var res in result.Results)
                    {
                        Assert.Equal(5, res.Values.Length);
                    }
                }

                now = DateTime.UtcNow;
                using (var session = store.OpenSession())
                {
                    var ts = session.TimeSeriesRollupFor <StockPrice>("users/karmel", p1.Name);
                    var a  = new TimeSeriesRollupEntry <StockPrice>(DateTime.Now)
                    {
                        Max = new StockPrice
                        {
                            Close = 1
                        }
                    };
                    ts.Append(a);
                    session.SaveChanges();
                }

                using (var session = store.OpenSession())
                {
                    var ts  = session.TimeSeriesRollupFor <StockPrice>("users/karmel", p1.Name);
                    var res = ts.Get(from: now.AddMilliseconds(-1)).ToList();
                    Assert.Equal(1, res.Count);
                    Assert.Equal(1, res[0].Max.Close);
                }
            }
        }
Пример #19
0
 public EditTimeSeriesConfigurationCommand(TimeSeriesConfiguration configuration, string databaseName, string uniqueRequestId) : base(databaseName, uniqueRequestId)
 {
     Configuration = configuration;
 }
Пример #20
0
        public async Task ManyTimeSeriesRetention()
        {
            DefaultClusterSettings[RavenConfiguration.GetKey(x => x.Tombstones.CleanupInterval)] = 1.ToString();
            var cluster = await CreateRaftCluster(3, watcherCluster : true);

            using (var store = GetDocumentStore(new Options
            {
                Server = cluster.Leader,
                ReplicationFactor = 3,
                RunInMemory = false
            }))
            {
                var retention = TimeSpan.FromSeconds(60);
                var raw       = new RawTimeSeriesPolicy(retention);
                var config    = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                            Policies  = new List <TimeSeriesPolicy>
                            {
                                new TimeSeriesPolicy("ByMinute", TimeSpan.FromSeconds(60))
                            }
                        }
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };

                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                for (int j = 0; j < 1024; j++)
                {
                    var now      = DateTime.UtcNow;
                    var baseline = now.Add(-retention * 2);
                    var total    = (int)retention.TotalSeconds * 2;

                    using (var session = store.OpenSession())
                    {
                        var id = "users/karmel/" + j;

                        session.Store(new User {
                            Name = "Karmel"
                        }, id);

                        for (int i = 0; i < total; i++)
                        {
                            session.TimeSeriesFor(id, "Heartrate")
                            .Append(baseline.AddSeconds(i), i);
                        }
                        session.SaveChanges();
                    }
                }

                using (var session = store.OpenSession())
                {
                    session.Store(new User(), "marker");
                    session.SaveChanges();
                    Assert.True(await WaitForDocumentInClusterAsync <User>(cluster.Nodes, store.Database, "marker", null, TimeSpan.FromSeconds(15)));
                }

                var sp = Stopwatch.StartNew();
                await Task.Delay(retention / 2);

                var check = true;
                while (check)
                {
                    Assert.True(sp.Elapsed < retention.Add(retention * 5), $"too long has passed {sp.Elapsed}, retention is {retention}");
                    await Task.Delay(200);

                    check = false;
                    foreach (var server in Servers)
                    {
                        var database = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                        var tss = database.DocumentsStorage.TimeSeriesStorage;

                        for (int j = 0; j < 1024; j++)
                        {
                            using (database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                                using (ctx.OpenReadTransaction())
                                {
                                    var id    = $"users/karmel/{j}";
                                    var stats = tss.Stats.GetStats(ctx, id, "Heartrate");

                                    TimeSeriesReader reader;
                                    if (stats == default || stats.Count == 0)
                                    {
                                        var name = config.Collections["Users"].Policies[0].GetTimeSeriesName("Heartrate");
                                        stats  = tss.Stats.GetStats(ctx, id, name);
                                        reader = tss.GetReader(ctx, id, name, DateTime.MinValue, DateTime.MaxValue);

                                        Assert.True(stats.Count > 0);
                                        Assert.Equal(stats.Start, reader.First().Timestamp, RavenTestHelper.DateTimeComparer.Instance);
                                        Assert.Equal(stats.End, reader.Last().Timestamp, RavenTestHelper.DateTimeComparer.Instance);
                                        continue;
                                    }
                                    check  = true;
                                    reader = tss.GetReader(ctx, id, "Heartrate", DateTime.MinValue, DateTime.MaxValue);
                                    Assert.Equal(stats.Start, reader.First().Timestamp, RavenTestHelper.DateTimeComparer.Instance);
                                    Assert.Equal(stats.End, reader.Last().Timestamp, RavenTestHelper.DateTimeComparer.Instance);
                                }
                        }
                    }
                }

                await EnsureNoReplicationLoop(Servers[0], store.Database);
                await EnsureNoReplicationLoop(Servers[1], store.Database);
                await EnsureNoReplicationLoop(Servers[2], store.Database);
            }
        }
Пример #21
0
        public async Task RapidRetention()
        {
            var cluster = await CreateRaftCluster(3);

            using (var store = GetDocumentStore(new Options
            {
                Server = cluster.Leader,
                ReplicationFactor = 3
            }))
            {
                var retention = TimeValue.FromSeconds(120);
                var raw       = new RawTimeSeriesPolicy(retention);
                var config    = new TimeSeriesConfiguration
                {
                    Collections = new Dictionary <string, TimeSeriesCollectionConfiguration>
                    {
                        ["Users"] = new TimeSeriesCollectionConfiguration
                        {
                            RawPolicy = raw,
                        }
                    },
                    PolicyCheckFrequency = TimeSpan.FromSeconds(1)
                };

                var now      = DateTime.UtcNow;
                var baseline = now.Add(-retention * 3);
                var total    = (int)((TimeSpan)retention).TotalMilliseconds * 3;

                using (var session = store.OpenSession())
                {
                    session.Store(new User {
                        Name = "Karmel"
                    }, "users/karmel");

                    for (int i = 0; i < total; i++)
                    {
                        session.TimeSeriesFor("users/karmel", "Heartrate")
                        .Append(baseline.AddMilliseconds(i), new[] { 29d * i, i, i * 0.01, i * 0.1 }, "watches/fitbit");
                    }
                    session.SaveChanges();

                    session.Store(new User(), "marker");
                    session.SaveChanges();

                    Assert.True(await WaitForDocumentInClusterAsync <User>(cluster.Nodes, store.Database, "marker", null, TimeSpan.FromSeconds(15)));
                }

                await store.Maintenance.SendAsync(new ConfigureTimeSeriesOperation(config));

                var sp = Stopwatch.StartNew();
                await Task.Delay((TimeSpan)retention / 2);

                var debug = new Dictionary <string, (long Count, DateTime Start, DateTime End)>();
                var check = true;
                while (check)
                {
                    Assert.True(sp.Elapsed < ((TimeSpan)retention).Add((TimeSpan)retention),
                                $"too long has passed {sp.Elapsed}, retention is {retention} {Environment.NewLine}" +
                                $"debug: {string.Join(',', debug.Select(kvp => $"{kvp.Key}: ({kvp.Value.Count},{kvp.Value.Start},{kvp.Value.End})"))}");

                    await Task.Delay(100);

                    check = false;
                    foreach (var server in Servers)
                    {
                        var database = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                        using (database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                            using (ctx.OpenReadTransaction())
                            {
                                var tss    = database.DocumentsStorage.TimeSeriesStorage;
                                var stats  = tss.Stats.GetStats(ctx, "users/karmel", "Heartrate");
                                var reader = tss.GetReader(ctx, "users/karmel", "Heartrate", DateTime.MinValue, DateTime.MaxValue);

                                if (stats.Count == 0)
                                {
                                    debug.Remove(server.ServerStore.NodeTag);
                                    continue;
                                }

                                check = true;
                                Assert.Equal(stats.Start, reader.First().Timestamp, RavenTestHelper.DateTimeComparer.Instance);
                                Assert.Equal(stats.End, reader.Last().Timestamp, RavenTestHelper.DateTimeComparer.Instance);
                                debug[server.ServerStore.NodeTag] = stats;
                            }
                    }
                }
                Assert.Empty(debug);
                Assert.True(sp.Elapsed < (TimeSpan)retention + (TimeSpan)retention);
                await Task.Delay(3000); // let the dust to settle

                await EnsureNoReplicationLoop(Servers[0], store.Database);
                await EnsureNoReplicationLoop(Servers[1], store.Database);
                await EnsureNoReplicationLoop(Servers[2], store.Database);

                foreach (var server in Servers)
                {
                    var database = await server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                    await TimeSeriesReplicationTests.AssertNoLeftOvers(database);
                }
            }
        }