/// <inheritdoc/> public async Task <bool> SetBlobMetadataAsync(Uri blobUri, IDictionary <string, string> metadata, StorageClientProviderContext context) { _ = blobUri ?? throw new ArgumentNullException(nameof(blobUri)); _ = context ?? throw new ArgumentNullException(nameof(context)); if (metadata is null || metadata.Count == 0) { throw new ArgumentNullException(nameof(metadata)); } bool exists = await GetBlobExistsAsync(blobUri, context).ConfigureAwait(false); if (!exists) { _log.LogEventObject(LogEventIds.StorageServiceAttemptToAddMetadataToBlobThatDoesNotExist, blobUri); throw new GridwichStorageServiceException(blobUri, "The operation failed because the requested blob does not exist.", LogEventIds.StorageServiceAttemptToAddMetadataToBlobThatDoesNotExist, context.ClientRequestIdAsJObject); } IStorageBlobClientSleeve blobSleeve = _blobBaseClientProvider.GetBlobClientSleeveForUri(blobUri, context); try { await blobSleeve.Client.SetMetadataAsync(metadata).ConfigureAwait(false); return(true); } catch (Exception e) { _log.LogExceptionObject(LogEventIds.FailedToSetMetadataInStorageService, e, blobUri); throw new GridwichStorageServiceException(blobUri, "Could not set the metadata of the blob.", LogEventIds.FailedToSetMetadataInStorageService, context.ClientRequestIdAsJObject, e); } }
/// <inheritdoc/> public async Task <bool> BlobDelete(Uri blobUri, StorageClientProviderContext context) { _ = blobUri ?? throw new ArgumentNullException(nameof(blobUri)); _ = context ?? throw new ArgumentNullException(nameof(context)); // 0. Get the SDK storage client IStorageBlobClientSleeve blobSleeve = _blobBaseClientProvider.GetBlobClientSleeveForUri(blobUri, context); Response <bool> resp; try { // 1. Get a SAS for the blob string sasUri = GetSasUrlForBlob(blobUri, new TimeSpan(0, 5, 0), context); // 2. Request the deletion // From the SDK source (see below), there are 3 possible responses: // 1. true -- blob existed and was deleted from index. // 2. false -- blob did not exist // 3a. RequestFailedException -- some storage problem, other than the blob not existing. // 3b. Some other exception -- unlikely but possible. // Azure SDK Source for Delete: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs // DeleteBlob REST Call: https://docs.microsoft.com/en-us/rest/api/storageservices/delete-blob resp = await blobSleeve.Client.DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots, null).ConfigureAwait(false); } catch (Exception e) { // something other than an expected Storage problem. _log.LogExceptionObject(LogEventIds.FailedToDeleteDueToStorageExceptionInStorageService, e, blobUri); throw new GridwichStorageServiceException(blobUri, "Failed to delete the blob.", LogEventIds.FailedToDeleteDueToStorageExceptionInStorageService, context.ClientRequestIdAsJObject, e); } return(resp); }
/// <inheritdoc/> public async Task <bool> ChangeBlobTierAsync(Uri blobUri, BlobAccessTier accessTier, BlobRehydratePriority rehydratePriority, StorageClientProviderContext context) { _ = blobUri ?? throw new ArgumentNullException(nameof(blobUri)); _ = accessTier ?? throw new ArgumentNullException(nameof(accessTier)); _ = context ?? throw new ArgumentNullException(nameof(context)); IStorageBlobClientSleeve blobSleeve = _blobBaseClientProvider.GetBlobClientSleeveForUri(blobUri, context); Response response; try { response = await blobSleeve.Client.SetAccessTierAsync(accessTier.ToAzureEnum(), null, rehydratePriority.ToAzureEnum()).ConfigureAwait(false); } catch (Exception e) { _log.LogExceptionObject(LogEventIds.FailedToChangeTierInStorageService, e, blobUri); throw new GridwichStorageServiceException(blobUri, "Could not change tier of the blob.", LogEventIds.FailedToChangeTierInStorageService, context.ClientRequestIdAsJObject, e); } if (response.Status == 200) { return(true); } _log.LogEventObject(LogEventIds.ChangeBlobTierUnexpectedResponse, new { blobUri, response }); throw new GridwichStorageServiceException(blobUri, $"Unexpected response when changing the blob's tier: {response}", LogEventIds.ChangeBlobTierUnexpectedResponse, context.ClientRequestIdAsJObject); }
/// <inheritdoc/> public async Task <bool> GetBlobExistsAsync(Uri blobUri, StorageClientProviderContext context) { _ = blobUri ?? throw new ArgumentNullException(nameof(blobUri)); _ = context ?? throw new ArgumentNullException(nameof(context)); IStorageBlobClientSleeve blobSleeve = _blobBaseClientProvider.GetBlobClientSleeveForUri(blobUri, context); try { return(await blobSleeve.Client.ExistsAsync().ConfigureAwait(false)); } catch (Exception e) { _log.LogExceptionObject(LogEventIds.FailedToCheckBlobExistenceDueToStorageExceptionInStorageService, e, blobUri); throw new GridwichStorageServiceException(blobUri, "The operation failed because the requested blob does not exist.", LogEventIds.FailedToCheckBlobExistenceDueToStorageExceptionInStorageService, context.ClientRequestIdAsJObject, e); } }
/// <inheritdoc/> public async Task <CopyFromUriOperation> BlobCopy(Uri sourceUri, Uri destinationUri, StorageClientProviderContext context) { _ = sourceUri ?? throw new ArgumentNullException(nameof(sourceUri)); _ = destinationUri ?? throw new ArgumentNullException(nameof(destinationUri)); _ = context ?? throw new ArgumentNullException(nameof(context)); IStorageBlobClientSleeve destinationBlobBaseClient = _blobBaseClientProvider.GetBlobClientSleeveForUri(destinationUri, context); var containerSleeve = _blobContainerClientProvider.GetBlobContainerSleeveForUri(destinationUri, context); // 0. Create Container if missing try { await containerSleeve.Client.CreateIfNotExistsAsync().ConfigureAwait(false); } catch (Exception e) { _log.LogExceptionObject(LogEventIds.StorageServiceFailedCreatingTargetContainerForBlobCopy, e, destinationUri); throw new GridwichStorageServiceException(destinationUri, "Could not create the destination container.", LogEventIds.StorageServiceFailedCreatingTargetContainerForBlobCopy, context.ClientRequestIdAsJObject, e); } CopyFromUriOperation blobCopyInfo; try { // 1. Get SAS for Source string sasUri = GetSasUrlForBlob(sourceUri, _blobCopyTimeout, context); // 2. Copy Async to Dest blobCopyInfo = await destinationBlobBaseClient.Client.StartCopyFromUriAsync(new Uri(sasUri)).ConfigureAwait(false); } catch (Exception e) { _log.LogExceptionObject(LogEventIds.FailedToCopyBlobInStorageService, e, sourceUri); throw new GridwichStorageServiceException(sourceUri, $"Could not copy blob from {sourceUri} to {destinationUri}.", LogEventIds.FailedToCopyBlobInStorageService, context.ClientRequestIdAsJObject, e); } return(blobCopyInfo); }
/// <inheritdoc/> public async Task <BlobProperties> GetBlobPropertiesAsync(Uri blobUri, StorageClientProviderContext context) { _ = blobUri ?? throw new ArgumentNullException(nameof(blobUri)); _ = context ?? throw new ArgumentNullException(nameof(context)); IStorageBlobClientSleeve blobSleeve = _blobBaseClientProvider.GetBlobClientSleeveForUri(blobUri, context); BlobProperties blobProperties; try { blobProperties = await blobSleeve.Client.GetPropertiesAsync().ConfigureAwait(false); } catch (Exception e) { _log.LogExceptionObject(LogEventIds.FailedToGetBlobPropertiesInStorageService, e, blobUri); throw new GridwichStorageServiceException(blobUri, "Could not get the blob's properties.", LogEventIds.FailedToGetBlobPropertiesInStorageService, context.ClientRequestIdAsJObject, e); } return(blobProperties); }
/// <inheritdoc/> public async Task <BlobDownloadInfo> DownloadHttpRangeAsync(Uri blobUri, StorageClientProviderContext context, HttpRange httpRange = default) { _ = blobUri ?? throw new ArgumentNullException(nameof(blobUri)); _ = context ?? throw new ArgumentNullException(nameof(context)); // Note: when the httpRange struct is omitted it defaults to 'default' which downloads the entire blob. IStorageBlobClientSleeve blobBaseClient = _blobBaseClientProvider.GetBlobClientSleeveForUri(blobUri, context); BlobDownloadInfo blobDownloadInfo; try { blobDownloadInfo = (await blobBaseClient.Client.DownloadAsync(httpRange).ConfigureAwait(false)).Value; } catch (Exception e) { _log.LogExceptionObject(LogEventIds.FailedToDownloadHttpRangeInStorageService, e, blobUri); throw new GridwichStorageServiceException(blobUri, "Could not download the HTTP range for a blob.", LogEventIds.FailedToDownloadHttpRangeInStorageService, context.ClientRequestIdAsJObject, e); } return(blobDownloadInfo); }