public override async Task Process(Message message)
        {
            Guard.ArgumentNotNull(message, nameof(message));

            JobSummary jobSummary = message.GetPayloadAsInstanceOf <JobSummary>();

            if (jobSummary.CompletionStatus == CompletionStatus.Succeeded && jobSummary.JobType == JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob)
            {
                JobCreateModel jobCreateModel = new JobCreateModel
                {
                    JobDefinitionId        = JobConstants.DefinitionNames.CreateInstructAllocationJob,
                    InvokerUserDisplayName = jobSummary.InvokerUserDisplayName,
                    InvokerUserId          = jobSummary.InvokerUserId,
                    CorrelationId          = message.GetCorrelationId(),
                    SpecificationId        = jobSummary.SpecificationId,
                    Properties             = new Dictionary <string, string>
                    {
                        { "specification-id", jobSummary.SpecificationId }
                    },
                    Trigger = jobSummary.Trigger
                };

                Job newJob = await _jobManagement.QueueJob(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}'");
            }
        }
Esempio n. 2
0
        public async Task <IViewComponentResult> InvokeAsync(int jobId, int requestId, JobStatuses targetStatus, CancellationToken cancellationToken)
        {
            JobSummary job = null;

            if (jobId > 0)
            {
                job = await _requestService.GetJobSummaryAsync(jobId, cancellationToken);

                requestId = job.RequestID;
            }
            var request = await _requestService.GetRequestSummaryAsync(requestId, cancellationToken);

            var user = await _authService.GetCurrentUser(HttpContext, cancellationToken);

            bool userIsAdmin = await _groupMemberService.GetUserHasRole(user.ID, request.ReferringGroupID, GroupRoles.TaskAdmin, true, cancellationToken);

            JobStatusChangePopupViewModel vm = await BuildVm(request, job, targetStatus, cancellationToken);

            if (job == null)
            {
                return((request.SingleJobStatus(), targetStatus, userIsAdmin) switch
                {
                    (_, JobStatuses.Done, true) => View("Admin_MarkRequestAsDonePopup", vm),
                    (_, JobStatuses.Cancelled, true) => View("Admin_CancelRequestPopup", vm),
                    _ => throw new Exception($"Unhandled status/admin combination for request: {request.SingleJobStatus()} -> {targetStatus} / admin:{userIsAdmin}")
                });
        public async Task CreateInstructGenerateAggregationsAllocationJob_GivenJobCreated_LogsInformation()
        {
            //Arrange
            JobSummary jobNotification = CreateJobSummary();

            string json = JsonConvert.SerializeObject(jobNotification);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            Job job = new Job
            {
                Id = "job-id-1"
            };

            IJobManagement jobManagement = CreateJobManagement();

            jobManagement
            .QueueJob(Arg.Any <JobCreateModel>())
            .Returns(job);

            ILogger logger = CreateLogger();

            JobService jobService = CreateJobService(jobManagement, logger);

            //Act
            await jobService.Process(message);

            //Assert
            logger
            .Received(1)
            .Information(Arg.Is($"Created new job of type: '{JobConstants.DefinitionNames.CreateInstructAllocationJob}' with id: '{job.Id}'"));
        }
        public void CreateInstructGenerateAggregationsAllocationJob_GivenCreatingJobReturnsNull_ThrowsException()
        {
            //Arrange
            JobSummary jobNotification = CreateJobSummary();

            string json = JsonConvert.SerializeObject(jobNotification);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            IJobManagement jobManagement = CreateJobManagement();

            jobManagement
            .QueueJob(Arg.Any <JobCreateModel>())
            .Returns((Job)null);

            ILogger logger = CreateLogger();

            JobService jobService = CreateJobService(jobManagement, logger);

            //Act
            Func <Task> test = () => jobService.Process(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}'"));
        }
Esempio n. 5
0
        public async Task <IActionResult> GetLatestSuccessfulJob(string specificationId, string jobDefinitionId)
        {
            Guard.ArgumentNotNull(specificationId, nameof(specificationId));
            Guard.ArgumentNotNull(jobDefinitionId, nameof(jobDefinitionId));

            string cacheKey = $"{CacheKeys.LatestSuccessfulJobs}{specificationId}:{jobDefinitionId}";
            Job    job      = await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.GetAsync <Job>(cacheKey));

            if (job == null)
            {
                job = await _jobRepository.GetLatestJobBySpecificationIdAndDefinitionId(specificationId, jobDefinitionId, CompletionStatus.Succeeded);

                if (job != null)
                {
                    await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.SetAsync(cacheKey, job));
                }
            }

            if (job == null)
            {
                return(new NotFoundObjectResult($"No successfully completed job found for specification '{specificationId}' and jobDefinitonId '{jobDefinitionId}'."));
            }

            JobSummary jobSummary = _mapper.Map <JobSummary>(job);

            return(new OkObjectResult(jobSummary));
        }
        public async Task ProcessJobCompletion_JobIsNotComplete_ThenNoActionTaken()
        {
            // Arrange
            IJobRepository jobRepository = CreateJobRepository();

            JobManagementService jobManagementService = CreateJobManagementService(jobRepository);

            string jobId = "abc123";

            JobSummary JobSummary = new JobSummary
            {
                JobId         = jobId,
                RunningStatus = RunningStatus.InProgress
            };

            string json = JsonConvert.SerializeObject(JobSummary);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties["jobId"] = jobId;

            // Act
            await jobManagementService.Process(message);

            // Assert
            await jobRepository
            .DidNotReceive()
            .GetJobById(Arg.Is(jobId));
        }
        public async Task ProcessJobCompletion_JobIdIsNotSet_ThenNoActionTakenAndErrorLogged()
        {
            // Arrange
            ILogger        logger        = CreateLogger();
            IJobRepository jobRepository = CreateJobRepository();

            JobManagementService jobManagementService = CreateJobManagementService(jobRepository, logger: logger);

            JobSummary JobSummary = new JobSummary {
                RunningStatus = RunningStatus.Completed
            };

            string json = JsonConvert.SerializeObject(JobSummary);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            // Act
            await jobManagementService.Process(message);

            // Assert
            logger
            .Received(1)
            .Error(Arg.Is("Job Notification message has no JobId"));

            await jobRepository
            .DidNotReceive()
            .GetJobById(Arg.Any <string>());
        }
        public async Task ProcessJobCompletion_JobIdNotFound_ThenNoActionTakenAndErrorLogged()
        {
            // Arrange
            string jobId = "abc123";

            ILogger        logger        = CreateLogger();
            IJobRepository jobRepository = CreateJobRepository();

            jobRepository
            .GetJobById(Arg.Is(jobId))
            .Returns((Job)null);

            JobManagementService jobManagementService = CreateJobManagementService(jobRepository, logger: logger);

            JobSummary JobSummary = new JobSummary {
                RunningStatus = RunningStatus.Completed
            };

            string json = JsonConvert.SerializeObject(JobSummary);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties["jobId"] = jobId;

            // Act
            await jobManagementService.Process(message);

            // Assert
            logger
            .Received(1)
            .Error(Arg.Is("Could not find job with id {JobId}"), Arg.Is(jobId));
        }
Esempio n. 9
0
        public async Task <IActionResult> GetLatestJobs(string specificationId, string jobTypes)
        {
            Guard.ArgumentNotNull(specificationId, nameof(specificationId));

            string[] jobDefinitionIds =
                !string.IsNullOrEmpty(jobTypes) ?
                jobTypes.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                : Array.Empty <string>();

            if (!jobDefinitionIds.Any())
            {
                return(new BadRequestObjectResult("JobTypes must be provided to get latest jobs."));
            }

            ConcurrentDictionary <string, Job> jobsByDefinition = new ConcurrentDictionary <string, Job>();

            List <Task> allTasks = new List <Task>();

            foreach (string jobDefinitionId in jobDefinitionIds.Distinct())
            {
                allTasks.Add(
                    Task.Run(async() =>
                {
                    string cacheKey = $"{CacheKeys.LatestJobs}{specificationId}:{jobDefinitionId}";

                    Job job = await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.GetAsync <Job>(cacheKey));

                    if (job != null)
                    {
                        jobsByDefinition[jobDefinitionId] = job;
                    }
                    else
                    {
                        job = await _jobRepository.GetLatestJobBySpecificationIdAndDefinitionId(specificationId, jobDefinitionId);

                        // create a new empty job if no job so we don't continually make calls as the cache will be invalidated in the create job and update job
                        // with a valid job so this will only be hit if redis is empty or a job has never been created
                        job ??= new Job();

                        await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.SetAsync(cacheKey, job));

                        jobsByDefinition[jobDefinitionId] = job;
                    }
                }));
            }

            await TaskHelper.WhenAllAndThrow(allTasks.ToArray());

            IEnumerable <JobSummary> jobSummaries = _mapper.Map <IEnumerable <JobSummary> >(jobsByDefinition.Values);

            JobSummary[] results = new JobSummary[jobDefinitionIds.Length];
            for (int i = 0; i < jobDefinitionIds.Length; i++)
            {
                results[i] = jobSummaries.FirstOrDefault(x => string.Equals(x.JobDefinitionId, jobDefinitionIds[i], StringComparison.InvariantCultureIgnoreCase));
            }

            return(new OkObjectResult(results));
        }
        public async Task ProcessJobCompletion_JobHasParentTwoChildrenOnlyOneCompleted_ThenParentNotCompleted()
        {
            // Arrange
            string parentJobId = "parent123";
            string jobId       = "child123";

            Job job = new Job {
                Id = jobId, ParentJobId = parentJobId, CompletionStatus = CompletionStatus.Succeeded, RunningStatus = RunningStatus.Completed
            };

            Job job2 = new Job {
                Id = "child456", ParentJobId = parentJobId, RunningStatus = RunningStatus.InProgress
            };

            Job parentJob = new Job {
                Id = parentJobId, RunningStatus = RunningStatus.InProgress
            };

            ILogger        logger        = CreateLogger();
            IJobRepository jobRepository = CreateJobRepository();

            jobRepository
            .GetJobById(Arg.Is(jobId))
            .Returns(job);

            jobRepository
            .GetJobById(Arg.Is(parentJobId))
            .Returns(parentJob);

            jobRepository
            .GetChildJobsForParent(Arg.Is(parentJobId))
            .Returns(new List <Job> {
                job, job2
            });

            JobManagementService jobManagementService = CreateJobManagementService(jobRepository, logger: logger);

            JobSummary JobSummary = new JobSummary {
                JobId = jobId, RunningStatus = RunningStatus.Completed
            };

            string  json    = JsonConvert.SerializeObject(JobSummary);
            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties["jobId"] = jobId;

            // Act
            await jobManagementService.Process(message);

            // Assert
            await jobRepository
            .DidNotReceive()
            .UpdateJob(Arg.Is <Job>(j => j.Id == parentJobId && j.RunningStatus == RunningStatus.Completed && j.Completed.HasValue));

            logger
            .Received(1)
            .Information(Arg.Is("Completed Job {JobId} parent {ParentJobId} has in progress child jobs and cannot be completed"), Arg.Is(jobId), Arg.Is(parentJobId));
        }
        public async Task ProcessJobCompletion_JobHasParentWithMultipleCompletedChildrenWithAllSucceeded_ThenParentCompletedStatusIsSucceeded()
        {
            // Arrange
            string parentJobId = "parent123";
            string jobId       = "child123";

            Job job = new Job {
                Id = jobId, ParentJobId = parentJobId, CompletionStatus = CompletionStatus.Succeeded, RunningStatus = RunningStatus.Completed
            };

            Job job2 = new Job {
                Id = "child456", ParentJobId = parentJobId, RunningStatus = RunningStatus.Completed, CompletionStatus = CompletionStatus.Succeeded
            };

            Job job3 = new Job {
                Id = "child789", ParentJobId = parentJobId, RunningStatus = RunningStatus.Completed, CompletionStatus = CompletionStatus.Succeeded
            };

            Job parentJob = new Job {
                Id = parentJobId, RunningStatus = RunningStatus.InProgress
            };

            ILogger        logger        = CreateLogger();
            IJobRepository jobRepository = CreateJobRepository();

            jobRepository
            .GetJobById(Arg.Is(jobId))
            .Returns(job);

            jobRepository
            .GetJobById(Arg.Is(parentJobId))
            .Returns(parentJob);

            jobRepository
            .GetChildJobsForParent(Arg.Is(parentJobId))
            .Returns(new List <Job> {
                job, job2
            });

            JobManagementService jobManagementService = CreateJobManagementService(jobRepository, logger: logger);

            JobSummary JobSummary = new JobSummary {
                JobId = jobId, RunningStatus = RunningStatus.Completed
            };

            string  json    = JsonConvert.SerializeObject(JobSummary);
            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties["jobId"] = jobId;

            // Act
            await jobManagementService.Process(message);

            // Assert
            await jobRepository
            .Received(1)
            .UpdateJob(Arg.Is <Job>(j => j.Id == parentJobId && j.CompletionStatus == CompletionStatus.Succeeded));
        }
        public async Task GetLatestJobForSpecification()
        {
            string     specificationId = NewRandomString();
            string     jobDefinitonId  = NewRandomString();
            JobSummary jobsummary      = NewJobSummary();

            await AssertGetRequest($"jobs/latest-success?specificationId={specificationId}&jobDefinitonId={jobDefinitonId}",
                                   jobsummary,
                                   () => _client.GetLatestSuccessfulJobForSpecification(specificationId, jobDefinitonId));
        }
        public async Task GetLatestJobByTriggerEntityId()
        {
            string     specificationId = NewRandomString();
            string     entityId        = NewRandomString();
            JobSummary jobsummary      = NewJobSummary();

            await AssertGetRequest($"jobs/latest-by-entity-id?specificationId={specificationId}&entityId={entityId}",
                                   jobsummary,
                                   () => _client.GetLatestJobByTriggerEntityId(specificationId, entityId));
        }
Esempio n. 14
0
        public async Task OnNotificationEvent_WhenChildJobWithSpecificationIdIsCreated_ThenSignalRMessagesAdded()
        {
            // Arrange
            NotificationService service = CreateService();

            JobSummary jobNotification = new JobSummary()
            {
                CompletionStatus = null,
                JobId            = JobId,
                JobType          = "test",
                SpecificationId  = SpecificationId,
                ParentJobId      = "parentJobId1",
            };

            string json = JsonConvert.SerializeObject(jobNotification);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            IAsyncCollector <SignalRMessage> generatedMessages = CreateSignalRMessageCollector();

            // Act
            await service.OnNotificationEvent(message, generatedMessages);

            // Assert
            await generatedMessages
            .Received(2)
            .AddAsync(Arg.Any <SignalRMessage>());

            await generatedMessages
            .Received(1)
            .AddAsync(
                Arg.Is <SignalRMessage>(
                    c => c.Target == JobConstants.NotificationsTargetFunction &&
                    c.Arguments.Length == 1 &&
                    c.Arguments.First() != null &&
                    c.GroupName == JobConstants.NotificationChannels.All));

            await generatedMessages
            .Received(1)
            .AddAsync(
                Arg.Is <SignalRMessage>(
                    c => c.Target == JobConstants.NotificationsTargetFunction &&
                    c.Arguments.Length == 1 &&
                    c.Arguments.First() != null &&
                    c.GroupName == $"{JobConstants.NotificationChannels.SpecificationPrefix}{SpecificationId.Replace("-", "")}"));

            await generatedMessages
            .Received(0)
            .AddAsync(
                Arg.Is <SignalRMessage>(
                    c => c.Target == JobConstants.NotificationsTargetFunction &&
                    c.Arguments.Length == 1 &&
                    c.Arguments.First() != null &&
                    c.GroupName == JobConstants.NotificationChannels.ParentJobs));
        }
Esempio n. 15
0
        public static JobViewModel ToViewModel(this JobSummary job)
        {
            if (job == null)
            {
                return(null);
            }

            return(new JobViewModel {
                Name = job.Name, Percent = job.Percent, Status = job.Status.ToString()
            });
        }
Esempio n. 16
0
        private void GivenTheJobForTheJobId(Action <JobSummaryBuilder> setUp = null)
        {
            JobSummaryBuilder jobSummaryBuilder = new JobSummaryBuilder();

            setUp?.Invoke(jobSummaryBuilder);

            _job = jobSummaryBuilder.Build();

            _jobs.GetLatestJobsForSpecification(_specificationId, Arg.Is <IEnumerable <string> >(_ => _.Single() == JobConstants.DefinitionNames.CreateInstructAllocationJob))
            .Returns(new[] { _job });
        }
        public async Task GetLatestSuccessfulJobs_WhenSucessfulJobForSpecificationAndJobDefinitionNOtExistsInCache_RetrieveAndReturnJobFromRepository()
        {
            // Arrange
            string specificationId = NewRandomString();
            string jobDefinitionId = NewRandomString();
            string jobId           = NewRandomString();

            Job job = new Job
            {
                Created = DateTimeOffset.UtcNow.AddHours(-1),
                Id      = jobId,
                InvokerUserDisplayName = "test",
                InvokerUserId          = "test1",
                JobDefinitionId        = jobDefinitionId,
                LastUpdated            = DateTimeOffset.UtcNow.AddHours(-1),
                RunningStatus          = RunningStatus.InProgress,
                SpecificationId        = specificationId,
                Trigger = new Trigger {
                    EntityId = "calc1", EntityType = "Calculation", Message = "Calc run started"
                }
            };

            ICacheProvider cacheProvider = CreateCacheProvider();

            string cacheKey = $"{CacheKeys.LatestSuccessfulJobs}{specificationId}:{jobDefinitionId}";

            cacheProvider.GetAsync <Job>(cacheKey).Returns((Job)null);

            IJobRepository jobRepository = CreateJobRepository();

            jobRepository
            .GetLatestJobBySpecificationIdAndDefinitionId(specificationId, jobDefinitionId, CompletionStatus.Succeeded)
            .Returns(job);

            IJobService service = CreateJobService(cacheProvider: cacheProvider, jobRepository: jobRepository);

            // Act
            IActionResult result = await service.GetLatestSuccessfulJob(specificationId, jobDefinitionId);

            // Assert
            OkObjectResult okResult = result
                                      .Should()
                                      .BeOfType <OkObjectResult>()
                                      .Subject;

            JobSummary jobSummary = okResult.Value
                                    .Should()
                                    .BeAssignableTo <JobSummary>()
                                    .Subject;

            jobSummary.JobId.Should().Be(jobId);
        }
        private async Task EnsureFeedbackCanBeGiven(JobSummary jobSummary, RequestRoles requestRole, int?userId)
        {
            if (jobSummary.JobStatus.Incomplete())
            {
                throw new Exception($"Attempt to load feedback form for job {jobSummary.JobID}, but it is {jobSummary.JobStatus}");
            }

            if (await _feedbackRepository.GetFeedbackExists(jobSummary.JobID, requestRole, userId))
            {
                throw new Exception($"Attempt to load feedback form for job {jobSummary.JobID}, but feedback already exists for role {requestRole} / user {userId}");
            }

            if (jobSummary.Archive == true)
            {
                throw new Exception($"Attempt to load feedback form for achived job {jobSummary.JobID}");
            }
        }
        public void GetJobs_CheckFieldsMapped()
        {
            // Arrange
            string entityId = "entity99";

            IJobRepository jobRepository = CreateJobRepository();

            jobRepository
            .GetJobs()
            .Returns(testData.AsQueryable());

            IJobService jobService = CreateJobService(jobRepository);

            // Act
            IActionResult results = jobService.GetJobs(null, null, entityId, null, null, false, 1);

            // Assert
            OkObjectResult objResult = results
                                       .Should()
                                       .BeOfType <OkObjectResult>()
                                       .Subject;

            JobQueryResponseModel response = objResult.Value
                                             .Should()
                                             .BeOfType <JobQueryResponseModel>()
                                             .Subject;

            IEnumerable <JobSummary> summaries = response.Results;

            summaries
            .Should()
            .HaveCount(1);

            JobSummary item = summaries.First();

            item.CompletionStatus.Should().Be(CompletionStatus.Succeeded);
            item.EntityId.Should().Be(entityId);
            item.InvokerUserDisplayName.Should().Be("Test User");
            item.InvokerUserId.Should().Be("testuser");
            item.JobId.Should().Be("job14");
            item.JobType.Should().Be("jobType3");
            item.ParentJobId.Should().Be("job1");
            item.RunningStatus.Should().Be(RunningStatus.Completed);
            item.SpecificationId.Should().Be("spec123");
            item.Created.Should().Be(DateTimeOffset.Parse("2018-12-20T15:15:00.000Z"));
        }
        public async Task GetLatestJob_WhenSingleJobTypeGiven_ReturnLatestJobOfType()
        {
            // Arrange
            string specificationId = "spec123";

            string jobType = "jobType1";

            IJobRepository jobRepository = CreateJobRepository();

            jobRepository
            .GetLatestJobBySpecificationId(Arg.Is(specificationId), Arg.Is <IEnumerable <string> >(m => m.First() == "jobType1"))
            .Returns(
                new Job
            {
                Created = DateTimeOffset.UtcNow.AddHours(-1),
                Id      = "job1",
                InvokerUserDisplayName = "test",
                InvokerUserId          = "test1",
                JobDefinitionId        = "jobType1",
                LastUpdated            = DateTimeOffset.UtcNow.AddHours(-1),
                RunningStatus          = RunningStatus.InProgress,
                SpecificationId        = specificationId,
                Trigger = new Trigger {
                    EntityId = "calc1", EntityType = "Calculation", Message = "Calc run started"
                }
            });

            IJobService service = CreateJobService(jobRepository);

            // Act
            IActionResult result = await service.GetLatestJob(specificationId, jobType);

            // Assert
            OkObjectResult okResult = result
                                      .Should()
                                      .BeOfType <OkObjectResult>()
                                      .Subject;

            JobSummary summary = okResult.Value
                                 .Should()
                                 .BeOfType <JobSummary>()
                                 .Subject;

            summary.JobId.Should().Be("job1");
        }
        public async Task OnNotificationEvent(Message message, IAsyncCollector <SignalRMessage> signalRMessages)
        {
            Guard.ArgumentNotNull(message, nameof(message));
            Guard.ArgumentNotNull(signalRMessages, nameof(signalRMessages));

            JobSummary jobNotification = message.GetPayloadAsInstanceOf <JobSummary>();

            if (jobNotification == null)
            {
                throw new InvalidOperationException("Job notificiation was null");
            }

            // Send to all notifications channel
            await signalRMessages.AddAsync(
                new SignalRMessage
            {
                Target    = JobConstants.NotificationsTargetFunction,
                GroupName = JobConstants.NotificationChannels.All,
                Arguments = new[] { jobNotification }
            });

            if (!string.IsNullOrWhiteSpace(jobNotification.SpecificationId))
            {
                // Send to individual specifications group
                await signalRMessages.AddAsync(
                    new SignalRMessage
                {
                    Target    = JobConstants.NotificationsTargetFunction,
                    GroupName = $"{JobConstants.NotificationChannels.SpecificationPrefix}{jobNotification.SpecificationId.Replace("-", "")}",
                    Arguments = new[] { jobNotification }
                });
            }

            if (string.IsNullOrWhiteSpace(jobNotification.ParentJobId))
            {
                // Send to parent jobs only group
                await signalRMessages.AddAsync(
                    new SignalRMessage
                {
                    Target    = JobConstants.NotificationsTargetFunction,
                    GroupName = JobConstants.NotificationChannels.ParentJobs,
                    Arguments = new[] { jobNotification }
                });
            }
        }
Esempio n. 22
0
        public async Task <bool> QueueJobAndWait(Func <Task <bool> > queueJob, string jobType, string specificationId, string correlationId, string jobNotificationTopic, double pollTimeout = 600000, double pollInterval = 120000)
        {
            if (IsServiceBusService)
            {
                await((IServiceBusService)_messengerService).CreateSubscription(jobNotificationTopic, correlationId, new TimeSpan(1, 0, 0, 0));
            }

            bool jobQueued = await queueJob();

            try
            {
                if (jobQueued)
                {
                    if (IsServiceBusService)
                    {
                        JobSummary scopedJob = await _messengerService.ReceiveMessage <JobSummary>($"{jobNotificationTopic}/Subscriptions/{correlationId}", _ =>
                        {
                            return(_?.JobType == jobType &&
                                   _.SpecificationId == specificationId &&
                                   (_.CompletionStatus == CompletionStatus.Succeeded || _.CompletionStatus == CompletionStatus.Failed));
                        },
                                                                                                   TimeSpan.FromMilliseconds(pollTimeout));

                        return(scopedJob?.CompletionStatus == CompletionStatus.Succeeded);
                    }
                    else
                    {
                        return(await WaitForJobToComplete(jobType, specificationId, pollTimeout, pollInterval));
                    }
                }
                else
                {
                    // if job not queued then return true
                    return(true);
                }
            }
            finally
            {
                if (IsServiceBusService)
                {
                    await((IServiceBusService)_messengerService).DeleteSubscription(jobNotificationTopic, correlationId);
                }
            }
        }
Esempio n. 23
0
        private async Task <bool> CheckAllJobs(string jobType, string specificationId, Predicate <JobSummary> predicate)
        {
            ApiResponse <IDictionary <string, JobSummary> > jobResponse = await _jobsApiClientPolicy.ExecuteAsync(() =>
            {
                return(_jobsApiClient.GetLatestJobsForSpecification(specificationId, new string[] { jobType }));
            });

            if ((int?)jobResponse?.StatusCode >= 200 && (int?)jobResponse?.StatusCode <= 299)
            {
                JobSummary summary = jobResponse.Content?.Values.FirstOrDefault();

                return(predicate(summary));
            }
            else
            {
                // any failures retrieving jobsummaries we ignore and keep polling as we don't know what state the jobs are in
                return(true);
            }
        }
        public void BuildRequestModel_GivenJobNotificationWithDefinitionNotConfiguredForScaling_ContainsNoRepositoryTypes()
        {
            //Arrange
            JobSummary jobNotification = new JobSummary
            {
                JobType = "any-job-def-id"
            };

            CosmosDbScalingRequestModelBuilder builder = new CosmosDbScalingRequestModelBuilder();

            //Act
            CosmosDbScalingRequestModel requestModel = builder.BuildRequestModel(jobNotification);

            //Assert
            requestModel
            .RepositoryTypes
            .Should()
            .BeNull();
        }
        public async Task GetNonCompletedJobsWithinTimeFrame_Called_ReturnsJobSummaries()
        {
            string jobId = "5678";

            DateTimeOffset from = DateTimeOffset.UtcNow.AddDays(-2);
            DateTimeOffset to   = DateTimeOffset.UtcNow.AddDays(-1);

            IJobsApiClient jobsApiClient             = Substitute.For <IJobsApiClient>();
            JobManagementResiliencePolicies policies = new JobManagementResiliencePolicies
            {
                JobsApiClient = Policy.NoOpAsync()
            };
            IMessengerService messengerService = Substitute.For <IMessengerService>();
            ILogger           logger           = Substitute.For <ILogger>();


            JobSummary jobSummary = new JobSummary
            {
                JobId = jobId
            };
            IEnumerable <JobSummary> jobSummaries = new List <JobSummary>
            {
                jobSummary
            };
            ApiResponse <IEnumerable <JobSummary> > jobSummariesApiResponse
                = new ApiResponse <IEnumerable <JobSummary> >(HttpStatusCode.OK, jobSummaries);

            jobsApiClient
            .GetNonCompletedJobsWithinTimeFrame(from, to)
            .Returns(jobSummariesApiResponse);

            JobManagement jobManagement = new JobManagement(jobsApiClient, logger, policies, messengerService);

            //Act
            IEnumerable <JobSummary> result = await jobManagement.GetNonCompletedJobsWithinTimeFrame(from, to);

            Assert.AreEqual(result, jobSummaries);

            await jobsApiClient
            .Received(1)
            .GetNonCompletedJobsWithinTimeFrame(from, to);
        }
        public async Task ProcessJobCompletion_JobHasNoParent_ThenNoActionTakenAndMessageLogged()
        {
            // Arrange
            string jobId = "abc123";

            Job job = new Job {
                Id = jobId, ParentJobId = null
            };

            ILogger        logger        = CreateLogger();
            IJobRepository jobRepository = CreateJobRepository();

            jobRepository
            .GetJobById(Arg.Is(jobId))
            .Returns(job);

            JobManagementService jobManagementService = CreateJobManagementService(jobRepository, logger: logger);

            JobSummary JobSummary = new JobSummary
            {
                JobId         = jobId,
                RunningStatus = RunningStatus.Completed
            };

            string json = JsonConvert.SerializeObject(JobSummary);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties["jobId"] = jobId;

            // Act
            await jobManagementService.Process(message);

            // Assert
            logger
            .Received(1)
            .Information(Arg.Is("Completed Job {JobId} has no parent"), Arg.Is(jobId));

            await jobRepository
            .DidNotReceive()
            .GetChildJobsForParent(Arg.Any <string>());
        }
Esempio n. 27
0
        public void SendNotification_WhenNoJobId_ThrowsArgumentException()
        {
            // Arrange
            INotificationService notificationService = CreateNotificationService();

            JobSummary jobSummary = CreateJobSummary();

            jobSummary.JobId = string.Empty;

            Func <Task> action = async() => await notificationService.SendNotification(jobSummary);

            // Act and Assert
            action
            .Should()
            .Throw <ArgumentException>()
            .And
            .ParamName
            .Should()
            .Be("JobId");
        }
Esempio n. 28
0
        public void SendNotification_WhenNoTrigger_ThrowsArgumentNullException()
        {
            // Arrange
            INotificationService notificationService = CreateNotificationService();

            JobSummary jobSummary = CreateJobSummary();

            jobSummary.Trigger = null;

            Func <Task> action = async() => await notificationService.SendNotification(jobSummary);

            // Act and Assert
            action
            .Should()
            .Throw <ArgumentNullException>()
            .And
            .ParamName
            .Should()
            .Be("Trigger");
        }
        public void BuildRequestModel_GivenJobWithDefinitions_EnsuresCorrectRepositoryTypes(string jobDefinitionId,
                                                                                            CosmosCollectionType[] cosmosRepositoryTypes)
        {
            //Arrange
            JobSummary jobNotification = new JobSummary
            {
                JobType = jobDefinitionId
            };

            CosmosDbScalingRequestModelBuilder builder = new CosmosDbScalingRequestModelBuilder();

            //Act
            CosmosDbScalingRequestModel requestModel = builder.BuildRequestModel(jobNotification);

            //Assert
            requestModel
            .RepositoryTypes
            .SequenceEqual(cosmosRepositoryTypes)
            .Should()
            .BeTrue();
        }
        private async Task QueueNotifications(IEnumerable <JobCreateResult> createdJobs, IEnumerable <JobDefinition> jobDefinitionsToSupersede)
        {
            List <Task>   allTasks  = new List <Task>();
            SemaphoreSlim throttler = new SemaphoreSlim(initialCount: 30);

            foreach (JobCreateResult jobCreateResult in createdJobs)
            {
                await throttler.WaitAsync();

                allTasks.Add(
                    Task.Run(async() =>
                {
                    try
                    {
                        Job job = jobCreateResult.Job;

                        JobDefinition jobDefinition = jobDefinitionsToSupersede.First(m => m.Id == job.JobDefinitionId);

                        await QueueNewJob(job, jobDefinition, jobCreateResult.CreateRequest.Compress);

                        JobSummary jobNotification = CreateJobNotificationFromJob(job);

                        jobCreateResult.WasQueued = true;

                        await _notificationService.SendNotification(jobNotification);
                    }
                    catch (QueueJobException queueJobException)
                    {
                        jobCreateResult.Error = queueJobException.Message;
                    }
                    finally
                    {
                        throttler.Release();
                    }
                }));
            }

            await TaskHelper.WhenAllAndThrow(allTasks.ToArray());
        }