private async Task DownloadItemImplAsync( SemaphoreSlim downloadThrottle, ContainerItem ticketedItem, string downloadPath, CancellationToken cancellationToken) { try { await downloadThrottle.WaitAsync().ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) { return; } // Download the file content to a temp file on the same drive. // Assumption: the build won't produce files ending in .download. string tmpDownloadPath = downloadPath + ".download"; FileSystemManager.EnsureParentDirectory(tmpDownloadPath); FileSystemManager.DeleteFile(downloadPath); await GetFileAsync(ticketedItem, tmpDownloadPath, cancellationToken).ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) { return; } // With the content successfully downloaded, move the tmp file to its permanent location. FileSystemManager.MoveFile(tmpDownloadPath, downloadPath); } finally { downloadThrottle.Release(); } }
// Wraps our use of the proxy client library private async Task GetFileAsync(ContainerItem ticketedItem, string tmpDownloadPath, CancellationToken cancellationToken) { // Will get doubled on each attempt. TimeSpan timeBetweenRetries = ContainerFetchEngineOptions.RetryInterval; for (int triesRemaining = ContainerFetchEngineOptions.RetryLimit; ; triesRemaining--) { bool lastAttempt = (triesRemaining == 0); timeBetweenRetries += timeBetweenRetries; // Delete the tmp file inbetween attempts FileSystemManager.DeleteFile(tmpDownloadPath); try { Task <Stream> getFileTask = Provider.GetFileTask(ticketedItem, cancellationToken); Task timeoutTask = Task.Delay(ContainerFetchEngineOptions.GetFileAsyncTimeout, cancellationToken); ExecutionLogger.Debug(StringUtil.Format("Fetching contents of file {0}", tmpDownloadPath)); // Wait for GetFileAsync or the timeout to elapse. await Task.WhenAny(getFileTask, timeoutTask).ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) { return; } if (!getFileTask.IsCompleted) { throw new TimeoutException(StringUtil.Loc("RMGetFileAsyncTimedOut", GetFileAsyncTimeoutMinutes)); } ExecutionLogger.Debug(StringUtil.Format("Writing contents of file {0} to disk", tmpDownloadPath)); using (Stream stream = await getFileTask.ConfigureAwait(false)) { await FileSystemManager.WriteStreamToFile(stream, tmpDownloadPath, ContainerFetchEngineOptions.DownloadBufferSize, cancellationToken); } ExecutionLogger.Debug(StringUtil.Format("Finished writing contents of file {0} to disk", tmpDownloadPath)); break; } catch (Exception exception) { if (exception is AggregateException) { exception = ((AggregateException)exception).Flatten().InnerException; } if (lastAttempt) { throw new Exception(StringUtil.Loc("RMErrorDownloadingContainerItem", tmpDownloadPath, exception)); } lock (_lock) { ExecutionLogger.Warning(StringUtil.Loc("RMReAttemptingDownloadOfContainerItem", tmpDownloadPath, exception)); } } // "Sleep" in between attempts. (Can't await inside a catch clause.) await Task.Delay(timeBetweenRetries); } }
private Task DownloadItemAsync(SemaphoreSlim downloadThrottle, ContainerItem ticketedItem) { string downloadPath = ConvertToLocalPath(ticketedItem); return(DownloadItemImplAsync(downloadThrottle, ticketedItem, downloadPath)); }