public async Task <Uri> UploadFile(WorkQueue queue, AbsolutePath path, Action <string, Percent> progressFn) { var definition = await GenerateFileDefinition(queue, path, progressFn); using (var result = await _client.PutAsync($"{Consts.WabbajackBuildServerUri}authored_files/create", new StringContent(definition.ToJson()))) { progressFn("Starting upload", Percent.Zero); definition.ServerAssignedUniqueId = await result.Content.ReadAsStringAsync(); } var results = await definition.Parts.PMap(queue, async part => { progressFn("Uploading Part", Percent.FactoryPutInRange(part.Index, definition.Parts.Length)); var buffer = new byte[part.Size]; await using (var fs = await path.OpenShared()) { fs.Position = part.Offset; await fs.ReadAsync(buffer); } int retries = 0; while (true) { try { using var putResult = await _client.PutAsync( $"{Consts.WabbajackBuildServerUri}authored_files/{definition.ServerAssignedUniqueId}/part/{part.Index}", new ByteArrayContent(buffer)); var hash = Hash.FromBase64(await putResult.Content.ReadAsStringAsync()); if (hash != part.Hash) { throw new InvalidDataException("Hashes don't match"); } return(hash); } catch (Exception ex) { Utils.Log("Failure uploading part"); Utils.Log(ex.ToString()); if (retries <= 4) { retries++; continue; } Utils.ErrorThrow(ex); } } }); progressFn("Finalizing upload", Percent.Zero); using (var result = await _client.PutAsync($"{Consts.WabbajackBuildServerUri}authored_files/{definition.ServerAssignedUniqueId}/finish", new StringContent(definition.ToJson()))) { progressFn("Finished", Percent.One); return(new Uri(await result.Content.ReadAsStringAsync())); } }
public async Task <Uri> UploadFile(WorkQueue queue, AbsolutePath path, Action <string, Percent> progressFn) { var definition = await GenerateFileDefinition(queue, path, progressFn); await CircuitBreaker.WithAutoRetryAllAsync(async() => { using var result = await _client.PutAsync($"{Consts.WabbajackBuildServerUri}authored_files/create", new StringContent(definition.ToJson())); progressFn("Starting upload", Percent.Zero); definition.ServerAssignedUniqueId = await result.Content.ReadAsStringAsync(); }); var results = await definition.Parts.PMap(queue, async part => { progressFn("Uploading Part", Percent.FactoryPutInRange(part.Index, definition.Parts.Length)); var buffer = new byte[part.Size]; await using (var fs = await path.OpenShared()) { fs.Position = part.Offset; await fs.ReadAsync(buffer); } return(await CircuitBreaker.WithAutoRetryAllAsync(async() => { using var putResult = await _client.PutAsync( $"{Consts.WabbajackBuildServerUri}authored_files/{definition.ServerAssignedUniqueId}/part/{part.Index}", new ByteArrayContent(buffer)); var hash = Hash.FromBase64(await putResult.Content.ReadAsStringAsync()); if (hash != part.Hash) { throw new InvalidDataException("Hashes don't match"); } return hash; })); }); progressFn("Finalizing upload", Percent.Zero); return(await CircuitBreaker.WithAutoRetryAllAsync(async() => { using var result = await _client.PutAsync( $"{Consts.WabbajackBuildServerUri}authored_files/{definition.ServerAssignedUniqueId}/finish", new StringContent(definition.ToJson())); progressFn("Finished", Percent.One); return new Uri(await result.Content.ReadAsStringAsync()); })); }