public static async Task Run([BlobTrigger(Constants.FailureOutputContainerName + "/{name}", Connection = Constants.AzureStorageConnectionStringEntry)] CloudBlockBlob cloudBlockBlob, string name, ILogger log) { log.LogInformation("Running ImageStatusUpdaterFailed"); await cloudBlockBlob.FetchAttributesAsync(); if (cloudBlockBlob.Metadata.ContainsKey(Constants.JobIdMetaData)) { string jobId = cloudBlockBlob.Metadata[Constants.JobIdMetaData]; log.LogInformation($"Found unsuccessfully converted blob {cloudBlockBlob.Name} with JobId {jobId}"); try { Jobs.JobsTable jobTable = new Jobs.JobsTable(); await jobTable.UpdateJobStatus(jobId, Jobs.JobStatusCode.Failure, null, cloudBlockBlob.Uri.AbsoluteUri); log.LogInformation($"Successfully updated JobId {jobId} to status Failure"); } catch (Exception ex) { log.LogError($"Could not update status of jobId: {jobId}: {ex.Message}"); } } else { log.LogError($"Error: {cloudBlockBlob.Name} has no {Constants.JobIdMetaData} metadata key."); } }
public static async Task Run([TimerTrigger("0 */2 * * * *")] TimerInfo myTimer, ILogger log) { log.LogInformation($"Cleanup starting at: {DateTime.Now}"); Jobs.JobsTable jobTable = new Jobs.JobsTable(); List <Jobs.Job> jobsToClean = (await jobTable.RetrieveAllJobs()) .Where(j => j.status == (int)Jobs.JobStatusCode.Success && j.imageSource != null) .ToList(); log.LogInformation($"Found {jobsToClean.Count} successful conversion jobs to clean up"); CloudStorageAccount storageAccount = Access.GetCloudStorageAccount(); await Task.WhenAll( jobsToClean.Select(j => { CloudBlockBlob blob = new CloudBlockBlob(new Uri(j.imageSource), storageAccount.Credentials); return(blob.DeleteIfExistsAsync() // Then update table to have no image source .ContinueWith(c => { j.imageSource = null; return jobTable.UpdateJob(j); })); }) ); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", Route = "v1/jobs")] HttpRequest req, ILogger log) { log.LogInformation("Getting status of all jobs"); try { Jobs.JobsTable jobTable = new Jobs.JobsTable(); return(new OkObjectResult( (await jobTable.RetrieveAllJobs()) .ConvertAll <DTOJobStatus>(j => new DTOJobStatus(j)) .ToList() )); } catch (Exception ex) { log.LogError($"Unable to retrieve jobs from job table: {ex.Message}"); return(new OkObjectResult(new List <DTOJobStatus>())); } }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", Route = "v1/jobs/{id}")] HttpRequest req, string id, ILogger log) { log.LogInformation($"Getting status of job {id}"); try { Jobs.JobsTable jobTable = new Jobs.JobsTable(); return(new OkObjectResult( new DTOJobStatus( await jobTable.RetrieveJob(id) ) )); } catch (Exception ex) { log.LogError($"Unable to retrieve job {id}: {ex.Message}"); return(new NotFoundObjectResult(new ErrorResponse(ErrorCode.NotFound, "id", id))); } }
public static async Task Run([BlobTrigger(Constants.GreyScaleInputContainerName + "/{name}", Connection = Constants.AzureStorageConnectionStringEntry)] CloudBlockBlob cloudBlockBlob, string name, ILogger log) { log.LogInformation("Running ImageConsumerGreyScale"); string convertedBlobName = $"{Guid.NewGuid().ToString()}-{name}"; string jobId = Guid.NewGuid().ToString(); log.LogInformation($"Associations: Converted Name: {convertedBlobName}, JobId: {jobId}"); // Add job to jobs table // (if fails, will not put image into failure container Jobs.JobsTable jobTable = new Jobs.JobsTable(); await jobTable.InsertOrReplaceJob(new Jobs.Job( jobId, Constants.GreyScaleMode, Jobs.JobStatusCode.Received, cloudBlockBlob.Uri.AbsoluteUri )); // Try to open image // (if can't open, then no way we can put it in failure container!) using (Stream blobStream = await cloudBlockBlob.OpenReadAsync()) { try { // Try to get output container // (if fails, will try to put image in failure container) // (doing now so we can fail early if something is wrong!) CloudBlobContainer successContainer = Access.GetSuccessOutputContainer(); await successContainer.CreateIfNotExistsAsync(); // Update job status to converting // (if fails, will log and still try to convert image) try { await jobTable.UpdateJobStatus(jobId, Jobs.JobStatusCode.Converting); } catch (Exception ex) { log.LogError($"Could not update status of jobId: {jobId}: {ex.Message}"); } // Try to convert and upload // (if fails, will try to put image in failure container) blobStream.Seek(0, SeekOrigin.Begin); using (MemoryStream convertedMemoryStream = new MemoryStream()) using (Image <Rgba32> image = Image.Load(blobStream)) { log.LogInformation($"Starting conversion of image {convertedBlobName}"); image.Mutate(x => x.Grayscale()); image.SaveAsJpeg(convertedMemoryStream); convertedMemoryStream.Seek(0, SeekOrigin.Begin); log.LogInformation($"Completed conversion of image {convertedBlobName}"); log.LogInformation($"Storing image {convertedBlobName} into {Constants.SuccessOutputContainerName} container"); // Upload to success container CloudBlockBlob convertedBlockBlob = successContainer.GetBlockBlobReference(convertedBlobName); convertedBlockBlob.Metadata.Add(Constants.JobIdMetaData, jobId); convertedBlockBlob.Properties.ContentType = System.Net.Mime.MediaTypeNames.Image.Jpeg; await convertedBlockBlob.UploadFromStreamAsync(convertedMemoryStream); log.LogInformation($"Stored image {convertedBlobName} into {Constants.SuccessOutputContainerName} container"); } } catch (Exception ex) { log.LogError($"Failed to convert blob {name}. {ex.Message}"); log.LogInformation($"Storing image {convertedBlobName} into {Constants.FailureOutputContainerName} container"); try { // Try to get failure container // (if fails, then hard fail.) CloudBlobContainer failureContainer = Access.GetFailureOutputContainer(); await failureContainer.CreateIfNotExistsAsync(); // Try to upload failed image. // (if fails, then hard fail) CloudBlockBlob failedBlockBlob = failureContainer.GetBlockBlobReference(convertedBlobName); failedBlockBlob.Metadata.Add(Constants.JobIdMetaData, jobId); blobStream.Seek(0, SeekOrigin.Begin); await failedBlockBlob.UploadFromStreamAsync(blobStream); log.LogInformation($"Stored image {convertedBlobName} into {Constants.FailureOutputContainerName} container"); } catch (Exception ex2) { // Hard fail. log.LogError($"Failed to store blob {name} into {Constants.FailureOutputContainerName}. {ex2.Message}"); } } } }