Example #1
0
        /// <summary>
        /// Bumps, or signals creation/completion/status update request, based on the stream's current state.
        /// </summary>
        /// <param name="streamStatus">Stream status with the source data filled in with info on the stream being signaled</param>
        /// <param name="cancellationToken">Used to cancel the operation</param>
        /// <returns>Stream status with target details filled in.</returns>
        /// <remarks>
        /// A returned value with equivalent target and sources hashes and a segment length equal to the full data length,
        /// then a completion signal was sent. In this case, <see cref="OnUploadCompleted( string,string)"/> will have been called.
        /// Otherwise, data uploading may begin/proceed if the caller has enough info, or the caller may bump again with a more
        /// targeted segment length.
        /// </remarks>
        public async Task <StreamStatus> BumpAsync(StreamStatus streamStatus, CancellationToken cancellationToken = default)
        {
            try
            {
                using (var client = new snh.HttpClient())
                {
                    var response = await client.PatchWithAuthenticationAsync(
                        $"{this.Config.BaseControllerPath}{this.DataSinkControllerPath}",
                        streamStatus.ToJson(),
                        this.AuthenticationHeaderGenerator,
                        this.Logger,
                        cancellationToken).ConfigureAwait(false);

                    if (!response.IsSuccessStatusCode)
                    {
                        throw new DataSinkHttpClientException("Unsuccessful service call response")
                              {
                                  ErrorResponse = response
                              };
                    }
                    using (var streamReader = new StreamReader(await response.Content.ReadAsStreamAsync().ConfigureAwait(false)))
                        using (var jsonTextReader = new JsonTextReader(streamReader))
                        {
                            cancellationToken.ThrowIfCancellationRequested();
                            return(new JsonSerializer().Deserialize <StreamStatus>(jsonTextReader));
                        }
                }
            }
            catch (Exception ex)
            {
                this.Logger?.LogError(ex, "Failure to BumpAsync");
                throw;
            }
        }
Example #2
0
        /// <summary>
        /// Accepts a stream representing the remaining amount of data to upload to continue a detected incomplete upload. Calls <see cref="OnUploadCompleted( string,string)"/> on success.
        /// </summary>
        /// <param name="id">Identifier for the upload. Must be unique for an authenticated user within the timeframe of the upload.</param>
        /// <param name="stream"><see cref="Stream"/> for accessing the remaining data. The first byte in the stream will be written at <paramref name="startAt"/>, and the rest will be written in order.</param>
        /// <param name="startAt">Position within the target data where writing should start.</param>
        /// <param name="length">If provided, the given number of bytes will be streamed. Defaults to <c>null</c>, meaning that all bytes will be streamed. Either way, the completion action will be invoked only if the last expected data byte is sent (based on expected data length). If given for a partial data upload, then the service can significantly reduce memory usage.</param>
        /// <param name="cancellationToken">Used to cancel the operation</param>
        public async Task SendDataAsync(string id, Stream stream, long startAt = 0, long?length = default, CancellationToken cancellationToken = default)
        {
            try
            {
                using (var client = new snh.HttpClient())
                {
                    client.Timeout = Timeout.InfiniteTimeSpan;

                    string requestUri;
                    if (length.HasValue)
                    {
                        requestUri = $"{this.Config.BaseControllerPath}{this.DataSinkControllerPath}/{id}/{startAt}/{length.Value}";
                    }
                    else if (startAt > 0)
                    {
                        requestUri = $"{this.Config.BaseControllerPath}{this.DataSinkControllerPath}/{id}/{startAt}";
                    }
                    else
                    {
                        requestUri = $"{this.Config.BaseControllerPath}{this.DataSinkControllerPath}/{id}";
                    }


                    var response = await client.PatchWithAuthenticationAsync(
                        requestUri,
                        stream,
                        "application/octet-stream",
                        this.IOBufferSize,
                        this.AuthenticationHeaderGenerator,
                        this.Logger,
                        cancellationToken).ConfigureAwait(false);

                    EnsureSuccessfulDataTransfer(response);
                }
            }
            catch (Exception ex)
            {
                this.Logger?.LogError(ex, "Failure to SendDataAsync");
                throw;
            }
        }