/// <summary> /// Uploads a given image to the converted images container /// /// The given image should already have the desired filter applied /// </summary> /// <param name="jobEntity"></param> /// <param name="blobName"></param> /// <param name="convertedImage"></param> public async void UploadConvertedImage(JobEntity jobEntity, string blobName, MemoryStream convertedImage) { CloudBlobContainer convertedImagesContainer = _blobClient.GetContainerReference(ConfigSettings.CONVERTED_IMAGES_CONTAINER_NAME); CloudBlockBlob convertedBlockBlob = convertedImagesContainer.GetBlockBlobReference(blobName); convertedBlockBlob.Metadata.Add(ConfigSettings.JOBID_METADATA_NAME, jobEntity.JobId); convertedBlockBlob.Metadata.Add(ConfigSettings.IMAGE_CONVERSION_MODE_METADATA_NAME, jobEntity.ImageConversionMode); convertedBlockBlob.Metadata.Add(ConfigSettings.IMAGE_SOURCE_METADATA_NAME, jobEntity.ImageSource); convertedBlockBlob.Properties.ContentType = System.Net.Mime.MediaTypeNames.Image.Jpeg; await convertedBlockBlob.UploadFromStreamAsync(convertedImage); }
public static async void Run([BlobTrigger(route, Connection = ConfigSettings.STORAGE_CONNECTIONSTRING_NAME)] Stream myBlob, string name, ILogger log) { log.LogInformation("[PENDING] Connecting to blob storage..."); BlobStorage blobStorage = new BlobStorage(); log.LogInformation("[SUCCESS] Connected to blob storage"); string imageSourceURI = $"{Environment.GetEnvironmentVariable(ConfigSettings.STORAGE_DOMAIN_METADATA_NAME)}/{ConfigSettings.TO_SEPIA_CONTAINER_NAME}/{name}"; string jobId = Guid.NewGuid().ToString(); JobEntity initialJobEntity = JobEntity.New(jobId, ConversionModeNames.SEPIA, JobStatusCodes.IMAGE_OBTAINED, JobStatusMessages.IMAGE_OBTAINED, imageSourceURI, ""); log.LogInformation("[PENDING] Adding initial job entry to table..."); await Shared.UpdateJobTableWithStatus(log, initialJobEntity); log.LogInformation("[SUCCESS] Initial job entry added to table"); string convertedBlobName = $"{Guid.NewGuid()}-{name}"; try { log.LogInformation("[PENDING] Applying sepia filter to image..."); MemoryStream convertedMemoryStream = ImageConverter.ConvertImageToSepia(myBlob); log.LogInformation("[SUCCESS] Applied sepia filter to image"); JobEntity convertInProgressJobEntity = JobEntity.New(jobId, ConversionModeNames.SEPIA, JobStatusCodes.BEING_CONVERTED, JobStatusMessages.BEING_CONVERTED, imageSourceURI, ""); log.LogInformation("[PENDING] Updating job status to conversion-in-progress"); await Shared.UpdateJobTableWithStatus(log, convertInProgressJobEntity); log.LogInformation("[SUCCESS] Job status updated to conversion-in-progress"); log.LogInformation("[PENDING] Uploading converted image to converted images container..."); blobStorage.UploadConvertedImage(initialJobEntity, convertedBlobName, convertedMemoryStream); log.LogInformation("[SUCCESS] Converted image uploaded to converted images container"); } catch (Exception e) { log.LogError("An error occured while converting the image"); try { log.LogInformation("[PENDING} Uploading original image to failed container..."); blobStorage.UploadFailedImage(initialJobEntity, convertedBlobName, myBlob); log.LogInformation("[SUCCESS] Original image uploaded to failed container"); } catch (Exception ex) { log.LogError("Failed to upload image to failed container"); } } }
/// <summary> /// Replace the corresponding job entity with the /// given job entity /// </summary> /// <param name="jobEntity"></param> /// <returns></returns> public async Task <bool> UpdateJobEntity(JobEntity jobEntity) { TableOperation replaceOperation = TableOperation.Replace(jobEntity); TableResult result = await _table.ExecuteAsync(replaceOperation); if (result.HttpStatusCode > 199 && result.HttpStatusCode < 300) { return(true); } return(false); }
/// <summary> /// Uploads a given image to the failed images container /// /// The given image is expected to be the original source /// </summary> /// <param name="jobEntity"></param> /// <param name="blobName"></param> /// <param name="originalImage"></param> public async void UploadFailedImage(JobEntity jobEntity, string blobName, Stream originalImage) { CloudBlobContainer failedImagesContainer = _blobClient.GetContainerReference(ConfigSettings.FAILED_IMAGES_CONTAINER_NAME); CloudBlockBlob failedBlobBlock = failedImagesContainer.GetBlockBlobReference(blobName); failedBlobBlock.Metadata.Add(ConfigSettings.JOBID_METADATA_NAME, jobEntity.JobId); failedBlobBlock.Metadata.Add(ConfigSettings.IMAGE_CONVERSION_MODE_METADATA_NAME, jobEntity.ImageConversionMode); failedBlobBlock.Metadata.Add(ConfigSettings.IMAGE_SOURCE_METADATA_NAME, jobEntity.ImageSource); originalImage.Seek(0, SeekOrigin.Begin); await failedBlobBlock.UploadFromStreamAsync(originalImage); }
/// <summary> /// Updates the job entity status. /// </summary> /// <param name="jobId">The job identifier.</param> /// <param name="status">The status.</param> /// <param name="message">The message.</param> /// <param name="imageResult">The url string for the converted/failed image.</param> public async Task UpdateJobEntityStatus(string jobId, int status, string message, string imageResult) { JobEntity jobEntityToReplace = await RetrieveJobEntity(jobId); if (jobEntityToReplace != null) { jobEntityToReplace.status = status; jobEntityToReplace.statusDescription = message; jobEntityToReplace.imageResult = imageResult; await UpdateJobEntity(jobEntityToReplace); } }
/// <summary> /// Updates the status of a job entity /// </summary> /// <param name="jobId"></param> /// <param name="status"></param> /// <param name="message"></param> /// <returns></returns> public async Task UpdateJobEntityStatus(JobEntity jobEntity) { JobEntity jobEntityToReplace = await RetrieveJobEntity(jobEntity.JobId); if (jobEntityToReplace != null) { jobEntityToReplace.ImageConversionMode = jobEntity.ImageConversionMode; jobEntityToReplace.Status = jobEntity.Status; jobEntityToReplace.StatusDescription = jobEntity.StatusDescription; jobEntityToReplace.ImageSource = jobEntity.ImageSource; jobEntityToReplace.ImageResult = jobEntity.ImageResult; await UpdateJobEntity(jobEntityToReplace); } }
/// <summary> /// Inserts the or replace job entity. /// </summary> /// <param name="jobId">The job identifier.</param> /// <param name="status">The status.</param> /// <param name="message">The message.</param> /// <param name="imageSource">The url string for the uploaded image.</param> /// <param name="imageConversionMode">The type of conversion to be processed.</param> public async Task InsertOrReplaceJobEntity(string jobId, int status, string message, string imageSource, string imageConversionMode) { // Map parameters to JobEntity attributes JobEntity jobEntityToInsertOrReplace = new JobEntity(); jobEntityToInsertOrReplace.RowKey = jobId; jobEntityToInsertOrReplace.imageConversionMode = imageConversionMode; jobEntityToInsertOrReplace.status = status; jobEntityToInsertOrReplace.statusDescription = message; jobEntityToInsertOrReplace.imageSource = imageSource; jobEntityToInsertOrReplace.PartitionKey = _partitionKey; TableOperation insertReplaceOperation = TableOperation.InsertOrReplace(jobEntityToInsertOrReplace); TableResult result = await _table.ExecuteAsync(insertReplaceOperation); }
/// <summary> /// Upserts the given job entity /// </summary> /// <param name="jobEntity"></param> /// <returns></returns> public async Task InsertOrReplaceJobEntity(JobEntity jobEntity) { JobEntity jobEntityToInsertOrReplace = new JobEntity() { RowKey = jobEntity.JobId, ImageConversionMode = jobEntity.ImageConversionMode, Status = jobEntity.Status, StatusDescription = jobEntity.StatusDescription, ImageSource = jobEntity.ImageSource, ImageResult = jobEntity.ImageResult, PartitionKey = _partitionKey, }; TableOperation insertReplaceOperation = TableOperation.InsertOrReplace(jobEntityToInsertOrReplace); TableResult result = await _table.ExecuteAsync(insertReplaceOperation); }
public static async Task <IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = "jobs/{id}")] HttpRequest req, string id, ILogger log) { if (string.IsNullOrEmpty(id)) { return(new BadRequestObjectResult("The query string id is required")); } if (id.Length > 36) { return(new BadRequestObjectResult("An id cannot be greater than 36 characters")); } log.LogInformation("[PENDING] Connecting to jobs table..."); JobTable jobTable = new JobTable(log, ConfigSettings.IMAGEJOBS_PARTITIONKEY); log.LogInformation("[SUCCESS] Connected to Jobs Table"); log.LogInformation("[PENDING] Searching for Job Entity {id}..."); JobEntity jobEntity = await jobTable.RetrieveJobEntity(id); if (jobEntity == null) { log.LogError("Job Entity {id} was not found"); ErrorResponse errorResponse = ErrorResponse.New(ErrorResponseCodes.NOT_FOUND, "JobId", id, ErrorResponseMessages.NOT_FOUND); return(new NotFoundObjectResult(errorResponse)); } log.LogInformation("[SUCCESS] Job Entity {id} was found"); JobEntityResponse jobEntityResponse = JobEntityResponse.New( jobEntity.RowKey, jobEntity.ImageConversionMode, jobEntity.Status, jobEntity.StatusDescription, jobEntity.ImageSource, jobEntity.ImageResult); return(new OkObjectResult(jobEntityResponse)); }