protected async Task <T> ExecuteQueryAsync <T>(string uri, Func <HttpResponseMessage, Task <T> > handler)
        {
            Polly.Retry.AsyncRetryPolicy <HttpResponseMessage> httpRetryPolicy = Policy
                                                                                 .HandleResult <HttpResponseMessage>(r => r.StatusCode == (HttpStatusCode)429)
                                                                                 .WaitAndRetryAsync(new[]
            {
                TimeSpan.FromSeconds(30),
                TimeSpan.FromSeconds(60),
                TimeSpan.FromSeconds(90)
            },
                                                                                                    onRetry: (outcome, timespan, retryAttempt, context) =>
            {
                //included for debug to see what the response is
            });

            var response = await httpRetryPolicy.ExecuteAndCaptureAsync(() => _httpClient.GetAsync(uri));

            if (response.Outcome == OutcomeType.Successful)
            {
                if (response.Result.IsSuccessStatusCode)
                {
                    return(await handler(response.Result));
                }

                throw new HttpRequestException($"There was an error while executing the HTTP query. Reason: {response.Result.ReasonPhrase}");
            }
            else
            {
                var reason = response.FinalHandledResult != null ? response.FinalHandledResult.ReasonPhrase : response.FinalException.Message;
                throw new HttpRequestException($"There was an error while executing the HTTP query. Reason: {reason}");
            }
        }
Пример #2
0
        private static IAsyncPolicy<HttpResponseMessage> GetFinalPolicy(Polly.Retry.AsyncRetryPolicy<HttpResponseMessage> retryPolicy, Func<HttpResponseMessage, Task<bool>> onResultFuncAsync = null)
        {
            if (onResultFuncAsync == null)
            {
                return retryPolicy;
            }

            var fallbackPolicy = BuildFallbackPolicy(onResultFuncAsync);
            return retryPolicy.WrapAsync(fallbackPolicy);
        }
Пример #3
0
        public override async Task RetrieveResources(SessionHostsStartInfo sessionHostsStartInfo)
        {
            string registryWithImageName = $"{sessionHostsStartInfo.ImageDetails.Registry}/{sessionHostsStartInfo.ImageDetails.ImageName}";
            string imageTag = sessionHostsStartInfo.ImageDetails.ImageTag;
            string username = sessionHostsStartInfo.ImageDetails.Username;
            string password = sessionHostsStartInfo.ImageDetails.Password;

            if (string.IsNullOrEmpty(imageTag))
            {
                imageTag = "latest";
            }

            _logger.LogInformation($"Starting image pull for: {registryWithImageName}:{imageTag}.");
            LogReporter logReporter = new LogReporter(_logger);

            Polly.Retry.AsyncRetryPolicy retryPolicy = Policy
                                                       .Handle <Exception>((Exception e) =>
            {
                _logger.LogError($"Exception encountered when creating image: {e.ToString()}");
                return(true);
            })
                                                       .WaitAndRetryAsync(_maxRetryAttempts, i => TimeSpan.FromMinutes(_createImageRetryTimeMins / _maxRetryAttempts));

            await retryPolicy.ExecuteAsync(async() =>
            {
                await _dockerClient.Images.CreateImageAsync(
                    new ImagesCreateParameters {
                    FromImage = registryWithImageName, Tag = imageTag
                },
                    new AuthConfig()
                {
                    Username = username, Password = password
                },
                    logReporter);

                // Making sure that the image was actually downloaded properly
                // We have seen some cases where Docker Registry API returns 'success' on pull while the image has not been properly downloaded
                IEnumerable <ImagesListResponse> images = await _dockerClient.Images.ListImagesAsync(new ImagesListParameters {
                    All = true
                });
                if (images.All(image => !image.RepoTags.Contains($"{registryWithImageName}:{imageTag}")))
                {
                    throw new ApplicationException("CreateImageAsync is completed but the image doesn't exist");
                }
            });

            _logger.LogEvent(MetricConstants.PullImage, null, new Dictionary <string, double>
            {
                { MetricConstants.DownloadDurationInMilliseconds, logReporter.DownloadSummary?.DurationInMilliseconds ?? 0d },
                { MetricConstants.ExtractDurationInMilliseconds, logReporter.ExtractionSummary?.DurationInMilliseconds ?? 0d },
                { MetricConstants.SizeInBytes, logReporter.DownloadSummary?.TotalSizeInBytes ?? 0d }
            }
                             );
        }
Пример #4
0
        public static async Task <HttpResponseMessage> CheckConnection(string uri)
        {
            Polly.Retry.AsyncRetryPolicy retryPolly = Policy
                                                      .Handle <HttpRequestException>()
                                                      .WaitAndRetryAsync(MaxTry, i => TimeSpan.FromSeconds(Seconds));

            var client   = new HttpClient();
            var response = await retryPolly
                           .ExecuteAsync(() => client.GetAsync(uri));

            return(response);
        }
Пример #5
0
        public static IAsyncPolicy <HttpResponseMessage> Retry(int retryAttempts)
        {
            Polly.Retry.AsyncRetryPolicy <HttpResponseMessage> retryPolicy = HttpPolicyExtensions
                                                                             .HandleTransientHttpError()
                                                                             .OrResult(msg => msg.StatusCode == HttpStatusCode.NotFound)
                                                                             .WaitAndRetryAsync(retryAttempts, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

            Polly.Fallback.AsyncFallbackPolicy <HttpResponseMessage> fallbackPolicy = HttpPolicyExtensions.HandleTransientHttpError().FallbackAsync(fallbackAction: (result, context, token) => Task.FromResult(new HttpResponseMessage(HttpStatusCode.RequestTimeout)
            {
                Content = new StringContent(result.Exception.Message)
            }),
                                                                                                                                                    (result, context) => Task.CompletedTask);

            return(Policy.WrapAsync(retryPolicy, fallbackPolicy));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="HttpClientHelper"/> class.
        /// </summary>
        /// <param name="jobSettings">Job settings</param>
        /// <param name="retryPolicy">Retry policy</param>
        public HttpClientHelper(Settings jobSettings, Polly.Retry.AsyncRetryPolicy retryPolicy)
        {
            _settings    = jobSettings;
            _retryPolicy = retryPolicy;

            //Use Tls1.2 as default transport layer
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            var httpClientHandler = new HttpClientHandler {
                AllowAutoRedirect      = false,
                UseCookies             = false,
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
            };

            _httpClient = new HttpClient(httpClientHandler)
            {
                Timeout = TimeSpan.FromMinutes(60) //Timeout for large uploads or downloads
            };

            _authenticationHelper = new AuthenticationHelper(_settings, _retryPolicy);
        }
        /// <summary>
        /// Called by the <see cref="T:Quartz.IScheduler" /> when a <see cref="T:Quartz.ITrigger" />
        /// fires that is associated with the <see cref="T:Quartz.IJob" />.
        /// </summary>
        /// <param name="context">The execution context.</param>
        /// <exception cref="JobExecutionException">false</exception>
        /// <remarks>
        /// The implementation may wish to set a  result object on the
        /// JobExecutionContext before this method exits.  The result itself
        /// is meaningless to Quartz, but may be informative to
        /// <see cref="T:Quartz.IJobListener" />s or
        /// <see cref="T:Quartz.ITriggerListener" />s that are watching the job's
        /// execution.
        /// </remarks>
        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                log4net.Config.XmlConfigurator.Configure();
                _context = context;
                _settings.Initialize(context);

                if (_settings.IndefinitePause)
                {
                    await context.Scheduler.PauseJob(context.JobDetail.Key);

                    Log.InfoFormat(CultureInfo.InvariantCulture,
                                   string.Format(Resources.Job_0_was_paused_indefinitely, _context.JobDetail.Key));
                    return;
                }

                _retryPolicyForIo = Policy.Handle <IOException>().WaitAndRetry(
                    retryCount: _settings.RetryCount,
                    sleepDurationProvider: attempt => TimeSpan.FromSeconds(_settings.RetryDelay),
                    onRetry: (exception, calculatedWaitDuration) =>
                {
                    Log.WarnFormat(CultureInfo.InvariantCulture, string.Format(Resources.Job_0_Retrying_IO_operation_Exception_1, _context.JobDetail.Key, exception.Message));
                });
                _retryPolicyForHttp = Policy.Handle <HttpRequestException>().WaitAndRetryAsync(
                    retryCount: _settings.RetryCount,
                    sleepDurationProvider: attempt => TimeSpan.FromSeconds(_settings.RetryDelay),
                    onRetry: (exception, calculatedWaitDuration) =>
                {
                    Log.WarnFormat(CultureInfo.InvariantCulture, string.Format(Resources.Job_0_Retrying_Http_operation_Exception_1, _context.JobDetail.Key, exception.Message));
                });

                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat(CultureInfo.InvariantCulture, string.Format(Resources.Job_0_starting, _context.JobDetail.Key));
                }

                await Process();

                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat(CultureInfo.InvariantCulture, string.Format(Resources.Job_0_ended, _context.JobDetail.Key));
                }
            }
            catch (Exception ex)
            {
                if (_settings.PauseJobOnException)
                {
                    await context.Scheduler.PauseJob(context.JobDetail.Key);

                    Log.WarnFormat(CultureInfo.InvariantCulture,
                                   string.Format(Resources.Job_0_was_paused_because_of_error, _context.JobDetail.Key));
                }
                if (Log.IsDebugEnabled)
                {
                    if (!string.IsNullOrEmpty(ex.Message))
                    {
                        Log.Error(ex.Message, ex);
                    }
                    else
                    {
                        Log.Error("Uknown exception", ex);
                    }

                    while (ex.InnerException != null)
                    {
                        if (!string.IsNullOrEmpty(ex.InnerException.Message))
                        {
                            Log.Error(ex.InnerException.Message, ex.InnerException);
                        }

                        ex = ex.InnerException;
                    }
                }
                if (context.Scheduler.SchedulerName != "Private")
                {
                    throw new JobExecutionException(string.Format(Resources.Upload_job_0_failed, _context.JobDetail.Key), ex, false);
                }

                if (!Log.IsDebugEnabled)
                {
                    Log.Error(string.Format(Resources.Job_0_thrown_an_error_1, _context.JobDetail.Key, ex.Message));
                }
            }
        }
Пример #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="AuthenticationHelper"/> class.
 /// </summary>
 /// <param name="jobSettings">Job settings</param>
 /// <param name="retryPolicy">Retry policy</param>
 public AuthenticationHelper(Settings jobSettings, Polly.Retry.AsyncRetryPolicy retryPolicy)
 {
     _settings    = jobSettings;
     _retryPolicy = retryPolicy;
 }
Пример #9
0
        public Rev(
            Config config
            )
        {
            _config = config;

            if (string.IsNullOrWhiteSpace(_config?.jwt))
            {
                throw new Exception("invalid config.JWT");
            }

            if (string.IsNullOrWhiteSpace(_config.workspace))
            {
                throw new Exception("invalid config.workspace");
            }

            if (string.IsNullOrWhiteSpace(_config.revUrl))
            {
                throw new Exception("invalid config.revUrl");
            }


            var trimmed = _config.revUrl.TrimEnd('/');

            completedRevUrl = (str) => $"{trimmed}{str}";

            _httpClient = new HttpClient();
            _httpClient.DefaultRequestHeaders.Add("workspace", _config.workspace);
            _httpClient.DefaultRequestHeaders.Authorization
                = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _config.jwt);


            _retryPolicy = Policy
                           .HandleResult <HttpResponseMessage>(message =>
            {
                var ret = !message.IsSuccessStatusCode &&
                          message.StatusCode != HttpStatusCode.NotImplemented &&
                          message.StatusCode != HttpStatusCode.NotFound &&
                          message.StatusCode != HttpStatusCode.Unauthorized
                ;

                return(ret);
            })
                           .WaitAndRetryAsync(8, i => {
                if (i == 1)
                {
                    return(TimeSpan.FromMilliseconds(1));
                }

                if (i > 4)
                {
                    return(TimeSpan.FromSeconds(10 * (i - 4)));
                }

                return(TimeSpan.FromSeconds(5));
            }, (result, timeSpan, retryCount, context) =>
            {
                //var t = result;
                if (1 == retryCount)
                {
                    return;
                }

                Console.WriteLine($"Request failed with {result.Result.StatusCode}. Waiting {timeSpan} before next retry. Retry attempt {retryCount}");
            });
        }
        /// <summary>
        /// Called by the <see cref="T:Quartz.IScheduler" /> when a <see cref="T:Quartz.ITrigger" />
        /// fires that is associated with the <see cref="T:Quartz.IJob" />.
        /// </summary>
        /// <param name="context">The execution context.</param>
        /// <exception cref="JobExecutionException">false</exception>
        /// <remarks>
        /// The implementation may wish to set a  result object on the
        /// JobExecutionContext before this method exits.  The result itself
        /// is meaningless to Quartz, but may be informative to
        /// <see cref="T:Quartz.IJobListener" />s or
        /// <see cref="T:Quartz.ITriggerListener" />s that are watching the job's
        /// execution.
        /// </remarks>
        public async Task Execute(IJobExecutionContext context)
        {
            var dataMap = context.JobDetail.JobDataMap;
            // Save the orig Values for later
            string inputDir         = dataMap.GetString(SettingsConstants.InputDir);
            string uploadSuccessDir = dataMap.GetString(SettingsConstants.UploadSuccessDir);
            string uploadErrorsDir  = dataMap.GetString(SettingsConstants.UploadErrorsDir);
            string origCompany      = dataMap.GetString(SettingsConstants.Company);

            try
            {
                log4net.Config.XmlConfigurator.Configure();
                _context = context;

                string placeHolder = "???";


                foreach (string company in FileHelper.getCompanysFromPath(inputDir, placeHolder, origCompany))
                {
                    // Set the folderspecific company values
                    dataMap.Put(SettingsConstants.InputDir, inputDir.Replace(placeHolder, company));
                    dataMap.Put(SettingsConstants.UploadSuccessDir, uploadSuccessDir.Replace(placeHolder, company));
                    dataMap.Put(SettingsConstants.UploadErrorsDir, uploadErrorsDir.Replace(placeHolder, company));
                    dataMap.Put(SettingsConstants.Company, company);

                    _settings.Initialize(context);

                    // Reset to orig value
                    dataMap.Put(SettingsConstants.InputDir, inputDir);
                    dataMap.Put(SettingsConstants.UploadSuccessDir, uploadSuccessDir);
                    dataMap.Put(SettingsConstants.UploadErrorsDir, uploadErrorsDir);
                    dataMap.Put(SettingsConstants.Company, origCompany);

                    if (_settings.IndefinitePause)
                    {
                        await context.Scheduler.PauseJob(context.JobDetail.Key);

                        Log.InfoFormat(CultureInfo.InvariantCulture,
                                       string.Format(Resources.Job_0_was_paused_indefinitely, _context.JobDetail.Key));
                        return;
                    }

                    _retryPolicyForIo = Policy.Handle <IOException>().WaitAndRetry(
                        retryCount: _settings.RetryCount,
                        sleepDurationProvider: attempt => TimeSpan.FromSeconds(_settings.RetryDelay),
                        onRetry: (exception, calculatedWaitDuration) =>
                    {
                        Log.WarnFormat(CultureInfo.InvariantCulture, string.Format(Resources.Job_0_Retrying_IO_operation_Exception_1, _context.JobDetail.Key, exception.Message));
                    });
                    _retryPolicyForHttp = Policy.Handle <HttpRequestException>().WaitAndRetryAsync(
                        retryCount: _settings.RetryCount,
                        sleepDurationProvider: attempt => TimeSpan.FromSeconds(_settings.RetryDelay),
                        onRetry: (exception, calculatedWaitDuration) =>
                    {
                        Log.WarnFormat(CultureInfo.InvariantCulture, string.Format(Resources.Job_0_Retrying_Http_operation_Exception_1, _context.JobDetail.Key, exception.Message));
                    });

                    if (Log.IsDebugEnabled)
                    {
                        Log.DebugFormat(CultureInfo.InvariantCulture, string.Format(Resources.Job_0_starting, _context.JobDetail.Key));
                    }

                    await Process();

                    if (Log.IsDebugEnabled)
                    {
                        Log.DebugFormat(CultureInfo.InvariantCulture, string.Format(Resources.Job_0_ended, _context.JobDetail.Key));
                    }
                }
            }
            catch (Exception ex)
            {
                if (dataMap != null)
                {
                    // Reset to orig values if an error occured
                    dataMap.Put(SettingsConstants.InputDir, inputDir);
                    dataMap.Put(SettingsConstants.UploadSuccessDir, uploadSuccessDir);
                    dataMap.Put(SettingsConstants.UploadErrorsDir, uploadErrorsDir);
                    dataMap.Put(SettingsConstants.Company, origCompany);
                }

                if (_settings.PauseJobOnException)
                {
                    await context.Scheduler.PauseJob(context.JobDetail.Key);

                    Log.WarnFormat(CultureInfo.InvariantCulture,
                                   string.Format(Resources.Job_0_was_paused_because_of_error, _context.JobDetail.Key));
                }
                if (Log.IsDebugEnabled)
                {
                    if (!string.IsNullOrEmpty(ex.Message))
                    {
                        Log.Error(ex.Message, ex);
                    }
                    else
                    {
                        Log.Error("Uknown exception", ex);
                    }

                    while (ex.InnerException != null)
                    {
                        if (!string.IsNullOrEmpty(ex.InnerException.Message))
                        {
                            Log.Error(ex.InnerException.Message, ex.InnerException);
                        }

                        ex = ex.InnerException;
                    }
                }
                if (context.Scheduler.SchedulerName != "Private")
                {
                    throw new JobExecutionException(string.Format(Resources.Upload_job_0_failed, _context.JobDetail.Key), ex, false);
                }

                if (!Log.IsDebugEnabled)
                {
                    Log.Error(string.Format(Resources.Job_0_thrown_an_error_1, _context.JobDetail.Key, ex.Message));
                }
            }
        }