Esempio n. 1
0
        public async Task <Stream> GetFileTask(ContainerItem ticketedItem, CancellationToken cancellationToken)
        {
            ArgUtil.NotNull(ticketedItem, nameof(ticketedItem));

            this._executionContext.Debug(StringUtil.Format("Get file container client for file {0}", ticketedItem.Path));

            VssConnection vssConnection = await GetVssConnection();

            FileContainerHttpClient fileContainer = null;

            try
            {
                fileContainer = vssConnection.GetClient <FileContainerHttpClient>();
            }
            catch (SocketException e)
            {
                ExceptionsUtil.HandleSocketException(e, vssConnection.Uri.ToString(), this._executionContext.Error);
                throw;
            }

            this._executionContext.Debug(StringUtil.Format("Start fetch file stream from filecontainer service for file {0}", ticketedItem.Path));

            Stream stream = await fileContainer.DownloadFileAsync(
                ticketedItem.ContainerId,
                ticketedItem.Path,
                cancellationToken,
                scopeIdentifier : ticketedItem.ScopeIdentifier);

            this._executionContext.Debug(StringUtil.Format("Finished fetch file stream from filecontainer service for file {0}", ticketedItem.Path));

            return(stream);
        }
        private async Task <DownloadResult> DownloadAsync(RunnerActionPluginExecutionContext context, int downloaderId, CancellationToken token)
        {
            List <DownloadInfo> failedFiles   = new List <DownloadInfo>();
            Stopwatch           downloadTimer = new Stopwatch();

            while (_fileDownloadQueue.TryDequeue(out DownloadInfo fileToDownload))
            {
                token.ThrowIfCancellationRequested();
                try
                {
                    int  retryCount     = 0;
                    bool downloadFailed = false;
                    while (true)
                    {
                        try
                        {
                            context.Debug($"Start downloading file: '{fileToDownload.ItemPath}' (Downloader {downloaderId})");
                            downloadTimer.Restart();
                            using (FileStream fs = new FileStream(fileToDownload.LocalPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: _defaultFileStreamBufferSize, useAsync: true))
                                using (var downloadStream = await _fileContainerHttpClient.DownloadFileAsync(_containerId, fileToDownload.ItemPath, token, _projectId))
                                {
                                    await downloadStream.CopyToAsync(fs, _defaultCopyBufferSize, token);

                                    await fs.FlushAsync(token);

                                    downloadTimer.Stop();
                                    context.Debug($"File: '{fileToDownload.LocalPath}' took {downloadTimer.ElapsedMilliseconds} milliseconds to finish download (Downloader {downloaderId})");
                                    break;
                                }
                        }
                        catch (OperationCanceledException) when(token.IsCancellationRequested)
                        {
                            context.Debug($"Download has been cancelled while downloading {fileToDownload.ItemPath}. (Downloader {downloaderId})");
                            throw;
                        }
                        catch (Exception ex)
                        {
                            retryCount++;
                            context.Warning($"Fail to download '{fileToDownload.ItemPath}', error: {ex.Message} (Downloader {downloaderId})");
                            context.Debug(ex.ToString());
                        }

                        if (retryCount < 3)
                        {
                            var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30));
                            context.Warning($"Back off {backOff.TotalSeconds} seconds before retry. (Downloader {downloaderId})");
                            await Task.Delay(backOff);
                        }
                        else
                        {
                            // upload still failed after 3 tries.
                            downloadFailed = true;
                            break;
                        }
                    }

                    if (downloadFailed)
                    {
                        // tracking file that failed to download.
                        failedFiles.Add(fileToDownload);
                    }

                    Interlocked.Increment(ref _downloadFilesProcessed);
                }
                catch (Exception ex)
                {
                    // We should never
                    context.Error($"Error '{ex.Message}' when downloading file '{fileToDownload}'. (Downloader {downloaderId})");
                    throw;
                }
            }

            return(new DownloadResult(failedFiles));
        }