public void DisposingOneSubscriptionShouldNotAffectOnNotificationsOfOthers() { SubscriptionWorker <User> subscription1 = null; SubscriptionWorker <User> subscription2 = null; var store = GetDocumentStore(); try { var id1 = store.Subscriptions.Create(new SubscriptionCreationOptions <User>()); var id2 = store.Subscriptions.Create(new SubscriptionCreationOptions <User>()); using (var s = store.OpenSession()) { s.Store(new User(), "users/1"); s.Store(new User(), "users/2"); s.SaveChanges(); } subscription1 = store.Subscriptions.GetSubscriptionWorker <User>(id1); var items1 = new BlockingCollection <User>(); subscription1.Run(x => x.Items.ForEach(i => items1.Add(i.Result))); subscription2 = store.Subscriptions.GetSubscriptionWorker <User>(id2); var items2 = new BlockingCollection <User>(); subscription2.Run(x => x.Items.ForEach(i => items2.Add(i.Result))); Assert.True(items1.TryTake(out var user, _reasonableWaitTime)); Assert.Equal("users/1", user.Id); Assert.True(items1.TryTake(out user, _reasonableWaitTime)); Assert.Equal("users/2", user.Id); Assert.True(items2.TryTake(out user, _reasonableWaitTime)); Assert.Equal("users/1", user.Id); Assert.True(items2.TryTake(out user, _reasonableWaitTime)); Assert.Equal("users/2", user.Id); subscription1.Dispose(); using (var s = store.OpenSession()) { s.Store(new User(), "users/3"); s.Store(new User(), "users/4"); s.SaveChanges(); } Assert.True(items2.TryTake(out user, _reasonableWaitTime)); Assert.Equal("users/3", user.Id); Assert.True(items2.TryTake(out user, _reasonableWaitTime)); Assert.Equal("users/4", user.Id); } finally { subscription1.Dispose(); subscription2.Dispose(); store.Dispose(); } }
public async Task CanReleaseSubscription() { SubscriptionWorker <dynamic> subscriptionWorker = null; SubscriptionWorker <dynamic> throwingSubscriptionWorker = null; SubscriptionWorker <dynamic> notThrowingSubscriptionWorker = null; var store = GetDocumentStore(); try { Server.ServerStore.Observer.Suspended = true; var id = store.Subscriptions.Create(new SubscriptionCreationOptions <User>()); subscriptionWorker = store.Subscriptions.GetSubscriptionWorker(new SubscriptionWorkerOptions(id) { Strategy = SubscriptionOpeningStrategy.OpenIfFree }); var mre = new AsyncManualResetEvent(); PutUserDoc(store); var t = subscriptionWorker.Run(x => { mre.Set(); }); Assert.True(await mre.WaitAsync(_reasonableWaitTime)); mre.Reset(); throwingSubscriptionWorker = store.Subscriptions.GetSubscriptionWorker(new SubscriptionWorkerOptions(id) { Strategy = SubscriptionOpeningStrategy.OpenIfFree }); var subscriptionTask = throwingSubscriptionWorker.Run(x => { }); Assert.True(await Assert.ThrowsAsync <SubscriptionInUseException>(() => { return(subscriptionTask); }).WaitAsync(_reasonableWaitTime)); store.Subscriptions.DropConnection(id); notThrowingSubscriptionWorker = store.Subscriptions.GetSubscriptionWorker(new SubscriptionWorkerOptions(id)); t = notThrowingSubscriptionWorker.Run(x => { mre.Set(); }); PutUserDoc(store); Assert.True(await mre.WaitAsync(_reasonableWaitTime)); } finally { subscriptionWorker?.Dispose(); throwingSubscriptionWorker?.Dispose(); notThrowingSubscriptionWorker?.Dispose(); store.Dispose(); } }
public async Task DistributedRevisionsSubscription(int nodesAmount) { var uniqueRevisions = new HashSet <string>(); var uniqueDocs = new HashSet <string>(); var(_, leader) = await CreateRaftCluster(nodesAmount).ConfigureAwait(false); var defaultDatabase = GetDatabaseName(); await CreateDatabaseInCluster(defaultDatabase, nodesAmount, leader.WebUrl).ConfigureAwait(false); using (var store = new DocumentStore { Urls = new[] { leader.WebUrl }, Database = defaultDatabase }.Initialize()) { await SetupRevisions(leader, defaultDatabase).ConfigureAwait(false); var reachedMaxDocCountMre = new AsyncManualResetEvent(); var ackSent = new AsyncManualResetEvent(); var continueMre = new AsyncManualResetEvent(); await GenerateDistributedRevisionsDataAsync(defaultDatabase); var subscriptionId = await store.Subscriptions.CreateAsync <Revision <User> >().ConfigureAwait(false); var docsCount = 0; var revisionsCount = 0; var expectedRevisionsCount = 0; SubscriptionWorker <Revision <User> > subscription = null; int i; for (i = 0; i < 10; i++) { subscription = store.Subscriptions.GetSubscriptionWorker <Revision <User> >(new SubscriptionWorkerOptions(subscriptionId) { MaxErroneousPeriod = nodesAmount == 5 ? TimeSpan.FromSeconds(15) : TimeSpan.FromSeconds(5), MaxDocsPerBatch = 1, TimeToWaitBeforeConnectionRetry = TimeSpan.FromMilliseconds(100) }); subscription.AfterAcknowledgment += async b => { Assert.True(await continueMre.WaitAsync(TimeSpan.FromSeconds(60))); try { if (revisionsCount == expectedRevisionsCount) { continueMre.Reset(); ackSent.Set(); } Assert.True(await continueMre.WaitAsync(TimeSpan.FromSeconds(60))); } catch (Exception) { } }; var started = new AsyncManualResetEvent(); var task = subscription.Run(b => { started.Set(); HandleSubscriptionBatch(nodesAmount, b, uniqueDocs, ref docsCount, uniqueRevisions, reachedMaxDocCountMre, ref revisionsCount); }); var cont = task.ContinueWith(t => { reachedMaxDocCountMre.SetException(t.Exception); ackSent.SetException(t.Exception); }, TaskContinuationOptions.OnlyOnFaulted); await Task.WhenAny(task, started.WaitAsync(TimeSpan.FromSeconds(60))); if (started.IsSet) { break; } Assert.IsType <SubscriptionDoesNotExistException>(task.Exception.InnerException); subscription.Dispose(); } Assert.NotEqual(i, 10); expectedRevisionsCount = nodesAmount + 2; continueMre.Set(); Assert.True(await ackSent.WaitAsync(_reasonableWaitTime).ConfigureAwait(false), $"Doc count is {docsCount} with revisions {revisionsCount}/{expectedRevisionsCount} (1st assert)"); ackSent.Reset(true); var disposedTag = await KillServerWhereSubscriptionWorks(defaultDatabase, subscription.SubscriptionName).ConfigureAwait(false); await WaitForResponsibleNodeToChange(defaultDatabase, subscription.SubscriptionName, disposedTag); continueMre.Set(); expectedRevisionsCount += 2; Assert.True(await ackSent.WaitAsync(_reasonableWaitTime).ConfigureAwait(false), $"Doc count is {docsCount} with revisions {revisionsCount}/{expectedRevisionsCount} (2nd assert)"); ackSent.Reset(true); continueMre.Set(); expectedRevisionsCount = (int)Math.Pow(nodesAmount, 2); if (nodesAmount == 5) { var secondDisposedTag = await KillServerWhereSubscriptionWorks(defaultDatabase, subscription.SubscriptionName).ConfigureAwait(false); await WaitForResponsibleNodeToChange(defaultDatabase, subscription.SubscriptionName, secondDisposedTag); } Assert.True(await reachedMaxDocCountMre.WaitAsync(_reasonableWaitTime).ConfigureAwait(false), $"Doc count is {docsCount} with revisions {revisionsCount}/{expectedRevisionsCount} (3rd assert)"); } }
public async Task ShouldKeepPullingDocsAfterServerRestart() { var dataPath = NewDataPath(); IDocumentStore store = null; RavenServer server = null; SubscriptionWorker <dynamic> subscriptionWorker = null; try { var co = new ServerCreationOptions { RunInMemory = false, CustomSettings = new Dictionary <string, string>() { [RavenConfiguration.GetKey(x => x.Core.DataDirectory)] = dataPath }, RegisterForDisposal = false }; server = GetNewServer(co); store = new DocumentStore() { Urls = new[] { server.ServerStore.GetNodeHttpServerUrl() }, Database = "RavenDB_2627", }.Initialize(); var doc = new DatabaseRecord(store.Database); var result = store.Maintenance.Server.Send(new CreateDatabaseOperationWithoutNameValidation(doc)); await WaitForRaftIndexToBeAppliedInCluster(result.RaftCommandIndex, _reasonableWaitTime); using (var session = store.OpenSession()) { session.Store(new User()); session.Store(new User()); session.Store(new User()); session.Store(new User()); session.SaveChanges(); } var id = store.Subscriptions.Create(new SubscriptionCreationOptions <User>()); subscriptionWorker = store.Subscriptions.GetSubscriptionWorker(new SubscriptionWorkerOptions(id) { TimeToWaitBeforeConnectionRetry = TimeSpan.FromSeconds(1), MaxDocsPerBatch = 1 }); var gotBatch = new ManualResetEventSlim(); var gotArek = new ManualResetEventSlim(); var t = subscriptionWorker.Run(x => { gotBatch.Set(); foreach (var item in x.Items) { if (item.Id == "users/arek") { gotArek.Set(); } } }); Assert.True(gotBatch.Wait(_reasonableWaitTime)); Server.ServerStore.DatabasesLandlord.UnloadDirectly(store.Database); for (int i = 0; i < 150; i++) { try { using (var session = store.OpenSession()) { session.Store(new User(), "users/arek"); session.SaveChanges(); } break; } catch { Thread.Sleep(25); if (i > 100) { throw; } } } Assert.True(gotArek.Wait(_reasonableWaitTime)); } finally { subscriptionWorker?.Dispose(); store?.Dispose(); server.Dispose(); } }
public async Task MixedCluster_DistributedRevisionsSubscription() { var uniqueRevisions = new HashSet <string>(); var uniqueDocs = new HashSet <string>(); var nodesAmount = 5; var(leader, peers, local) = await CreateMixedCluster(new[] { "4.0.7-nightly-20180820-0400", "4.0.7-nightly-20180820-0400" }, 2, new Dictionary <string, string> { [RavenConfiguration.GetKey(x => x.Cluster.MoveToRehabGraceTime)] = "1" }); var stores = await GetStores(leader, peers, local, modifyDocumentStore : s => s.Conventions.DisableTopologyUpdates = false); using (stores.Disposable) { var storeA = stores.Stores[0]; var dbName = await CreateDatabase(storeA, nodesAmount); await Task.Delay(500); await RevisionsHelper.SetupRevisions(leader.ServerStore, dbName).ConfigureAwait(false); var reachedMaxDocCountMre = new AsyncManualResetEvent(); var ackSent = new AsyncManualResetEvent(); var continueMre = new AsyncManualResetEvent(); GenerateDistributedRevisionsData(dbName, stores.Stores); var subscriptionId = await storeA.Subscriptions.CreateAsync <Revision <User> >(database : dbName).ConfigureAwait(false); var docsCount = 0; var revisionsCount = 0; var expectedRevisionsCount = 0; SubscriptionWorker <Revision <User> > subscription = null; int i; for (i = 0; i < 10; i++) { subscription = storeA.Subscriptions.GetSubscriptionWorker <Revision <User> >(new SubscriptionWorkerOptions(subscriptionId) { MaxDocsPerBatch = 1, TimeToWaitBeforeConnectionRetry = TimeSpan.FromMilliseconds(100) }, dbName); subscription.AfterAcknowledgment += async b => { await continueMre.WaitAsync(); try { if (revisionsCount == expectedRevisionsCount) { continueMre.Reset(); ackSent.Set(); } await continueMre.WaitAsync(); } catch (Exception) { } }; var started = new AsyncManualResetEvent(); var task = subscription.Run(b => { started.Set(); HandleSubscriptionBatch(nodesAmount, b, uniqueDocs, ref docsCount, uniqueRevisions, reachedMaxDocCountMre, ref revisionsCount); }); await Task.WhenAny(task, started.WaitAsync()); if (started.IsSet) { break; } Assert.IsType <SubscriptionDoesNotExistException>(task.Exception.InnerException); subscription.Dispose(); } Assert.NotEqual(i, 10); expectedRevisionsCount = nodesAmount + 2; continueMre.Set(); Assert.True(await ackSent.WaitAsync(_reasonableWaitTime).ConfigureAwait(false), $"Doc count is {docsCount} with revisions {revisionsCount}/{expectedRevisionsCount} (1st assert)"); ackSent.Reset(true); await KillServerWhereSubscriptionWorks(storeA, dbName, subscription.SubscriptionName, (leader, peers, local)).ConfigureAwait(false); continueMre.Set(); expectedRevisionsCount += 2; Assert.True(await ackSent.WaitAsync(_reasonableWaitTime).ConfigureAwait(false), $"Doc count is {docsCount} with revisions {revisionsCount}/{expectedRevisionsCount} (2nd assert)"); ackSent.Reset(true); continueMre.Set(); expectedRevisionsCount = (int)Math.Pow(nodesAmount, 2); await KillServerWhereSubscriptionWorks(storeA, dbName, subscription.SubscriptionName, (leader, peers, local)).ConfigureAwait(false); Assert.True(await reachedMaxDocCountMre.WaitAsync(_reasonableWaitTime).ConfigureAwait(false), $"Doc count is {docsCount} with revisions {revisionsCount}/{expectedRevisionsCount} (3rd assert)"); } }
public void Dispose() { _subscription?.Dispose(); }