public async Task CanSnapshotSubscriptionState() { var(_, leader) = await CreateRaftCluster(1, watcherCluster : true); using (var store = GetDocumentStore(options: new Options { Server = leader })) { var sub = await store.Subscriptions.CreateAsync <User>(); var worker = store.Subscriptions.GetSubscriptionWorker <User>(sub); var waitForBatch = new ManualResetEvent(false); var t = worker.Run((batch) => { waitForBatch.WaitOne(TimeSpan.FromSeconds(15)); }); using (var session = store.OpenAsyncSession()) { await session.StoreAsync(new User()); await session.SaveChangesAsync(); } var database = await leader.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database); database.SubscriptionStorage.GetSubscriptionFromServerStore(sub); var server2 = GetNewServer(); var server2Url = server2.ServerStore.GetNodeHttpServerUrl(); Servers.Add(server2); using (var requestExecutor = ClusterRequestExecutor.CreateForSingleNode(leader.WebUrl, null)) using (requestExecutor.ContextPool.AllocateOperationContext(out var ctx)) { await requestExecutor.ExecuteAsync(new AddClusterNodeCommand(server2Url, watcher : true), ctx); var addDatabaseNode = new AddDatabaseNodeOperation(store.Database); await store.Maintenance.Server.SendAsync(addDatabaseNode); await WaitAndAssertForValueAsync(() => GetMembersCount(store), 2); } database = await server2.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database); var state = database.SubscriptionStorage.GetSubscriptionFromServerStore(sub); using (server2.ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context)) using (context.OpenReadTransaction()) { Assert.Single(SubscriptionStorage.GetResendItems(context, store.Database, state.SubscriptionId)); } waitForBatch.Set(); } }
public async Task CanSnapshotCompareExchangeTombstones() { var leader = await CreateRaftClusterAndGetLeader(1); using (var store = GetDocumentStore(options: new Options { Server = leader })) { using (var session = store.OpenAsyncSession(new SessionOptions { TransactionMode = TransactionMode.ClusterWide })) { session.Advanced.ClusterTransaction.CreateCompareExchangeValue("foo", "bar"); await session.SaveChangesAsync(); var result = await session.Advanced.ClusterTransaction.GetCompareExchangeValueAsync <string>("foo"); session.Advanced.ClusterTransaction.DeleteCompareExchangeValue(result); await session.SaveChangesAsync(); } var server2 = GetNewServer(); var server2Url = server2.ServerStore.GetNodeHttpServerUrl(); Servers.Add(server2); using (var requestExecutor = ClusterRequestExecutor.CreateForSingleNode(leader.WebUrl, null)) using (requestExecutor.ContextPool.AllocateOperationContext(out var ctx)) { await requestExecutor.ExecuteAsync(new AddClusterNodeCommand(server2Url, watcher : true), ctx); var addDatabaseNode = new AddDatabaseNodeOperation(store.Database); await store.Maintenance.Server.SendAsync(addDatabaseNode); } using (server2.ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext ctx)) using (ctx.OpenReadTransaction()) { Assert.True(server2.ServerStore.Cluster.HasCompareExchangeTombstones(ctx, store.Database)); } } }
public async Task CanSnapshotCompareExchangeWithExpiration() { var count = 45; var(_, leader) = await CreateRaftCluster(1, watcherCluster : true); using (var store = GetDocumentStore(options: new Options { Server = leader })) { var expiry = DateTime.Now.AddMinutes(2); var compareExchanges = new Dictionary <string, User>(); await CompareExchangeExpirationTest.AddCompareExchangesWithExpire(count, compareExchanges, store, expiry); await CompareExchangeExpirationTest.AssertCompareExchanges(compareExchanges, store, expiry); using (leader.ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context)) using (context.OpenReadTransaction()) { Assert.Equal(count, CompareExchangeExpirationStorage.GetExpiredValues(context, long.MaxValue).Count()); } var server2 = GetNewServer(); var server2Url = server2.ServerStore.GetNodeHttpServerUrl(); Servers.Add(server2); using (var requestExecutor = ClusterRequestExecutor.CreateForSingleNode(leader.WebUrl, null)) using (requestExecutor.ContextPool.AllocateOperationContext(out var ctx)) { await requestExecutor.ExecuteAsync(new AddClusterNodeCommand(server2Url, watcher : true), ctx); var addDatabaseNode = new AddDatabaseNodeOperation(store.Database); await store.Maintenance.Server.SendAsync(addDatabaseNode); } using (server2.ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context)) using (context.OpenReadTransaction()) { Assert.Equal(count, CompareExchangeExpirationStorage.GetExpiredValues(context, long.MaxValue).Count()); } var now = DateTime.UtcNow; leader.ServerStore.Observer.Time.UtcDateTime = () => now.AddMinutes(3); var leaderCount = WaitForValue(() => { using (leader.ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context)) using (context.OpenReadTransaction()) { return(CompareExchangeExpirationStorage.GetExpiredValues(context, long.MaxValue).Count()); } }, 0, interval: 333); Assert.Equal(0, leaderCount); var server2count = WaitForValue(() => { using (server2.ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context)) using (context.OpenReadTransaction()) { return(CompareExchangeExpirationStorage.GetExpiredValues(context, long.MaxValue).Count()); } }, 0, interval: 333); Assert.Equal(0, server2count); } }
public async Task CanSnapshotManyCompareExchangeWithExpiration() { DebuggerAttachedTimeout.DisableLongTimespan = true; var count = 1024; using var leader = GetNewServer(); using var follower = GetNewServer(); using (var store = GetDocumentStore(new Options { Server = leader })) { var expiry = DateTime.Now.AddMinutes(2); var compareExchanges = new Dictionary <string, User>(); await AddCompareExchangesWithExpire(count, compareExchanges, store, expiry); await AssertCompareExchanges(compareExchanges, store, expiry); using (var requestExecutor = ClusterRequestExecutor.CreateForSingleNode(leader.WebUrl, null)) using (requestExecutor.ContextPool.AllocateOperationContext(out var ctx)) { await requestExecutor.ExecuteAsync(new AddClusterNodeCommand(follower.WebUrl, watcher : true), ctx); var cmd = new AddDatabaseNodeOperation(store.Database).GetCommand(store.Conventions, ctx); await requestExecutor.ExecuteAsync(cmd, ctx); await follower.ServerStore.Cluster.WaitForIndexNotification(cmd.Result.RaftCommandIndex); } using (var fStore = GetDocumentStore(new Options { Server = follower, CreateDatabase = false, ModifyDatabaseName = _ => store.Database, ModifyDocumentStore = s => s.Conventions = new DocumentConventions { DisableTopologyUpdates = true } })) { await AssertCompareExchanges(compareExchanges, store, expiry); leader.ServerStore.Observer.Time.UtcDateTime = () => DateTime.UtcNow.AddMinutes(3); var val = await WaitForValueAsync(async() => { var stats = await store.Maintenance.SendAsync(new GetDetailedStatisticsOperation()); return(stats.CountOfCompareExchange); }, 0); Assert.Equal(0, val); val = await WaitForValueAsync(async() => { var stats = await fStore.Maintenance.SendAsync(new GetDetailedStatisticsOperation()); return(stats.CountOfCompareExchange); }, 0); Assert.Equal(0, val); } } }