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); }
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)); }
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); }