Exemple #1
0
        public async Task Complete_ValidResult_Persists()
        {
            var exampleQueueId = QueueId.Parse(Guid.NewGuid().ToString("N"));
            var exampleJobId   = JobId.Generate();
            var exampleResult  = new JobResult {
                { "Datacenter", "PEN" }
            };

            Assert.That(exampleResult, Is.Not.Null);

            await RunInMongoLand(async database =>
            {
                var collection = database.GetJobCollection();
                collection.InsertOne(new Job {
                    QueueId = exampleQueueId, Id = exampleJobId
                });
                var sut = new MongoJobCompletionService(database);
                await sut.Complete(exampleQueueId, exampleJobId, exampleResult).ConfigureAwait(false);

                var result = await collection.Find(Builders <Job> .Filter.Empty).SingleAsync().ConfigureAwait(false);

                Assert.That(result.Result, Is.Not.Null);
                Assert.That(result.Result["Datacenter"], Is.EqualTo("PEN"));
            }).ConfigureAwait(false);
        }
Exemple #2
0
        protected static async Task <Job> TryProcessOneJobUsingTakeNext(IMongoDatabase database, QueueId exampleQueueName, JobAttributes attributesThatShouldWork)
        {
            // Take Next available job
            var takeNextService = new MongoJobTakeNextService(database);
            var standardAck     = new JobAcknowledgment
            {
                { "RunnerId", Guid.NewGuid().ToString("N") }
            };
            var peekQuery = new TakeNextOptions
            {
                QueueId        = exampleQueueName,
                HasAttributes  = attributesThatShouldWork,
                Acknowledgment = standardAck
            };
            var nextJob = await takeNextService.TakeFor(peekQuery).ConfigureAwait(false);

            if (nextJob == null)
            {
                return(null);
            }

            var exampleReportMessage1 = "FooBar";
            var exampleReportMessage2 = "WizBang";
            var exampleReportMessage3 = "PowPop";

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

            await
            reportService.AddReport(exampleQueueName, nextJob.Id,
                                    new JobReport { { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", exampleReportMessage2 } }).ConfigureAwait(false);

            await
            reportService.AddReport(exampleQueueName, nextJob.Id,
                                    new JobReport { { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", exampleReportMessage3 } }).ConfigureAwait(false);

            // Send Result
            var completionService = new MongoJobCompletionService(database);
            await completionService.Complete(exampleQueueName, 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().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);

            return(finishedJobFromDb);
        }
        private static Task SetupPeekThenAckWorkerWithSubscription(IMongoDatabase database, QueueId queueName, ConcurrentBag <Job> finishedJobs, JobAttributes attributesThatShouldWork, CancellationToken cancellationToken)
        {
            var standardAck = new JobAcknowledgment
            {
                { "RunnerId", Guid.NewGuid().ToString("N") }
            };

            var options = new PeekNextSubscriptionOptions()
            {
                Token           = cancellationToken,
                PeekNextOptions = new PeekNextOptions
                {
                    QueueId       = queueName,
                    HasAttributes = attributesThatShouldWork
                }
            };

            var subscriber = new TaskBasedPeekNextSubscriber(new MongoJobPeekNextService(new MongoJobQueryService(database)));

            return(subscriber.Subscribe(async nextJobs =>
            {
                var nextJob = nextJobs.First();
                // Acknowledge the job
                var acknowledgmentService = new MongoJobAcknowledgmentService(database);

                var ackResult = await acknowledgmentService.Ack(queueName, nextJob.Id, standardAck).ConfigureAwait(false);
                if (!ackResult.Success)
                {
                    return;
                }

                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));
        }
Exemple #4
0
        protected static async Task <Job> TryProcessOneJobUsingPeekThanAck(IMongoDatabase database, QueueId exampleQueueName, JobAttributes attributesThatShouldWork)
        {
            // Query for next available a job for my datacenter
            var peekNextService = new MongoJobPeekNextService(new MongoJobQueryService(database));
            var peekQuery       = new PeekNextOptions
            {
                QueueId       = exampleQueueName,
                HasAttributes = attributesThatShouldWork,
                Limit         = 5
            };
            var jobs = (await peekNextService.PeekFor(peekQuery).ConfigureAwait(false)).ToList();

            if (!jobs.Any())
            {
                return(null);
            }

            foreach (var job in jobs)
            {
                // Acknowledge the job
                var acknowledgmentService = new MongoJobAcknowledgmentService(database);
                var standardAck           = new JobAcknowledgment
                {
                    { "RunnerId", Guid.NewGuid().ToString("N") }
                };
                var ackResult = await acknowledgmentService.Ack(exampleQueueName, job.Id, standardAck).ConfigureAwait(false);

                if (!ackResult.Success)
                {
                    continue;
                }

                var exampleReportMessage1 = "FooBar";
                var exampleReportMessage2 = "WizBang";
                var exampleReportMessage3 = "PowPop";

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

                await
                reportService.AddReport(exampleQueueName, job.Id,
                                        new JobReport { { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", exampleReportMessage2 } }).ConfigureAwait(false);

                await
                reportService.AddReport(exampleQueueName, job.Id,
                                        new JobReport { { "Timestamp", DateTime.UtcNow.ToString("O") }, { "Message", exampleReportMessage3 } }).ConfigureAwait(false);

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

                // Finish Job
                var finishedJobFromDb =
                    await database.GetJobCollection().Find(Builders <Job> .Filter.Eq(x => x.Id, job.Id)).FirstAsync().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);

                return(finishedJobFromDb);
            }
            return(null);
        }
        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);
        }