private void AndTheMapDatasetFailsToQueue(string exception, bool retriable = false) { if (retriable) { _jobsApiClient .CreateJob(Arg.Any <JobCreateModel>()) .Throws(new NonRetriableException(exception)); } else { _jobsApiClient .CreateJob(Arg.Any <JobCreateModel>()) .Throws(new Exception(exception)); } }
public void CreateInstructGenerateAggregationsAllocationJob_GivenCreatingJobReturnsNull_ThrowsException() { //Arrange JobNotification jobNotification = CreateJobNotification(); string json = JsonConvert.SerializeObject(jobNotification); Message message = new Message(Encoding.UTF8.GetBytes(json)); IJobsApiClient jobsApiClient = CreateJobsApiClient(); jobsApiClient .CreateJob(Arg.Any <JobCreateModel>()) .Returns((Job)null); ILogger logger = CreateLogger(); JobService jobService = CreateJobService(jobsApiClient, logger); //Act Func <Task> test = () => jobService.CreateInstructAllocationJob(message); //Assert test .Should() .ThrowExactly <Exception>() .Which .Message .Should() .Be($"Failed to create new job of type: '{JobConstants.DefinitionNames.CreateInstructAllocationJob}'"); logger .Received(1) .Error(Arg.Is($"Failed to create new job of type: '{JobConstants.DefinitionNames.CreateInstructAllocationJob}'")); }
public async Task CreateInstructGenerateAggregationsAllocationJob_GivenJobCreated_LogsInformation() { //Arrange JobNotification jobNotification = CreateJobNotification(); string json = JsonConvert.SerializeObject(jobNotification); Message message = new Message(Encoding.UTF8.GetBytes(json)); Job job = new Job { Id = "job-id-1" }; IJobsApiClient jobsApiClient = CreateJobsApiClient(); jobsApiClient .CreateJob(Arg.Any <JobCreateModel>()) .Returns(job); ILogger logger = CreateLogger(); JobService jobService = CreateJobService(jobsApiClient, logger); //Act await jobService.CreateInstructAllocationJob(message); //Assert logger .Received(1) .Information(Arg.Is($"Created new job of type: '{JobConstants.DefinitionNames.CreateInstructAllocationJob}' with id: '{job.Id}'")); }
public async Task CreateInstructAllocationJob(Message message) { Guard.ArgumentNotNull(message, nameof(message)); JobNotification jobNotification = message.GetPayloadAsInstanceOf <JobNotification>(); if (jobNotification.CompletionStatus == CompletionStatus.Succeeded && jobNotification.JobType == JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob) { JobCreateModel jobCreateModel = new JobCreateModel { JobDefinitionId = JobConstants.DefinitionNames.CreateInstructAllocationJob, InvokerUserDisplayName = jobNotification.InvokerUserDisplayName, InvokerUserId = jobNotification.InvokerUserId, CorrelationId = message.GetCorrelationId(), SpecificationId = jobNotification.SpecificationId, Properties = new Dictionary <string, string> { { "specification-id", jobNotification.SpecificationId } }, Trigger = jobNotification.Trigger }; Job newJob = await _jobsApiClient.CreateJob(jobCreateModel); if (newJob == null) { _logger.Error($"Failed to create new job of type: '{JobConstants.DefinitionNames.CreateInstructAllocationJob}'"); throw new Exception($"Failed to create new job of type: '{JobConstants.DefinitionNames.CreateInstructAllocationJob}'"); } _logger.Information($"Created new job of type: '{JobConstants.DefinitionNames.CreateInstructAllocationJob}' with id: '{newJob.Id}'"); } }
public async Task <Job> CreateJob(string forCorrelationId, bool isHardDelete, Reference user, string correlationId) { try { Job job = await _resilience.ExecuteAsync(() => _jobs.CreateJob(new JobCreateModel { InvokerUserDisplayName = user.Name, InvokerUserId = user.Id, JobDefinitionId = PublishedFundingUndoJob, Properties = new Dictionary <string, string> { { ForCorrelationIdPropertyName, forCorrelationId }, { IsHardDeletePropertyName, isHardDelete.ToString() }, { "user-id", user.Id }, { "user-name", user.Name } }, Trigger = new Trigger { Message = $"Rollback publishing since correlation Id {forCorrelationId}" }, CorrelationId = correlationId })); if (job != null) { _logger.Information($"New job of type '{PublishedFundingUndoJob}' created with id: '{job.Id}'"); } else { _logger.Error($"Failed to create job of type '{PublishedFundingUndoJob}' for correlation id '{forCorrelationId}'"); } return(job); } catch (Exception ex) { _logger.Error(ex, $"Failed to queue published funding undo job for correlation id: {forCorrelationId}"); throw; } }
private async Task <Job> SendInstructAllocationsToJobService(string specificationId, Reference user, Trigger trigger, string correlationId, bool generateAggregations = false) { JobCreateModel job = new JobCreateModel { InvokerUserDisplayName = user.Name, InvokerUserId = user.Id, JobDefinitionId = generateAggregations ? JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob : JobConstants.DefinitionNames.CreateInstructAllocationJob, SpecificationId = specificationId, Properties = new Dictionary <string, string> { { "specification-id", specificationId }, { "ignore-save-provider-results", "true" } }, Trigger = trigger, CorrelationId = correlationId }; return(await _jobsApiClientPolicy.ExecuteAsync(() => _jobsApiClient.CreateJob(job))); }
private async Task SendInstructAllocationsToJobService(string providerCacheKey, string specificationId, string userId, string userName, Trigger trigger, string correlationId, bool generateCalculationAggregations) { JobCreateModel job = new JobCreateModel { InvokerUserDisplayName = userName, InvokerUserId = userId, JobDefinitionId = generateCalculationAggregations ? JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob : JobConstants.DefinitionNames.CreateInstructAllocationJob, SpecificationId = specificationId, Properties = new Dictionary <string, string> { { "specification-id", specificationId }, { "provider-cache-key", providerCacheKey } }, Trigger = trigger, CorrelationId = correlationId }; Job createdJob = await _jobsApiClientPolicy.ExecuteAsync(() => _jobsApiClient.CreateJob(job)); _logger.Information($"New job of type '{createdJob.JobDefinitionId}' created with id: '{createdJob.Id}'"); return; }
public async Task <Job> CreateReIndexJob(Reference user, string correlationId) { try { Job job = await _jobsClientPolicy.ExecuteAsync(() => _jobs.CreateJob(new JobCreateModel { JobDefinitionId = JobConstants.DefinitionNames.ReIndexTemplatesJob, InvokerUserId = user.Id, InvokerUserDisplayName = user.Name, CorrelationId = correlationId, Trigger = new Trigger { Message = "ReIndexing Templates", EntityType = nameof(TemplateIndex), } })); if (job != null) { _logger.Information($"New job of type '{job.JobDefinitionId}' created with id: '{job.Id}'"); } else { string errorMessage = $"Failed to create job of type '{JobConstants.DefinitionNames.ReIndexTemplatesJob}'"; _logger.Error(errorMessage); } return(job); } catch (Exception ex) { string error = "Failed to queue templates re-index job"; _logger.Error(ex, error); throw new Exception(error); } }
public async Task QueueJob_Called_ReturnsJob() { string specificationId = "1234"; string jobId = "3456"; IJobsApiClient jobsApiClient = Substitute.For <IJobsApiClient>(); JobManagementResiliencePolicies policies = new JobManagementResiliencePolicies { JobsApiClient = Policy.NoOpAsync() }; IMessengerService messengerService = Substitute.For <IMessengerService>(); ILogger logger = Substitute.For <ILogger>(); Job jobApiResponse = new Job { Id = jobId }; JobCreateModel jobCreateModel = new JobCreateModel { SpecificationId = specificationId }; jobsApiClient .CreateJob(jobCreateModel) .Returns(jobApiResponse); JobManagement jobManagement = new JobManagement(jobsApiClient, logger, policies, messengerService); //Act await jobManagement.QueueJob(jobCreateModel); await jobsApiClient .Received(1) .CreateJob(jobCreateModel); }
public async Task UpdateCalculationsForSpecification_GivenModelHasChangedPolicyNameAndSourceCodeContainsCalculationAggregate_SavesChangesEnsuresGenerateAggregationsJobCreated() { // Arrange const string specificationId = "spec-id"; Models.Specs.SpecificationVersionComparisonModel specificationVersionComparison = new Models.Specs.SpecificationVersionComparisonModel() { Id = specificationId, Current = new Models.Specs.SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" }, Name = "any-name", Policies = new[] { new Models.Specs.Policy { Id = "pol-id", Name = "policy2" } } }, Previous = new Models.Specs.SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" }, Policies = new[] { new Models.Specs.Policy { Id = "pol-id", Name = "policy1" } } } }; string json = JsonConvert.SerializeObject(specificationVersionComparison); Message message = new Message(Encoding.UTF8.GetBytes(json)); message.UserProperties.Add("user-id", UserId); message.UserProperties.Add("user-name", Username); ILogger logger = CreateLogger(); IEnumerable <Calculation> calcs = new[] { new Calculation { SpecificationId = "spec-id", Name = "any name", Id = "any-id", CalculationSpecification = new Reference("any name", "any-id"), FundingPeriod = new Reference("18/19", "2018/2019"), CalculationType = CalculationType.Number, FundingStream = new Reference("fp1", "fs1-111"), Current = new CalculationVersion { Author = new Reference(UserId, Username), Date = DateTimeOffset.Now, PublishStatus = PublishStatus.Draft, SourceCode = "return Min(calc1)", Version = 1 }, Policies = new List <Reference> { new Reference { Id = "pol-id", Name = "policy1" } } } }; BuildProject buildProject = new BuildProject { Id = "build-project-1", SpecificationId = specificationId }; ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .GetCalculationsBySpecificationId(Arg.Is(specificationId)) .Returns(calcs); IBuildProjectsService buildProjectsService = CreateBuildProjectsService(); buildProjectsService .GetBuildProjectForSpecificationId(Arg.Is(specificationId)) .Returns(buildProject); ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository(); IJobsApiClient jobsApiClient = CreateJobsApiClient(); jobsApiClient .CreateJob(Arg.Any <JobCreateModel>()) .Returns(new Job { Id = "job-id-1", JobDefinitionId = JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob }); CalculationService service = CreateCalculationService( calculationsRepository, logger, buildProjectsService: buildProjectsService, searchRepository: searchRepository, jobsApiClient: jobsApiClient); // Act await service.UpdateCalculationsForSpecification(message); // Assert await jobsApiClient .Received(1) .CreateJob(Arg.Is <JobCreateModel>( m => m.InvokerUserDisplayName == Username && m.InvokerUserId == UserId && m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob && m.Properties["specification-id"] == specificationId && m.Trigger.EntityId == specificationId && m.Trigger.EntityType == nameof(Models.Specs.Specification) && m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'" )); logger .Received(1) .Information(Arg.Is($"New job of type '{JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob}' created with id: 'job-id-1'")); }
public async Task UpdateCalculationsForSpecification_GivenModelHasChangedPolicyNameButCreatingJobReturnsNull_LogsError() { // Arrange const string specificationId = "spec-id"; Models.Specs.SpecificationVersionComparisonModel specificationVersionComparison = new Models.Specs.SpecificationVersionComparisonModel() { Id = specificationId, Current = new Models.Specs.SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" }, Name = "any-name", Policies = new[] { new Models.Specs.Policy { Id = "pol-id", Name = "policy2" } } }, Previous = new Models.Specs.SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" }, Policies = new[] { new Models.Specs.Policy { Id = "pol-id", Name = "policy1" } } } }; string json = JsonConvert.SerializeObject(specificationVersionComparison); Message message = new Message(Encoding.UTF8.GetBytes(json)); message.UserProperties.Add("user-id", UserId); message.UserProperties.Add("user-name", Username); ILogger logger = CreateLogger(); IEnumerable <Calculation> calcs = new[] { new Calculation { SpecificationId = "spec-id", Name = "any name", Id = "any-id", CalculationSpecification = new Reference("any name", "any-id"), FundingPeriod = new Reference("18/19", "2018/2019"), CalculationType = CalculationType.Number, FundingStream = new Reference("fp1", "fs1-111"), Current = new CalculationVersion { Author = new Reference(UserId, Username), Date = DateTimeOffset.Now, PublishStatus = PublishStatus.Draft, SourceCode = "source code", Version = 1 }, Policies = new List <Reference> { new Reference { Id = "pol-id", Name = "policy1" } } } }; BuildProject buildProject = new BuildProject { Id = "build-project-1", SpecificationId = specificationId }; ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .GetCalculationsBySpecificationId(Arg.Is(specificationId)) .Returns(calcs); IBuildProjectsService buildProjectsService = CreateBuildProjectsService(); buildProjectsService .GetBuildProjectForSpecificationId(Arg.Is(specificationId)) .Returns(buildProject); ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository(); IJobsApiClient jobsApiClient = CreateJobsApiClient(); jobsApiClient .CreateJob(Arg.Any <JobCreateModel>()) .Returns((Job)null); CalculationService service = CreateCalculationService( calculationsRepository, logger, buildProjectsService: buildProjectsService, searchRepository: searchRepository, jobsApiClient: jobsApiClient); // Act Func <Task> test = async() => await service.UpdateCalculationsForSpecification(message); // Assert test .Should() .ThrowExactly <RetriableException>() .Which .Message .Should() .Be($"Failed to create job: '{JobConstants.DefinitionNames.CreateInstructAllocationJob} for specification id '{specificationId}'"); await jobsApiClient .Received(1) .CreateJob(Arg.Is <JobCreateModel>( m => m.InvokerUserDisplayName == Username && m.InvokerUserId == UserId && m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructAllocationJob && m.Properties["specification-id"] == specificationId && m.Trigger.EntityId == specificationId && m.Trigger.EntityType == nameof(Models.Specs.Specification) && m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'" )); logger .Received(1) .Error(Arg.Is($"Failed to create job: '{JobConstants.DefinitionNames.CreateInstructAllocationJob} for specification id '{specificationId}'")); }
public async Task UpdateCalculationsForSpecification_GivenModelHasChangedFundingStreams_SetsTheAllocationLineAndFundingStreamToNull() { //Arrange const string specificationId = "spec-id"; Models.Specs.SpecificationVersionComparisonModel specificationVersionComparison = new Models.Specs.SpecificationVersionComparisonModel() { Id = specificationId, Current = new Models.Specs.SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" }, Name = "any-name", FundingStreams = new List <Reference> { new Reference { Id = "fs2" } } }, Previous = new Models.Specs.SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" }, FundingStreams = new List <Reference> { new Reference { Id = "fs1" } } } }; string json = JsonConvert.SerializeObject(specificationVersionComparison); Message message = new Message(Encoding.UTF8.GetBytes(json)); ILogger logger = CreateLogger(); IEnumerable <Calculation> calcs = new[] { new Calculation { SpecificationId = "spec-id", Name = "any name", Id = "any-id", CalculationSpecification = new Reference("any name", "any-id"), FundingPeriod = new Reference("18/19", "2018/2019"), CalculationType = CalculationType.Number, FundingStream = new Reference("fs1", "fs1-111"), Current = new CalculationVersion { Author = new Reference(UserId, Username), Date = DateTimeOffset.Now, PublishStatus = PublishStatus.Draft, SourceCode = "source code", Version = 1 }, Policies = new List <Reference>() } }; BuildProject buildProject = new BuildProject(); ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .GetCalculationsBySpecificationId(Arg.Is(specificationId)) .Returns(calcs); IBuildProjectsService buildProjectsService = CreateBuildProjectsService(); buildProjectsService .GetBuildProjectForSpecificationId(Arg.Is(specificationId)) .Returns(buildProject); ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository(); IJobsApiClient jobsApiClient = CreateJobsApiClient(); jobsApiClient .CreateJob(Arg.Any <JobCreateModel>()) .Returns(new Job { Id = "job-id-1" }); CalculationService service = CreateCalculationService(calculationsRepository, logger, buildProjectsService: buildProjectsService, searchRepository: searchRepository, jobsApiClient: jobsApiClient); //Act await service.UpdateCalculationsForSpecification(message); //Assert calcs .First() .FundingStream .Should() .BeNull(); calcs .First() .AllocationLine .Should() .BeNull(); await searchRepository .Received(1) .Index(Arg.Is <IEnumerable <CalculationIndex> >(c => c.First().Id == calcs.First().Id&& c.First().FundingStreamId == "" && c.First().FundingStreamName == "No funding stream set")); }
public async Task UpdatePublishedAllocationLineResultsStatus_GivenBatchingButNoUpdateModel_ReturnsBadRequest() { //arrange IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues> { { "specificationId", new StringValues(specificationId) }, }); IEnumerable <UpdatePublishedAllocationLineResultStatusProviderModel> Providers = new[] { new UpdatePublishedAllocationLineResultStatusProviderModel { ProviderId = "1111", AllocationLineIds = new[] { "AAAAA" } }, new UpdatePublishedAllocationLineResultStatusProviderModel { ProviderId = "1111-1", AllocationLineIds = new[] { "AAAAA" } }, new UpdatePublishedAllocationLineResultStatusProviderModel { ProviderId = "1111-2", AllocationLineIds = new[] { "AAAAA" } } }; UpdatePublishedAllocationLineResultStatusModel model = new UpdatePublishedAllocationLineResultStatusModel { Providers = Providers, Status = AllocationLineStatus.Approved }; string json = JsonConvert.SerializeObject(model); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpRequest request = Substitute.For <HttpRequest>(); request .Query .Returns(queryStringValues); request .Body .Returns(stream); ILogger logger = CreateLogger(); Job newJob = new Job { Id = "new-job-id" }; IEnumerable <PublishedProviderResult> publishedProviderResults = CreatePublishedProviderResultsWithDifferentProviders(); foreach (PublishedProviderResult publishedProviderResult in publishedProviderResults) { publishedProviderResult.FundingStreamResult.AllocationLineResult.Current.ProfilingPeriods = new[] { new ProfilingPeriod() }; } IJobsApiClient jobsApiClient = CreateJobsApiClient(); jobsApiClient .CreateJob(Arg.Any <JobCreateModel>()) .Returns(newJob); ICacheProvider cacheProvider = CreateCacheProvider(); PublishedResultsService resultsService = CreateResultsService(logger, jobsApiClient: jobsApiClient, cacheProvider: cacheProvider); //Act IActionResult actionResult = await resultsService.UpdatePublishedAllocationLineResultsStatus(request); //Arrange actionResult .Should() .BeAssignableTo <OkResult>(); logger .Received(1) .Information(Arg.Is($"New job: '{JobConstants.DefinitionNames.CreateInstructAllocationLineResultStatusUpdateJob}' created with id: '{newJob.Id}'")); await cacheProvider .Received(1) .SetAsync <UpdatePublishedAllocationLineResultStatusModel>(Arg.Any <string>(), Arg.Any <UpdatePublishedAllocationLineResultStatusModel>()); await jobsApiClient .Received(1) .CreateJob(Arg.Is <JobCreateModel>(m => !string.IsNullOrWhiteSpace(m.InvokerUserDisplayName) && !string.IsNullOrWhiteSpace(m.InvokerUserId) && m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructAllocationLineResultStatusUpdateJob && m.SpecificationId == specificationId && m.Properties["specification-id"] == specificationId && !string.IsNullOrWhiteSpace(m.Properties["cache-key"]) && m.Trigger.EntityId == specificationId && m.Trigger.EntityType == "Specification" && m.Trigger.Message == $"Updating allocation line results status" )); }
public async Task <Job> QueueJob(JobCreateModel jobCreateModel) => await _jobsApiClientPolicy.ExecuteAsync(() => _jobsApiClient.CreateJob(jobCreateModel));
public async Task <IActionResult> AssignDatasourceVersionToRelationship(HttpRequest request) { string json = await request.GetRawBodyStringAsync(); AssignDatasourceModel model = JsonConvert.DeserializeObject <AssignDatasourceModel>(json); if (model == null) { _logger.Error("Null AssignDatasourceModel was provided to AssignDatasourceVersionToRelationship"); return(new BadRequestObjectResult("Null AssignDatasourceModel was provided")); } Dataset dataset = await _datasetRepository.GetDatasetByDatasetId(model.DatasetId); if (dataset == null) { _logger.Error($"Dataset not found for dataset id: {model.DatasetId}"); return(new StatusCodeResult(412)); } DefinitionSpecificationRelationship relationship = await _datasetRepository.GetDefinitionSpecificationRelationshipById(model.RelationshipId); if (relationship == null) { _logger.Error($"Relationship not found for relationship id: {model.RelationshipId}"); return(new StatusCodeResult(412)); } relationship.DatasetVersion = new DatasetRelationshipVersion { Id = model.DatasetId, Version = model.Version }; HttpStatusCode statusCode = await _datasetRepository.UpdateDefinitionSpecificationRelationship(relationship); if (!statusCode.IsSuccess()) { _logger.Error($"Failed to assign data source to relationship : {model.RelationshipId} with status code {statusCode.ToString()}"); return(new StatusCodeResult((int)statusCode)); } Reference user = request.GetUser(); Trigger trigger = new Trigger { EntityId = dataset.Id, EntityType = nameof(Dataset), Message = $"Mapping dataset: '{dataset.Id}'" }; string correlationId = request.GetCorrelationId(); JobCreateModel job = new JobCreateModel { InvokerUserDisplayName = user.Name, InvokerUserId = user.Id, JobDefinitionId = JobConstants.DefinitionNames.MapDatasetJob, MessageBody = JsonConvert.SerializeObject(dataset), Properties = new Dictionary <string, string> { { "specification-id", relationship.Specification.Id }, { "relationship-id", relationship.Id } }, SpecificationId = relationship.Specification.Id, Trigger = trigger, CorrelationId = correlationId }; await _jobsApiClientPolicy.ExecuteAsync(() => _jobsApiClient.CreateJob(job)); return(new NoContentResult()); }