Пример #1
0
        public async Task Subscribe_WillFindMessages(int numberOfJobs)
        {
            var exampleQueueId = QueueId.Parse("ExampleQueue");
            var cancel         = new CancellationTokenSource(TimeSpan.FromSeconds(5));
            var exampleOptions = new TakeNextSubscriptionOptions
            {
                Token           = cancel.Token,
                PollingInterval = TimeSpan.FromMilliseconds(1),
                TakeNextOptions = new TakeNextOptions()
            };
            var mockPeekNextService = new Mock <IJobTakeNextService>();
            var numberOfJobsTaken   = 0;

            mockPeekNextService.Setup(x => x.TakeFor(exampleOptions.TakeNextOptions)).Returns(() =>
            {
                numberOfJobsTaken += 1;
                return(numberOfJobsTaken <= numberOfJobs ? Task.FromResult(new Job()) : Task.FromResult(default(Job)));
            });

            var sut = new TaskBasedTakeNextSubscriber(mockPeekNextService.Object);

            var numberOfTimesOurDelegateIsInvoked = 0;
            await sut.Subscribe(job => Task.FromResult(numberOfTimesOurDelegateIsInvoked += 1), exampleOptions).ConfigureAwait(false);

            do
            {
                Thread.Sleep(10);
                // wait for us to have processed the jobs, or for the max time to be over.
            } while (numberOfTimesOurDelegateIsInvoked < numberOfJobs && !cancel.IsCancellationRequested);

            cancel.Cancel();

            Assert.That(numberOfTimesOurDelegateIsInvoked, Is.EqualTo(numberOfJobs));
            mockPeekNextService.Verify(x => x.TakeFor(exampleOptions.TakeNextOptions), Times.AtLeast(numberOfJobsTaken));
        }
Пример #2
0
        public async Task Subscribe_WillCheckMoreThanMoreThanOnce()
        {
            var exampleQueueId = QueueId.Parse("ExampleQueue");
            var cancel         = new CancellationTokenSource(TimeSpan.FromSeconds(5));
            var exampleOptions = new TakeNextSubscriptionOptions
            {
                Token           = cancel.Token,
                PollingInterval = TimeSpan.FromMilliseconds(1),
                TakeNextOptions = new TakeNextOptions()
            };
            var mockPeekNextService = new Mock <IJobTakeNextService>();

            var sut = new TaskBasedTakeNextSubscriber(mockPeekNextService.Object);

            var hasBeenCalled = false;
            await sut.Subscribe(job => Task.FromResult(hasBeenCalled = true), exampleOptions).ConfigureAwait(false);

            Thread.Sleep(10);

            cancel.Cancel();

            Assert.That(hasBeenCalled, Is.False);
            mockPeekNextService.Verify(x => x.TakeFor(exampleOptions.TakeNextOptions), Times.AtLeast(2));
        }
        private static Task SetupTakeNextWorkerWithSubscription(IMongoDatabase database, QueueId queueName, ConcurrentBag <Job> finishedJobs, JobAttributes attributesThatShouldWork, CancellationToken cancellationToken)
        {
            var standardAck = new JobAcknowledgment
            {
                { "RunnerId", Guid.NewGuid().ToString("N") }
            };

            var options = new TakeNextSubscriptionOptions
            {
                Token           = cancellationToken,
                TakeNextOptions = new TakeNextOptions
                {
                    QueueId        = queueName,
                    Acknowledgment = standardAck,
                    HasAttributes  = attributesThatShouldWork
                }
            };

            var subscriber = new TaskBasedTakeNextSubscriber(new MongoJobTakeNextService(database));

            return(subscriber.Subscribe(async nextJob =>
            {
                var exampleReportMessage1 = "FooBar";
                var exampleReportMessage2 = "WizBang";
                var exampleReportMessage3 = "PowPop";

                // Send Reports
                var reportService = new MongoJobReportService(database);
                await
                reportService.AddReport(queueName, nextJob.Id,
                                        new JobReport {
                    { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", exampleReportMessage1 }
                }).ConfigureAwait(false);
                await
                reportService.AddReport(queueName, nextJob.Id,
                                        new JobReport {
                    { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", exampleReportMessage2 }
                }).ConfigureAwait(false);
                await
                reportService.AddReport(queueName, nextJob.Id,
                                        new JobReport {
                    { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", exampleReportMessage3 }
                }).ConfigureAwait(false);

                // Send Result
                var completionService = new MongoJobCompletionService(database);
                await completionService.Complete(queueName, nextJob.Id, new JobResult {
                    { "Result", "Success" }
                }).ConfigureAwait(false);

                // Finish Job
                var finishedJobFromDb =
                    await database.GetJobCollection()
                    .Find(Builders <Job> .Filter.Eq(x => x.Id, nextJob.Id))
                    .FirstAsync(cancellationToken)
                    .ConfigureAwait(false);

                Assert.That(finishedJobFromDb, Is.Not.Null);
                Assert.That(finishedJobFromDb.Acknowledgment, Is.Not.Null);

                Assert.That(finishedJobFromDb.Reports, Has.Length.EqualTo(3));
                var valuesOfReports = finishedJobFromDb.Reports.SelectMany(x => x.Values).ToList();
                Assert.That(valuesOfReports, Contains.Item(exampleReportMessage1));
                Assert.That(valuesOfReports, Contains.Item(exampleReportMessage2));
                Assert.That(valuesOfReports, Contains.Item(exampleReportMessage3));

                Assert.That(finishedJobFromDb.Result, Is.Not.Null);
                finishedJobs.Add(finishedJobFromDb);
            }, options));
        }
        public async Task RollingDeploy_ModelSubJobsOrchestratedByParent()
        {
            var exampleQueueName = QueueId.Parse("Wind");

            await RunInMongoLand(async database =>
            {
                var cancellationSource = new CancellationTokenSource();
                cancellationSource.CancelAfter(MaxTestTime);
                var cancellationToken = cancellationSource.Token;

                var finishedJobs = new ConcurrentBag <Job>();

                await SetupTakeNextWorkerWithSubscription(database, exampleQueueName, finishedJobs, new JobAttributes {
                    { "Name", "DeployServer" },
                }, cancellationToken).ConfigureAwait(false);

                // Create a rolling deploy relevant for my datacenter
                var creationService = new MongoJobCreationService(database);
                await creationService.Create(exampleQueueName, new JobAttributes
                {
                    { "Name", "RollingDeploy" },
                    { "Environment", "Prod" }
                }).ConfigureAwait(false);

                // Take Next available job
                var takeNextSubscriber = new TaskBasedTakeNextSubscriber(new MongoJobTakeNextService(database));
                var standardAck        = new JobAcknowledgment
                {
                    { "RunnerId", Guid.NewGuid().ToString("N") }
                };
                var peekQuery = new TakeNextOptions
                {
                    QueueId       = exampleQueueName,
                    HasAttributes = new JobAttributes {
                        { "Environment", "Prod" }
                    },
                    Acknowledgment = standardAck
                };
                await takeNextSubscriber.Subscribe(async rollingDeployJob =>
                {
                    // Send Reports
                    var reportService = new MongoJobReportService(database);
                    await
                    reportService.AddReport(exampleQueueName, rollingDeployJob.Id,
                                            new JobReport {
                        { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", "Starting Rolling Deploy" }
                    }).ConfigureAwait(false);

                    var queryService = new MongoJobQueryService(database);

                    IEnumerable servers = new[] { "PROD2", "PROD1" };
                    foreach (var server in servers)
                    {
                        var deployServer = new JobAttributes
                        {
                            { "Name", "DeployServer" },
                            { "Server", server }
                        };

                        await reportService.AddReport(exampleQueueName, rollingDeployJob.Id,
                                                      new JobReport {
                            { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", $"Requesting Deploy on server {server}" }
                        }).ConfigureAwait(false);
                        var deployServerJobId = await creationService.Create(exampleQueueName, deployServer).ConfigureAwait(false);

                        Job hasResult;
                        do
                        {
                            // replace with detail service
                            hasResult = (await queryService.QueryFor(new JobQuery {
                                QueueId = exampleQueueName, JobIds = new[] { deployServerJobId }, HasResult = true
                            }).ConfigureAwait(false)).FirstOrDefault();
                            Thread.Sleep(500);
                        } while (hasResult == null);

                        await reportService.AddReport(exampleQueueName, rollingDeployJob.Id,
                                                      new JobReport {
                            { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", $"Deploy on server {server} Completed, {JsonConvert.SerializeObject(hasResult.Result)}" }
                        }).ConfigureAwait(false);
                        // inspect result
                    }

                    // Send Result
                    var completionService = new MongoJobCompletionService(database);
                    await completionService.Complete(exampleQueueName, rollingDeployJob.Id, new JobResult {
                        { "Result", "Success" }
                    }).ConfigureAwait(false);

                    var finalizedRollingDeployJob = await queryService.QueryFor(new JobQuery {
                        QueueId = exampleQueueName, JobIds = new[] { rollingDeployJob.Id }
                    }).ConfigureAwait(false);

                    cancellationSource.Cancel();

                    Console.WriteLine($"Finalized Rolling Deploy Job: {JsonConvert.SerializeObject(finalizedRollingDeployJob)}");

                    Assert.That(finalizedRollingDeployJob.First().Result["Result"], Is.EqualTo("Success"));
                }, new TakeNextSubscriptionOptions
                {
                    TakeNextOptions = peekQuery,
                    Token           = cancellationToken,
                }).ConfigureAwait(false);
            }).ConfigureAwait(false);
        }