Example #1
0
        public override async Task <string> EgressAsync(
            AzureBlobEgressProviderOptions options,
            Func <CancellationToken, Task <Stream> > action,
            EgressArtifactSettings artifactSettings,
            CancellationToken token)
        {
            try
            {
                var containerClient = await GetBlobContainerClientAsync(options, token);

                BlobClient blobClient = containerClient.GetBlobClient(GetBlobName(options, artifactSettings));

                Logger?.EgressProviderInvokeStreamAction(EgressProviderTypes.AzureBlobStorage);
                using var stream = await action(token);

                // Write blob content, headers, and metadata
                await blobClient.UploadAsync(stream, CreateHttpHeaders(artifactSettings), artifactSettings.Metadata, cancellationToken : token);

                string blobUriString = GetBlobUri(blobClient);
                Logger?.EgressProviderSavedStream(EgressProviderTypes.AzureBlobStorage, blobUriString);
                return(blobUriString);
            }
            catch (AggregateException ex) when(ex.InnerException is RequestFailedException innerException)
            {
                throw CreateException(innerException);
            }
            catch (RequestFailedException ex)
            {
                throw CreateException(ex);
            }
        }
Example #2
0
        private BlobHttpHeaders CreateHttpHeaders(EgressArtifactSettings artifactSettings)
        {
            BlobHttpHeaders headers = new BlobHttpHeaders();

            headers.ContentEncoding = artifactSettings.ContentEncoding;
            headers.ContentType     = artifactSettings.ContentType;
            return(headers);
        }
Example #3
0
 private string GetBlobName(AzureBlobEgressProviderOptions options, EgressArtifactSettings artifactSettings)
 {
     if (string.IsNullOrEmpty(options.BlobPrefix))
     {
         return(artifactSettings.Name);
     }
     else
     {
         return(string.Concat(options.BlobPrefix, "/", artifactSettings.Name));
     }
 }
Example #4
0
        public override async Task <string> EgressAsync(
            AzureBlobEgressProviderOptions options,
            Func <Stream, CancellationToken, Task> action,
            EgressArtifactSettings artifactSettings,
            CancellationToken token)
        {
            try
            {
                var containerClient = await GetBlobContainerClientAsync(options, token);

                BlockBlobClient blobClient = containerClient.GetBlockBlobClient(GetBlobName(options, artifactSettings));

                // Write blob content

                var bloboptions = new BlockBlobOpenWriteOptions
                {
                    BufferSize = BlobStorageBufferSize,
                };
                using (Stream blobStream = await blobClient.OpenWriteAsync(overwrite: true, options: bloboptions, cancellationToken: token))
                    using (AutoFlushStream flushStream = new AutoFlushStream(blobStream, BlobStorageBufferSize))
                    {
                        //Azure's stream from OpenWriteAsync will do the following
                        //1. Write the data to a local buffer
                        //2. Once that buffer is full, stage the data remotely (this data is not considered valid yet)
                        //3. After 4Gi of data has been staged, the data will be commited. This can be forced earlier by flushing
                        //the stream.
                        // Since we want the data to be readily available, we automatically flush (and therefore commit) every time we fill up the buffer.
                        Logger?.EgressProviderInvokeStreamAction(EgressProviderTypes.AzureBlobStorage);
                        await action(flushStream, token);

                        await flushStream.FlushAsync(token);
                    }

                // Write blob headers
                await blobClient.SetHttpHeadersAsync(CreateHttpHeaders(artifactSettings), cancellationToken : token);

                // Write blob metadata
                await blobClient.SetMetadataAsync(artifactSettings.Metadata, cancellationToken : token);

                string blobUriString = GetBlobUri(blobClient);
                Logger?.EgressProviderSavedStream(EgressProviderTypes.AzureBlobStorage, blobUriString);
                return(blobUriString);
            }
            catch (AggregateException ex) when(ex.InnerException is RequestFailedException innerException)
            {
                throw CreateException(innerException);
            }
            catch (RequestFailedException ex)
            {
                throw CreateException(ex);
            }
        }
Example #5
0
        public override async Task <string> EgressAsync(
            FileSystemEgressProviderOptions options,
            Func <Stream, CancellationToken, Task> action,
            EgressArtifactSettings artifactSettings,
            CancellationToken token)
        {
            if (!Directory.Exists(options.DirectoryPath))
            {
                WrapException(() => Directory.CreateDirectory(options.DirectoryPath));
            }

            string targetPath = Path.Combine(options.DirectoryPath, artifactSettings.Name);

            if (!string.IsNullOrEmpty(options.IntermediateDirectoryPath))
            {
                if (!Directory.Exists(options.IntermediateDirectoryPath))
                {
                    WrapException(() => Directory.CreateDirectory(options.IntermediateDirectoryPath));
                }

                string intermediateFilePath = null;
                try
                {
                    int  remainingAttempts = 10;
                    bool intermediatePathExists;
                    do
                    {
                        intermediateFilePath   = Path.Combine(options.IntermediateDirectoryPath, Path.GetRandomFileName());
                        intermediatePathExists = File.Exists(intermediateFilePath);
                        remainingAttempts--;
                    }while (intermediatePathExists && remainingAttempts > 0);

                    if (intermediatePathExists)
                    {
                        throw CreateException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorMessage_EgressUnableToCreateIntermediateFile, options.IntermediateDirectoryPath));
                    }

                    await WriteFileAsync(action, intermediateFilePath, token);

                    WrapException(() => File.Move(intermediateFilePath, targetPath));
                }
                finally
                {
                    // Attempt to delete the intermediate file if it exists.
                    try
                    {
                        if (File.Exists(intermediateFilePath))
                        {
                            File.Delete(intermediateFilePath);
                        }
                    }
                    catch (Exception)
                    {
                    }
                }
            }
            else
            {
                await WriteFileAsync(action, targetPath, token);
            }

            Logger?.EgressProviderSavedStream(EgressProviderTypes.FileSystem, targetPath);
            return(targetPath);
        }