public async Task <IActionResult> QueueBatchUploadValidation(BatchUploadValidationRequest batchUploadValidationRequest,
                                                                     Reference user,
                                                                     string correlationId)
        {
            ValidationResult validationResult = await _requestValidation.ValidateAsync(batchUploadValidationRequest);

            if (!validationResult.IsValid)
            {
                BadRequestObjectResult badRequest = validationResult.AsBadRequest();

                _logger.Warning($"Unable to queue batch upload validation job as validation errors.\n{badRequest.Value}");

                return(badRequest);
            }

            BatchUploadValidationProperties properties = batchUploadValidationRequest;

            Job job = await QueueJob(new JobCreateModel
            {
                CorrelationId          = correlationId,
                InvokerUserId          = user?.Id,
                InvokerUserDisplayName = user?.Name,
                JobDefinitionId        = BatchPublishedProviderValidationJob,
                SpecificationId        = batchUploadValidationRequest.SpecificationId,
                Trigger    = new Trigger(),
                Properties = (Dictionary <string, string>)properties
            });

            return(new OkObjectResult(new
            {
                JobId = job.Id
            }));
        }
        public override async Task Process(Message message)
        {
            BatchUploadValidationProperties properties = message;

            string batchId         = properties.BatchId;
            string fundingStreamId = properties.FundingStreamId;
            string fundingPeriodId = properties.FundingPeriodId;

            BatchUploadBlobName blobName = new BatchUploadBlobName(batchId);

            IBatchUploadReader batchUploadReader = _batchUploadReaderFactory.CreateBatchUploadReader();

            await batchUploadReader.LoadBatchUpload(blobName);

            List <string> publishedProviderIds = new List <string>();
            List <string> missingUkprns        = new List <string>();

            _logger.Information($"Starting validation for batch {batchId} with a total of {batchUploadReader.Count} to check");

            while (batchUploadReader.HasPages)
            {
                string[] page = batchUploadReader.NextPage()?.ToArray() ?? new string[0];

                IDictionary <string, string> publishedProviderIdPage = await _publishedFundingResilience.ExecuteAsync(() => _publishedFunding.GetPublishedProviderIdsForUkprns(fundingStreamId,
                                                                                                                                                                               fundingPeriodId,
                                                                                                                                                                               page)) ?? new Dictionary <string, string>();

                if (page.Length != publishedProviderIdPage.Count)
                {
                    missingUkprns.AddRange(page.Except(publishedProviderIdPage.Keys));
                }

                publishedProviderIds.AddRange(publishedProviderIdPage.Values);

                ItemsProcessed = ItemsProcessed.GetValueOrDefault() + publishedProviderIdPage.Count;
            }

            ItemsProcessed = batchUploadReader.Count;

            if (missingUkprns.Any())
            {
                ItemsFailed = missingUkprns.Count;

                throw new NonRetriableException(
                          $"Did not locate the following ukprns for {fundingStreamId} and {fundingPeriodId}:\n{missingUkprns.JoinWith(',')}");
            }

            byte[] publishedProviderIdsJsonBytes = JsonExtensions.AsJsonBytes(publishedProviderIds.ToArray());

            BatchUploadProviderIdsBlobName batchUploadProviderIdsBlobName = new BatchUploadProviderIdsBlobName(batchId);

            ICloudBlob cloudBlob = _blobClient.GetBlockBlobReference(batchUploadProviderIdsBlobName, ContainerName);

            await _blobClientResilience.ExecuteAsync(() => cloudBlob.UploadFromByteArrayAsync(publishedProviderIdsJsonBytes, 0, publishedProviderIdsJsonBytes.Length));
        }