コード例 #1
0
ファイル: DataSubscriptions.cs プロジェクト: stevehansen/docs
        public async Task Worker(IDocumentStore store, CancellationToken cancellationToken)
        {
            string subscriptionName = await store.Subscriptions.CreateAsync <Order>(x => x.Company == "companies/11");

            SubscriptionWorker <Order> subscription = store.Subscriptions.GetSubscriptionWorker <Order>(subscriptionName);
            Task subscriptionTask = subscription.Run(x =>
                                                     x.Items.ForEach(item =>
                                                                     Console.WriteLine($"Order #{item.Result.Id} will be shipped via: {item.Result.ShipVia}")),
                                                     cancellationToken);

            await subscriptionTask;
        }
コード例 #2
0
 public Worker(ILogger <Worker> logger,
               IHostApplicationLifetime appLifetime,
               IOptions <WorkerParams> options,
               SubscriptionWorker subscriptionWorker,
               AzureAdWorker azureAdWorker)
 {
     _logger             = logger;
     _appLifetime        = appLifetime;
     _subscriptionWorker = subscriptionWorker;
     _azureAdWorker      = azureAdWorker;
     _parms = options.Value;
 }
コード例 #3
0
        public static void PreWarm(this IApplicationBuilder applicationBuilder)
        {
            Startup.LoadTypes();

            //SubscriptionWorker worker = new SubscriptionWorker()
            var internalSubscriptionService = Boolean.Parse(ConfigurationReader.GetValue("InternalSubscriptionService"));

            if (internalSubscriptionService)
            {
                String eventStoreConnectionString             = ConfigurationReader.GetValue("EventStoreSettings", "ConnectionString");
                Int32  inflightMessages                       = Int32.Parse(ConfigurationReader.GetValue("AppSettings", "InflightMessages"));
                Int32  persistentSubscriptionPollingInSeconds = Int32.Parse(ConfigurationReader.GetValue("AppSettings", "PersistentSubscriptionPollingInSeconds"));
                String filter        = ConfigurationReader.GetValue("AppSettings", "InternalSubscriptionServiceFilter");
                String ignore        = ConfigurationReader.GetValue("AppSettings", "InternalSubscriptionServiceIgnore");
                String streamName    = ConfigurationReader.GetValue("AppSettings", "InternalSubscriptionFilterOnStreamName");
                Int32  cacheDuration = Int32.Parse(ConfigurationReader.GetValue("AppSettings", "InternalSubscriptionServiceCacheDuration"));

                ISubscriptionRepository subscriptionRepository = SubscriptionRepository.Create(eventStoreConnectionString, cacheDuration);

                ((SubscriptionRepository)subscriptionRepository).Trace += (sender, s) => Extensions.log(TraceEventType.Information, "REPOSITORY", s);

                // init our SubscriptionRepository
                subscriptionRepository.PreWarm(CancellationToken.None).Wait();

                var eventHandlerResolver = Startup.ServiceProvider.GetService <IDomainEventHandlerResolver>();

                SubscriptionWorker concurrentSubscriptions = SubscriptionWorker.CreateConcurrentSubscriptionWorker(eventStoreConnectionString, eventHandlerResolver, subscriptionRepository, inflightMessages, persistentSubscriptionPollingInSeconds);

                concurrentSubscriptions.Trace   += (_, args) => concurrentLog(TraceEventType.Information, args.Message);
                concurrentSubscriptions.Warning += (_, args) => concurrentLog(TraceEventType.Warning, args.Message);
                concurrentSubscriptions.Error   += (_, args) => concurrentLog(TraceEventType.Error, args.Message);

                if (!String.IsNullOrEmpty(ignore))
                {
                    concurrentSubscriptions = concurrentSubscriptions.IgnoreSubscriptions(ignore);
                }

                if (!String.IsNullOrEmpty(filter))
                {
                    //NOTE: Not overly happy with this design, but
                    //the idea is if we supply a filter, this overrides ignore
                    concurrentSubscriptions = concurrentSubscriptions.FilterSubscriptions(filter)
                                              .IgnoreSubscriptions(null);
                }

                if (!String.IsNullOrEmpty(streamName))
                {
                    concurrentSubscriptions = concurrentSubscriptions.FilterByStreamName(streamName);
                }

                concurrentSubscriptions.StartAsync(CancellationToken.None).Wait();
            }
        }
コード例 #4
0
        public void SubscriptionWorker_DefaultValues_WorkerCreated()
        {
            Task <List <PersistentSubscriptionInfo> > getSubscriptions = new(TestData.GetPersistentSubscriptions_DemoEstate);
            String eventStoreConnectionString           = "esdb://*****:*****@192.168.1.133:2113?tls=false&tlsVerifyCert=false";
            ISubscriptionRepository subscriptionService = SubscriptionRepository.Create(getSubscriptions);

            SubscriptionWorker concurrentSubscriptions =
                SubscriptionWorker.CreateConcurrentSubscriptionWorker(eventStoreConnectionString, this.domainEventHandlerResolver.Object, subscriptionService);

            concurrentSubscriptions.FilterSubscriptions.ShouldBeNull();
            concurrentSubscriptions.IgnoreSubscriptions.ShouldBe("local-");
            concurrentSubscriptions.StreamNameFilter.ShouldBeNull();
            concurrentSubscriptions.InflightMessages.ShouldBe(200);
            concurrentSubscriptions.IsOrdered.ShouldBeFalse();
        }
コード例 #5
0
        static async Task SubscriptionsTest()
        {
            String eventStoreConnectionString             = "esdb://127.0.0.1:2113?tls=false";
            Int32  inflightMessages                       = 1;
            Int32  persistentSubscriptionPollingInSeconds = 10;
            String filter        = String.Empty;
            String ignore        = String.Empty;
            String streamName    = String.Empty;
            Int32  cacheDuration = 0;

            ISubscriptionRepository subscriptionRepository = SubscriptionRepository.Create(eventStoreConnectionString, cacheDuration);

            //((SubscriptionRepository)subscriptionRepository).Trace += (sender, s) => Extensions.log(TraceEventType.Information, "REPOSITORY", s);

            // init our SubscriptionRepository
            subscriptionRepository.PreWarm(CancellationToken.None).Wait();

            IDomainEventHandlerResolver eventHandlerResolver = new DomainEventHandlerResolver(new Dictionary <String, String[]>(),
                                                                                              null);

            SubscriptionWorker concurrentSubscriptions = SubscriptionWorker.CreateConcurrentSubscriptionWorker(Program.ConfigureEventStoreSettings(), eventHandlerResolver, subscriptionRepository, inflightMessages, persistentSubscriptionPollingInSeconds);

            //concurrentSubscriptions.Trace += (_, args) => Extensions.concurrentLog(TraceEventType.Information, args.Message);
            //concurrentSubscriptions.Warning += (_, args) => Extensions.concurrentLog(TraceEventType.Warning, args.Message);
            //concurrentSubscriptions.Error += (_, args) => Extensions.concurrentLog(TraceEventType.Error, args.Message);

            if (!String.IsNullOrEmpty(ignore))
            {
                concurrentSubscriptions = concurrentSubscriptions.IgnoreSubscriptions(ignore);
            }

            if (!String.IsNullOrEmpty(filter))
            {
                //NOTE: Not overly happy with this design, but
                //the idea is if we supply a filter, this overrides ignore
                concurrentSubscriptions = concurrentSubscriptions.FilterSubscriptions(filter)
                                          .IgnoreSubscriptions(null);
            }

            if (!String.IsNullOrEmpty(streamName))
            {
                concurrentSubscriptions = concurrentSubscriptions.FilterByStreamName(streamName);
            }

            concurrentSubscriptions.StartAsync(CancellationToken.None).Wait();
        }
コード例 #6
0
        private void InsertProductsToUsers(SubscriptionWorker <dynamic> subscription)
        {
            var rand = new Random();
            var ct   = new CancellationTokenSource();
            int min  = 0;

            subscription.Run(batch =>
            {
                foreach (var doc in batch.Items)
                {
                    if (doc.Id.StartsWith($"user2.{GenralGuid}") == false)
                    {
                        continue;
                    }
                    if (min >= doc.Result.Age)
                    {
                        continue;
                    }
                    min = doc.Result.Age;

                    var randNumber1 = rand.Next(1, 6);
                    for (var i = 0; i < randNumber1; i++)
                    {
                        var randNumber2 = rand.Next(0, 2);
                        var randNumber3 = rand.Next(0, 4);
                        Debug.Assert(randNumber2 * randNumber3 < ProductsCount);
                        if (doc.Result.Products == null)
                        {
                            doc.Result.Products = new LinkedList <string>();
                        }
                        doc.Result.Products.AddFirst($"products.{GenralGuid}/{_productsGuid[randNumber2 * randNumber3]}");
                    }
                    using (var session = DocumentStore.OpenSession())
                    {
                        session.Store(doc.Result);
                        session.SaveChanges();
                    }
                    if (doc.Result.Age == 5000)
                    {
                        ct.Cancel();
                    }
                }
            }, ct.Token);
        }
コード例 #7
0
        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            Console.Title = "Messaging Service";

            //At this stage, we only need our hosting file for ip and ports
            IConfigurationRoot config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
                                        .AddJsonFile("hosting.json", optional: true)
                                        .AddJsonFile("hosting.development.json", optional: true)
                                        .AddEnvironmentVariables().Build();

            IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args);

            hostBuilder.ConfigureLogging(logging =>
            {
                logging.AddConsole();
            }).ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup <Startup>();
                webBuilder.UseConfiguration(config);
                webBuilder.UseKestrel();
            })
            .ConfigureServices(services =>
            {
                RequestSentToEmailProviderEvent e = new RequestSentToEmailProviderEvent(Guid.Parse("2AA2D43B-5E24-4327-8029-1135B20F35CE"), "", new List <String>(),
                                                                                        "", "", true);

                RequestSentToSMSProviderEvent s = new RequestSentToSMSProviderEvent(Guid.NewGuid(), "", "", "");

                TypeProvider.LoadDomainEventsTypeDynamically();

                services.AddHostedService <SubscriptionWorker>(provider =>
                {
                    IDomainEventHandlerResolver r =
                        provider.GetRequiredService <IDomainEventHandlerResolver>();
                    EventStorePersistentSubscriptionsClient p = provider.GetRequiredService <EventStorePersistentSubscriptionsClient>();
                    HttpClient h = provider.GetRequiredService <HttpClient>();
                    SubscriptionWorker worker = new SubscriptionWorker(r, p, h);
                    worker.TraceGenerated    += Worker_TraceGenerated;
                    return(worker);
                });
            });
            return(hostBuilder);
        }
コード例 #8
0
        private void CreateOrderDoc(SubscriptionWorker <dynamic> subscription)
        {
            var rand = new Random();
            var ct   = new CancellationTokenSource(new TimeSpan(0, 60, 0));

            subscription.Run(batch =>
            {
                foreach (var doc in batch.Items)
                {
                    /*if (doc.Id.StartsWith($"user2.{GenralGuid}") == false)
                     * {
                     *  ReportInfo($"DocID: {doc.Id}");
                     *  continue;
                     * }*/

                    using (var session = DocumentStore.OpenSession())
                    {
                        var shipper = rand.Next(0, 10);
                        var list    = new LinkedList <string>();
                        var x       = (doc.Result.ProductsNames as JArray).GetEnumerator();

                        while (x.MoveNext())
                        {
                            list.AddFirst(x.Current.ToString());
                        }

                        var user = new Order
                        {
                            ShipVia       = $"shipper.{GenralGuid}-{_shipperGuid[shipper]}",
                            ShipTo        = doc.Id,
                            ProductsNames = list
                        };
                        session.Store(user, $"order.{GenralGuid}/");
                        _shipper[shipper] += 1;
                        session.SaveChanges();
                    }
                }
            }, ct.Token);
        }
コード例 #9
0
        public async Task SubscriptionWorker_CanBeStartedAndStopped()
        {
            CancellationToken  cancellationToken = CancellationToken.None;
            SubscriptionWorker sw = SubscriptionWorker.CreateConcurrentSubscriptionWorker(this.EventStoreConnectionString,
                                                                                          this.domainEventHandlerResolver.Object,
                                                                                          this.SubscriptionRepository).UseInMemory();

            await sw.StartAsync(cancellationToken);

            //Give our service time to run
            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);

            sw.IsRunning.ShouldBeTrue();

            await sw.StopAsync(cancellationToken);

            sw.IsRunning.ShouldBe(false);

            var stillConnected = sw.GetPersistentSubscription().Count;

            stillConnected.ShouldBe(0);
        }
コード例 #10
0
        public async Task SubscriptionWorker_CanBeCreatedAndReceiveEvents()
        {
            CancellationToken      cancellationToken = CancellationToken.None;
            TestDomainEventHandler eventHandler1     = new();
            Int32 inflight         = 200;
            Int32 pollingInSeconds = 60;

            this.domainEventHandlerResolver.Setup(d => d.GetDomainEventHandlers(It.IsAny <IDomainEvent>())).Returns(new List <IDomainEventHandler>()
            {
                eventHandler1
            });

            SubscriptionWorker sw = SubscriptionWorker.CreateConcurrentSubscriptionWorker(this.EventStoreConnectionString,
                                                                                          this.domainEventHandlerResolver.Object,
                                                                                          this.SubscriptionRepository,
                                                                                          inflight,
                                                                                          pollingInSeconds).UseInMemory();

            await sw.StartAsync(cancellationToken);

            //Give our service time to run
            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);

            sw.IsRunning.ShouldBeTrue();

            PersistentSubscription ps = sw.GetPersistentSubscription()[0];

            String @event = "{\r\n  \"estateId\": \"4fc2692f-067a-443e-8006-335bf2732248\",\r\n  \"estateName\": \"Demo Estate\"\r\n}\t";

            ps.Connected.ShouldBeTrue();
            ps.PersistentSubscriptionDetails.InflightMessages.ShouldBe(inflight);

            //Manually add events.
            ((InMemoryPersistentSubscriptionsClient)ps.PersistentSubscriptionsClient).WriteEvent(@event, "EstateCreatedEvent", cancellationToken);

            eventHandler1.DomainEvents.Count.ShouldBe(1);
        }
コード例 #11
0
        public void Subscribe()
        {
            const string subName = "NewOrders";
            var          subscriptionCreationOptions = new SubscriptionCreationOptions
            {
                Name = subName,
            };

            try
            {
                InternetShopStore.Store.Subscriptions.GetSubscriptionState(subName, InternetShopStore.DatabaseName);
            }
            catch (SubscriptionDoesNotExistException)
            {
                InternetShopStore.Store.Subscriptions.Create <Order>(options: subscriptionCreationOptions, database: InternetShopStore.DatabaseName);
            }
            _subscription = InternetShopStore.Store.Subscriptions.GetSubscriptionWorker <Order>(subName);
            _subscription.Run(x =>
                              x.Items.ForEach(async item =>
            {
                await _hubContext.Clients.All.SendAsync("OrderAdded", $"{item.Result.Product.Name}");
            }),
                              CancellationToken.None);
        }
コード例 #12
0
        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),
                    ShipTo       = x.ShipTo,
                    EmployeeName = RavenQuery.Load <Employee>(x.Employee).FirstName + " " +
                                   RavenQuery.Load <Employee>(x.Employee).LastName
                }
            });

            #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){
                                var employee = LoadDocument(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
        }
コード例 #13
0
        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)");
            }
        }
コード例 #14
0
        public void AllClientsWith_WaitForFree_StrategyShouldGetAccessToSubscription()
        {
            using (var store = GetDocumentStore())
            {
                var id = store.Subscriptions.Create <User>();

                const int numberOfClients = 4;

                var subscriptions = new SubscriptionWorker <User> [numberOfClients];
                var processed     = new ManualResetEvent[numberOfClients];
                var done          = new bool[numberOfClients];
                for (int i = 0; i < numberOfClients; i++)
                {
                    processed[i] = new ManualResetEvent(false);
                }
                var userShouldnotexist = "user/shouldNotExist";
                using (var session = store.OpenSession())
                {
                    session.Store(new User(), userShouldnotexist);
                    session.SaveChanges();
                    //session.Delete(userShouldnotexist);
                }

                for (int i = 0; i < numberOfClients; i++)
                {
                    var clientNumber = i;

                    subscriptions[clientNumber] = store.Subscriptions.GetSubscriptionWorker <User>(new SubscriptionWorkerOptions(id)
                    {
                        Strategy = SubscriptionOpeningStrategy.WaitForFree
                    });

                    subscriptions[clientNumber].AfterAcknowledgment += x =>
                    {
                        processed[clientNumber].Set();
                        return(Task.CompletedTask);
                    };

                    subscriptions[clientNumber].Run(x =>
                    {
                    });

                    Thread.Sleep(200);
                }

                for (int i = 0; i < numberOfClients; i++)
                {
                    using (var s = store.OpenSession())
                    {
                        s.Store(new User());
                        s.SaveChanges();
                    }

                    var index = WaitHandle.WaitAny(processed, waitForDocTimeout);

                    Assert.NotEqual(WaitHandle.WaitTimeout, index);

                    subscriptions[index].Dispose();

                    done[index] = true;

                    processed[index].Reset();
                }

                for (int i = 0; i < numberOfClients; i++)
                {
                    Assert.True(done[i]);
                }
            }
        }
コード例 #15
0
ファイル: SubscriptionsBasic.cs プロジェクト: radtek/ravendb
        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,
                    TimeToWaitBeforeConnectionRetry = TimeSpan.FromSeconds(5)
                });
                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,
                    TimeToWaitBeforeConnectionRetry = TimeSpan.FromSeconds(5)
                });
                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)
                {
                    TimeToWaitBeforeConnectionRetry = TimeSpan.FromSeconds(5),
                    Strategy = SubscriptionOpeningStrategy.WaitForFree
                });

                t = notThrowingSubscriptionWorker.Run(x =>
                {
                    mre.Set();
                });

                PutUserDoc(store);

                Assert.True(await mre.WaitAsync(_reasonableWaitTime));
            }
            finally
            {
                subscriptionWorker?.Dispose();
                throwingSubscriptionWorker?.Dispose();
                notThrowingSubscriptionWorker?.Dispose();
                store.Dispose();
            }
        }
コード例 #16
0
ファイル: SubscriptionsBasic.cs プロジェクト: radtek/ravendb
        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();
            }
        }
コード例 #17
0
        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)");
            }
        }