public async Task CreationExamples() { string name; IDocumentStore store = new DocumentStore(); #region create_whole_collection_generic_with_name name = await store.Subscriptions.CreateAsync(new SubscriptionCreationOptions <Order> { Name = "OrdersProcessingSumbscription" }); #endregion #region create_whole_collection_generic_with_mentor_node name = await store.Subscriptions.CreateAsync(new SubscriptionCreationOptions <Order> { MentorNode = "D" }); #endregion #region create_whole_collection_generic1 name = await store.Subscriptions.CreateAsync <Order>(); #endregion #region create_whole_collection_RQL name = await store.Subscriptions.CreateAsync(new SubscriptionCreationOptions() { Query = "From Orders" }); #endregion #region create_filter_only_generic name = await store.Subscriptions.CreateAsync <Order>(x => x.Lines.Sum(line => line.PricePerUnit *line.Quantity) > 100); #endregion #region create_filter_only_RQL name = await store.Subscriptions.CreateAsync(new SubscriptionCreationOptions() { Query = @" declare function getOrderLinesSum(doc){ var sum = 0; for (var i in doc.Lines) { sum += doc.Lines[i];} return sum; } From Orders as o Where getOrderLinesSum(o) > 100" }); #endregion #region create_filter_and_projection_generic name = store.Subscriptions.Create( new SubscriptionCreationOptions <Order>() { Filter = x => x.Lines.Sum(line => line.PricePerUnit * line.Quantity) > 100, Projection = x => new { Id = x.Id, Total = x.Lines.Sum(line => line.PricePerUnit * line.Quantity) } }); #endregion #region create_filter_and_projection_RQL name = await store.Subscriptions.CreateAsync(new SubscriptionCreationOptions() { Query = @"declare function getOrderLinesSum(doc){ var sum = 0; for (var i in doc.Lines) { sum += doc.Lines[i];} return sum; } declare function projectOrder(doc){ return { Id: order.Id, Total: getOrderLinesSum(order) }; } From Orders as o Where getOrderLinesSum(o) > 100 Select projectOrder(o)" }); #endregion #region create_filter_and_load_document_generic name = store.Subscriptions.Create( new SubscriptionCreationOptions <Order>() { Filter = x => x.Lines.Sum(line => line.PricePerUnit * line.Quantity) > 100, Projection = x => new { Id = x.Id, Total = x.Lines.Sum(line => line.PricePerUnit * line.Quantity), ShipTo = x.ShipTo, EmployeeName = RavenQuery.Load <Employee>(x.Employee).FirstName + " " + RavenQuery.Load <Employee>(x.Employee).LastName } }); #endregion #region create_filter_and_load_document_RQL name = await store.Subscriptions.CreateAsync(new SubscriptionCreationOptions() { Query = @"declare function getOrderLinesSum(doc){ var sum = 0; for (var i in doc.Lines) { sum += doc.Lines[i];} return sum; } declare function projectOrder(doc){ var employee = load(doc.Employee); return { Id: order.Id, Total: getOrderLinesSum(order), ShipTo: order.ShipTo, EmployeeName: employee.FirstName + ' ' + employee.LastName }; } From Orders as o Where getOrderLinesSum(o) > 100 Select projectOrder(o)" }); #endregion #region create_simple_revisions_subscription_generic name = store.Subscriptions.Create( new SubscriptionCreationOptions <Revision <Order> >()); #endregion #region create_simple_revisions_subscription_RQL name = await store.Subscriptions.CreateAsync(new SubscriptionCreationOptions() { Query = @"From Orders (Revisions = true)" }); #endregion #region use_simple_revision_subscription_generic SubscriptionWorker <Revision <Order> > revisionWorker = store.Subscriptions.GetSubscriptionWorker <Revision <Order> >(name); await revisionWorker.Run((SubscriptionBatch <Revision <Order> > x) => { foreach (var documentsPair in x.Items) { var prev = documentsPair.Result.Previous; var current = documentsPair.Result.Current; ProcessOrderChanges(prev, current); } } ); #endregion void ProcessOrderChanges(Order prev, Order cur) { } #region create_projected_revisions_subscription_generic name = store.Subscriptions.Create( new SubscriptionCreationOptions <Revision <Order> >() { Filter = tuple => tuple.Current.Lines.Count > tuple.Previous.Lines.Count, Projection = tuple => new { PreviousRevenue = tuple.Previous.Lines.Sum(x => x.PricePerUnit * x.Quantity), CurrentRevenue = tuple.Current.Lines.Sum(x => x.PricePerUnit * x.Quantity) } }); #endregion #region create_projected_revisions_subscription_RQL name = await store.Subscriptions.CreateAsync(new SubscriptionCreationOptions() { Query = @"declare function getOrderLinesSum(doc){ var sum = 0; for (var i in doc.Lines) { sum += doc.Lines[i];} return sum; } From Orders (Revisions = true) Where getOrderLinesSum(this.Current) > getOrderLinesSum(this.Previous) Select { PreviousRevenue: getOrderLinesSum(this.Previous), CurrentRevenue: getOrderLinesSum(this.Current) }" }); #endregion #region consume_revisions_subscription_generic SubscriptionWorker <OrderRevenues> revenuesComparisonWorker = store.Subscriptions.GetSubscriptionWorker <OrderRevenues>(name); await revenuesComparisonWorker.Run(x => { foreach (var item in x.Items) { Console.WriteLine($"Revenue for order with Id: {item.Id} grown from {item.Result.PreviousRevenue} to {item.Result.CurrentRevenue}"); } }); #endregion SubscriptionWorker <Order> subscription; var cancellationToken = new CancellationTokenSource().Token; #region consumption_0 var subscriptionName = await store.Subscriptions.CreateAsync <Order>(x => x.Company == "companies/11"); subscription = store.Subscriptions.GetSubscriptionWorker <Order>(subscriptionName); var subscriptionTask = subscription.Run(x => x.Items.ForEach(item => Console.WriteLine($"Order #{item.Result.Id} will be shipped via: {item.Result.ShipVia}")), cancellationToken); await subscriptionTask; #endregion #region open_1 subscription = store.Subscriptions.GetSubscriptionWorker <Order>(name); #endregion #region open_2 subscription = store.Subscriptions.GetSubscriptionWorker <Order>(new SubscriptionWorkerOptions(name) { Strategy = SubscriptionOpeningStrategy.WaitForFree }); #endregion #region open_3 subscription = store.Subscriptions.GetSubscriptionWorker <Order>(new SubscriptionWorkerOptions(name) { Strategy = SubscriptionOpeningStrategy.WaitForFree, MaxDocsPerBatch = 500, IgnoreSubscriberErrors = true }); #endregion #region create_subscription_with_includes_strongly_typed store.Subscriptions.Create(new SubscriptionCreationOptions <Order>() { Includes = builder => builder .IncludeDocuments(x => x.Lines.Select(y => y.Product)) }); #endregion #region create_subscription_with_includes_rql_path store.Subscriptions.Create(new SubscriptionCreationOptions() { Query = @"from Orders include Lines[].Product" }); #endregion #region create_subscription_with_includes_rql_javascript store.Subscriptions.Create(new SubscriptionCreationOptions() { Query = @" declare function includeProducts(doc) { doc.IncludedFields=0; doc.LinesCount = doc.Lines.length; for (let i=0; i< doc.Lines.length; i++) { doc.IncludedFields++; include(doc.Lines[i].Product); } return doc; } from Orders as o select includeProducts(o)" }); #endregion }
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)"); } }