Пример #1
0
        public async Task SetAsync(
            string key,
            T item,
            TimeSpan expiration)
        {
            var result = await _setFallBack
                         .ExecuteAsync(async() =>
                                       await SetAsyncInner(key, item, expiration)
                                       .ConfigureAwait(false))
                         .ConfigureAwait(false);

            if (result)
            {
                if (_debugLoggingEnabled)
                {
                    _logger.LogDebug(
                        $"Cache insert operation successful for {key}");
                }
            }
            else
            {
                if (_errorLoggingEnabled)
                {
                    _logger.LogDebug(
                        $"Caching problems when setting {key}");
                }
            }
        }
Пример #2
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await Task.Yield(); // https://github.com/dotnet/extensions/issues/2149

            while (!stoppingToken.IsCancellationRequested)
            {
                if (_queue.Messages.Count > _maxQueue)
                {
                    _queue.Messages.Clear();
                    _logger.LogWarning($"Dumped {_maxQueue} logs in queue.");
                }

                if (_queue.Messages.TryDequeue(out HttpLogEntry message))
                {
                    try
                    {
                        await _policy.ExecuteAsync(async() => await _service.PostLogAsync(JsonSerializer.Serialize(message), stoppingToken));
                    }
                    catch (Exception e) when(
                        e is HttpRequestException ||
                        e is OperationCanceledException ||
                        e is BrokenCircuitException)
                    {
                        if (Enum.Parse <LogLevel>(message.LogLevel) > LogLevel.Debug)
                        {
                            _queue.Messages.Enqueue(message);
                        }
                    }
                }
            }
        }
Пример #3
0
        public override async Task <TReturn> HandleExceptionAsync <TReturn>(Func <CancellationToken, Task <TReturn> > func, CancellationToken funcCancellationToken = default, Func <CancellationToken, Task> onExceptionCompensatingHandler = null, CancellationToken onExceptionCompensatingHandlerCancellationToken = default)
        {
            Task <TReturn> returnValue = default;

            try
            {
                var returnValueFromFunc = await func(funcCancellationToken);

                if (returnValueFromFunc is Task <TReturn> )
                {
                    returnValue = returnValueFromFunc as Task <TReturn>;
                }
                else
                {
                    returnValue = Task.FromResult(returnValueFromFunc);
                }
            }
            catch (Exception ex)
            {
                returnValue = await ExceptionHandlingUtility.WrapFuncWithExceptionHandling(async() =>
                {
                    if (CheckIfExceptionsNeedsToBePollyHandled(ex))
                    {
                        AsyncPolicyWrap policyWrap = GetPolicyWrapWithProperFallbackActionSetForFallbackPoliciesAsync(ex, onExceptionCompensatingHandler);
                        return(await policyWrap.ExecuteAsync(func, funcCancellationToken) as Task <TReturn>);
                    }
                    return(default(Task <TReturn>));
                }, _logger);

                await HandleExceptionWithThrowCondition(ex, onExceptionCompensatingHandler, onExceptionCompensatingHandlerCancellationToken);
            }
            return(await returnValue);
        }
        public void Should_retry_until_threshold_is_reached()
        {
            AsyncCircuitBreakerPolicy breaker = Policy
                                                .Handle <Exception>()
                                                .CircuitBreakerAsync(3,
                                                                     TimeSpan.FromMilliseconds(1000),
                                                                     OnBreak, OnReset);

            AsyncPolicyWrap retryPolicy = Policy.Handle <Exception>().RetryAsync(3)
                                          .WrapAsync(breaker);



            //var policy = Policy
            //    .Handle<TaskCanceledException>()
            //    .Or<FailedConnectionToBankException>()
            //    .FallbackAsync(cancel => ReturnWillHandleLater(payment.GatewayPaymentId, payment.RequestId))
            //    .WrapAsync(breaker);



            int count = 0;



            retryPolicy.ExecuteAsync(async() =>
            {
                Console.WriteLine(count++);
                await Task.FromException(new Exception());
            });
        }
Пример #5
0
        public async Task <T> GetAsync(string key)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(key))
                {
                    throw new ArgumentNullException(nameof(key));
                }

                var cacheKey = GetKey(key);

                string json = await _getFallBack
                              .ExecuteAsync(async() =>
                                            await Task.Run(
                                                () => _handle.cache.Get <string>(cacheKey))
                                            .ConfigureAwait(false)
                                            )
                              .ConfigureAwait(false);

                if (string.IsNullOrWhiteSpace(json))
                {
                    if (_debugLoggingEnabled)
                    {
                        _logger.LogDebug(
                            "Cache Miss: No item with key {key} in NCache", key);
                    }
                    return(null);
                }
                else if (json.Equals(CacheHandle.CACHE_PROBLEMS))
                {
                    if (_errorLoggingEnabled)
                    {
                        _logger.LogError(
                            $"Cache problems when accessing {key}");
                    }
                    return(null);
                }
                else
                {
                    if (_debugLoggingEnabled)
                    {
                        _logger.LogDebug(
                            "Cache Hit: Item with key {key} found in NCache", key);
                    }
                    return(_serializer.Deserialize <T>(json));
                }
            }
            catch (Exception ex)
            {
                if (_errorLoggingEnabled)
                {
                    _logger.LogError(
                        ex,
                        $"Something wrong with GetAsync for key {key}");
                }
                throw;
            }
        }
        protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var response = await Policy.ExecuteAsync(
                async() =>
            {
                Log.Information("sending request to {@Uri}...", request.RequestUri);
                return(await base.SendAsync(request, cancellationToken).ConfigureAwait(false));
            }
                ).ConfigureAwait(false);

            return(response);
        }
Пример #7
0
 public async Task <bool> Handle(ChargePatientCommand request, CancellationToken cancellationToken)
 {
     return(await _policyWrap.ExecuteAsync(async() =>
     {
         var result = await _customer.Charge(300);
         if (result == false)
         {
             throw new HttpRequestException("This is a fake request Exception");
         }
         return true;
     }));
 }
Пример #8
0
        /// <inheritdoc />
        public async Task <(Stream stream, string mediaType)> FetchAsync(Uri fetchUri)
        {
            var stopwatch     = Stopwatch.StartNew();
            var policyContext = new Context(fetchUri.ToString());

            _logger.LogDebug("Start fetch request to {url}", fetchUri);
            using (var response = await _timeoutWithRetryPolicy.ExecuteAsync(FetchAction, policyContext, CancellationToken.None))
            {
                stopwatch.Stop();
                _fetchDurationMsMetric.Labels(fetchUri.Host).Observe(stopwatch.ElapsedMilliseconds);
                _logger.LogDebug("Fetch request executed in {elapsedMs} ms", stopwatch.ElapsedMilliseconds);

                if (!response.IsSuccessStatusCode)
                {
                    _fetchErrorsMetric.Inc();
                    var content = await response.Content.ReadAsStringAsync();

                    _logger.LogError("Got status {status} on {method} request to {url} with content: {content}", response.StatusCode, HttpMethod.Get, fetchUri, content);
                    throw new FetchRequestException(response.StatusCode, content);
                }

                if (response.Content.Headers.ContentLength > _maxBinarySize)
                {
                    throw new FetchResponseTooLargeException(response.Content.Headers.ContentLength.Value);
                }

                if (string.IsNullOrEmpty(response.Content.Headers.ContentType.MediaType))
                {
                    throw new FetchResponseContentTypeInvalidException("Content type in response is not specified");
                }

                var memoryStream = new MemoryStream();
                using (var responseStream = await response.Content.ReadAsStreamAsync())
                {
                    int readBytes;
                    var buffer = new byte[StreamCopyBufferSize];
                    do
                    {
                        readBytes = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                        await memoryStream.WriteAsync(buffer, 0, readBytes);

                        if (memoryStream.Length > _maxBinarySize)
                        {
                            throw new FetchResponseTooLargeException(memoryStream.Length);
                        }
                    }while (readBytes > 0);
                }

                return(memoryStream, response.Content.Headers.ContentType.MediaType);
            }
        }
        public async Task <ActionResult <IEnumerable <Team> > > GetSomeData(CancellationToken cancellationToken)
        {
            Context context = new Context(nameof(GetSomeData)).WithChaosSettings(chaosSettings);

            retries = 0;
            //https://github.com/PawelGerr/EntityFrameworkCore-Demos/blob/master/src/EntityFramework.Demo/Demos/NamedTransactionsDemo.cs
            //catch (InvalidOperationException ex) when ((ex.InnerException?.InnerException is SqlException sqlEx) && sqlEx.Number == 1205)
            var fault       = new InvalidOperationException("Simmy injected a deadlockException");
            var chaosPolicy = MonkeyPolicy.InjectExceptionAsync(with =>
                                                                with.Fault(fault)
                                                                .InjectionRate(0.95)
                                                                .Enabled()
                                                                );
            var retryPolicy = Policy.Handle <Exception>().WaitAndRetryAsync(
                3,                                         // Retry 3 times
                attempt => TimeSpan.FromMilliseconds(200), // Wait 200ms between each try.
                (exception, calculatedWaitDuration) =>     // Capture some info for logging!
            {
                // This is your new exception handler!
                // Tell the user what they've won!
                _logger.LogWarning(EventIds.DBReadFailure, exception, "hit an exception");
                retries++;
            });

            AsyncPolicyWrap faultAndRetryWrap = Policy.WrapAsync(retryPolicy, chaosPolicy);

            try
            {
                // Retry the following call according to the policy - 3 times.
                var something = await faultAndRetryWrap.ExecuteAsync <List <Team> >(
                    async (context, cancellationToken) => // The Execute() overload takes a CancellationToken, but it happens the executed code does not honour it.
                {
                    // This code is executed within the Policy
                    var corr = context.CorrelationId;
                    // Make a request and get a response

                    // Display the response message on the console
                    _logger.LogDebug("Getting some data: ");
                    return(await _context.Teams.ToListAsync());
                }
                    , context
                    , cancellationToken // The cancellationToken passed in to Execute() enables the policy instance to cancel retries, when the token is signalled.
                    );

                return(something);
            }
            catch (Exception e)
            {
                _logger.LogError("Request eventually failed with: " + e.Message);
            }
            return(BadRequest());
        }
        private async Task <IEnumerable <SyndicationItem> > TryReadFeed(IAmACommunityMember tamarin, string feedUri, Func <SyndicationItem, bool> filter)
        {
            try
            {
                return(await policy.ExecuteAsync(context => ReadFeed(feedUri, filter), new Context(feedUri)).ConfigureAwait(false));
            }
            catch (FeedReadFailedException ex)
            {
                Logger.Error(ex, $"{tamarin.FirstName} {tamarin.LastName}'s feed of {ex.Data["FeedUri"]} failed to load.");
            }

            return(new SyndicationItem[0]);
        }
Пример #11
0
        public async Task <ResponseObject> GetAsync(Uri url, string token)
        {
            _client.DefaultRequestHeaders.Authorization = getBearerAuthorization(token);

            var response = await policies.ExecuteAsync(() => _client.GetAsync(url));

            return(manageResponse(response));
        }
Пример #12
0
        public async Task <ServiceResponse <T> > ExecuteRequest <T>(string baseUrl,
                                                                    string path, Method method, object body = null, List <RequestParameter> parameters          = null,
                                                                    List <RequestHeader> headers            = null, AsyncPolicyWrap <IRestResponse <T> > policy = null)
            where T : new()
        {
            var client = new RestClient(baseUrl)
            {
                Timeout = RequestTimeout * 1000
            };

            var request = ConfigureRequest(path, method, body, parameters, headers);
            var fullUrl = client.BuildUri(request);

            IRestResponse <T> response = null;

            if (policy == null)
            {
                response = await client.ExecuteTaskAsync <T>(request);
            }
            else
            {
                Context context = new Context().WithLogger(_logger);
                response = await policy.ExecuteAsync(ctx => client.ExecuteTaskAsync <T>(request), context);
            }

            //var cb = policy.GetPolicies();

            string responseErr = null;
            ServiceResponseException responseEx   = null;
            HttpStatusCode           responseCode = response.StatusCode;

            if (!response.IsSuccessful)
            {
                response.Data = default;
                responseErr   = !string.IsNullOrWhiteSpace(response.ErrorMessage) ? response.ErrorMessage : response.Content;
                if (response.ResponseStatus == ResponseStatus.TimedOut)
                {
                    responseCode = HttpStatusCode.GatewayTimeout;
                }
                LogFailedRequest(response.ErrorException, responseCode, responseErr, fullUrl.ToString());
                if (!string.IsNullOrWhiteSpace(responseErr) || response.ErrorException != null)
                {
                    responseEx = new ServiceResponseException(response.StatusCode, responseErr, response.ErrorException);
                }
            }

            return(new ServiceResponse <T>(response.Data, response, responseCode, response.IsSuccessful, responseErr, responseEx));
        }
Пример #13
0
        private static async Task WaitForTransmissionAsync()
        {
            var torrentClient = DIContainer.Default.Get <ITorrentClient>();

            try
            {
                await _WaitForHealthyPolicy.ExecuteAsync(async() =>
                {
                    await torrentClient.GetAllTorrentsAsync().ConfigureAwait(false);
                }).ConfigureAwait(false);
            }
            catch (Polly.Timeout.TimeoutRejectedException e)
            {
                throw new ApplicationException("Timed out while waiting on the torrent client", e);
            }
        }
Пример #14
0
        public async Task <IActionResult> Index()
        {
            var recommendationsTask = fallback.ExecuteAsync(() => _client.GetStringAsync(_config.GetValue <string>("externalRestServices:recommendationService")));
            var viewedItemsTask     = _client.GetStringAsync(_config.GetValue <string>("externalRestServices:viewedItemsService"));
            var cartTask            = _client.GetStringAsync(_config.GetValue <string>("externalRestServices:cartService"));
            var customerTask        = _client.GetStringAsync(_config.GetValue <string>("externalRestServices:customerService"));

            var response = await Task.WhenAll(recommendationsTask, viewedItemsTask, cartTask, customerTask);

            CompositeModel model = new CompositeModel {
                Recommendations = JsonConvert.DeserializeObject <IEnumerable <Item> > (response[0]),
                ViewedItems     = JsonConvert.DeserializeObject <IEnumerable <Item> > (response[1]),
                CartItems       = JsonConvert.DeserializeObject <IEnumerable <Item> > (response[2]),
                Customers       = JsonConvert.DeserializeObject <IEnumerable <Customer> > (response[3])
            };

            return(View(model));
        }
Пример #15
0
        public async Task <T> MakeRequestAsync <T>(Task <T> request, AsyncPolicyWrap policy) where T : Status
        {
            T response = (T)Activator.CreateInstance(typeof(T));

            if (!CrossConnectivity.Current.IsConnected)
            {
                response.ErrorCode    = "";
                response.ErrorMessage = ErrorMessageConstants.DEVICE_CONNECTIVITY_ERROR;
                response.IsSuccess    = false;
            }
            else
            {
                try
                {
                    response = await policy.ExecuteAsync(async() => await request);

                    response.IsSuccess = true;
                }
                catch (AggregateException e)
                {
                    foreach (var nestedException in e.InnerExceptions)
                    {
                        response.ErrorCode    = "";
                        response.ErrorMessage = nestedException.Message;
                        response.IsSuccess    = false;
                    }
                }
                catch (ApiException e)
                {
                    response.ErrorCode    = e.StatusCode.ToString();
                    response.ErrorMessage = e.Message;
                    response.IsSuccess    = false;
                }
                catch (Exception e)
                {
                    response.ErrorCode    = "";
                    response.ErrorMessage = e.Message;
                    response.IsSuccess    = false;
                }
            }

            return(response);
        }
Пример #16
0
 public override async Task HandleExceptionAsync(Func <CancellationToken, Task> action, CancellationToken actionCancellationToken = default, Func <CancellationToken, Task> onExceptionCompensatingHandler = null, CancellationToken onExceptionCompensatingHandlerCancellationToken = default)
 {
     try
     {
         await action(actionCancellationToken);
     }
     catch (Exception ex)
     {
         ExceptionHandlingUtility.WrapActionWithExceptionHandling(async() =>
         {
             if (CheckIfExceptionsNeedsToBePollyHandled(ex))
             {
                 AsyncPolicyWrap policyWrap = GetPolicyWrapWithProperFallbackActionSetForFallbackPoliciesAsync(ex, onExceptionCompensatingHandler);
                 await policyWrap.ExecuteAsync(action, actionCancellationToken);
             }
         }, _logger);
         await HandleExceptionWithThrowCondition(ex, onExceptionCompensatingHandler, onExceptionCompensatingHandlerCancellationToken);
     }
 }
Пример #17
0
        public async Task <IActionResult> GetProduct(int productId)
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://localhost:44363/")
            };
            var contextDictionary = new Dictionary <string, object>
            {
                { "Logging", "Enabled" }
            };
            var catalogContext = new Context("CatalogContext", contextDictionary);

            // Without polly
            //var response = await httpClient.GetAsync($"api/inventories/{productId}");

            // With Polly (Retry)
            // var response = await _httpRetryPolicy.ExecuteAsync(() => httpClient.GetAsync($"api/inventories/{productId}"));

            // With Polly (Wait and Retry)
            // var response = await _httpWaitAndRetryPolicy.ExecuteAsync(() => httpClient.GetAsync($"api/inventories/{productId}"));

            // With Polly (Fallback and Retry)
            // var response = await _fallbackPolicy.ExecuteAsync(async () =>
            //     await _httpRetryPolicy.ExecuteAsync(() => httpClient.GetAsync($"api/inventories/{productId}")));

            // With Polly (Fallback, Retry and timeout) - Manual Wrap
            //var response = await
            //        _fallbackPolicy.ExecuteAsync(() =>
            //            _httpRetryPolicy.ExecuteAsync(() =>
            //                _timeoutPolicy.ExecuteAsync(async (token) => await httpClient.GetAsync($"api/inventories/{productId}", token), cancellationToken: CancellationToken.None)));

            // With Polly and Wrap
            // var response = await _policyWrap.ExecuteAsync(() => httpClient.GetAsync($"api/inventories/{productId}", CancellationToken.None));

            // With Polly and context
            var response = await _policyWrap.ExecuteAsync((context) => httpClient.GetAsync($"api/inventories/{productId}", CancellationToken.None), catalogContext);

            var result = await response.Content.ReadAsStringAsync();

            return(new OkObjectResult(result));
        }
        /// <summary>
        /// Calls the dynamic service and returns the result.
        /// </summary>
        /// <param name="serviceInfo">Information about the service to call</param>
        /// <param name="cacheRegion">The cache region to look for values for post parameters under in</param>
        /// <param name="cancellationToken">Cancellation token to cancel the request</param>
        /// <param name="additionalParameters">Additional post parameters to include in the request body</param>
        /// <returns>A service response representing the result of the call to the dynamic service</returns>
        protected override async Task <ServiceResponse> CallServiceInternal(CalledServiceInfo serviceInfo, string cacheRegion,
                                                                            CancellationToken cancellationToken, IEnumerable <KeyValuePair <string, string> > additionalParameters)
        {
            var serviceResponse = new ServiceResponse
            {
                ServiceId = serviceInfo.Id
            };

            try
            {
                AsyncPolicyWrap <ServiceResponse> breaker = GetCircuitBreakerPolicy(serviceInfo);

                return(await breaker.ExecuteAsync(async (cancelToken) =>
                {
                    IEnumerable <KeyValuePair <string, string> > postParameters = GetPostParameters(serviceInfo, cacheRegion, additionalParameters);

                    HttpClientResponse response = await _httpClientWrapper.PostAsync(serviceInfo.Endpoint, postParameters, cancelToken);


                    if (response.HttpStatusCode.IsOkStatus())
                    {
                        serviceResponse.Value = response.Response;
                        serviceResponse.Status = ServiceResponseStatus.Success;
                        serviceResponse.TokenResponses = _tokenService.ParseTokens(cacheRegion, response.Response, serviceInfo.Tokens).ToArray();
                    }
                    else
                    {
                        serviceResponse.Status = ServiceResponseStatus.Error;
                    }

                    return serviceResponse;
                }, cancellationToken : cancellationToken));
            }
            catch (Exception)
            {
                serviceResponse.Status = ServiceResponseStatus.Error;
                return(serviceResponse);
            }
        }
Пример #19
0
        public async Task <IActionResult> Get(int id)
        {
            var httpClient = GetHttpClient();

            string requestEndpoint = $"samples/mix-generic-and-non/inventory/{id}";

            var response = await _policyWrap.ExecuteAsync(token => httpClient.GetAsync(requestEndpoint, token), CancellationToken.None);

            if (response.IsSuccessStatusCode)
            {
                var itemsInStock = JsonConvert.DeserializeObject <int>(await response.Content.ReadAsStringAsync());

                return(Ok(itemsInStock));
            }

            if (response.Content != null)
            {
                return(StatusCode((int)response.StatusCode, response.Content.ReadAsStringAsync()));
            }

            return(StatusCode((int)response.StatusCode));
        }
        /// <summary>
        /// Removes the specified cacheKey async.
        /// </summary>
        /// <returns>The async.</returns>
        /// <param name="cacheKey">Cache key.</param>
        public async Task RemoveAsync(string cacheKey)
        {
            ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));

            try
            {
                // distributed cache at first
                await _distributedCache.RemoveAsync(cacheKey);
            }
            catch (Exception ex)
            {
                LogMessage($"remove cache key [{cacheKey}] error", ex);
            }

            await _localCache.RemoveAsync(cacheKey);

            // send message to bus
            await _busAsyncWrap.ExecuteAsync(async() => await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage {
                Id = _cacheId, CacheKeys = new string[] { cacheKey }
            }));
        }
Пример #21
0
        public async Task <GetOffersResult> GetOffers(OfferTypes?type, string searchCommand, int?page, int?pageSize, CancellationToken cancellationToken)
        {
            // Build request URL
            pageSize ??= _options.DefaultPageSize;
            pageSize = Math.Min(pageSize.Value, MaxPageSize);
            var parameters = new List <string>()
            {
                $"page={page ?? DefaultPage}",
                $"PageSize={pageSize}"
            };

            if (type != null)
            {
                var typeString = FirstCharLower($"{type}");
                parameters.Add($"type={typeString}");
            }
            if (searchCommand != null)
            {
                parameters.Add($"zo={searchCommand}");
            }
            var requestUrl = BuildRequestUrl("/feeds/Aanbod.svc", parameters);

            // Make request
            using var response = await _retryPolicy.ExecuteAsync(async () => await _httpClient.GetAsync(requestUrl, cancellationToken));

            // Get content from response body
            var contentString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            var content = new
            {
                Objects = new[]
                {
                    new
                    {
                        Id           = default(Guid),
                        MakelaarId   = default(int),
                        MakelaarNaam = default(string),
                    }
                },
                Paging = new
                {
                    AantalPaginas = default(int),
                    HuidigePagina = default(int),
                },
                TotaalAantalObjecten = default(int)
            };

            content = JsonConvert.DeserializeAnonymousType(contentString, content);
            var result = new GetOffersResult();

            // Build result from content
            if (content != null)
            {
                result.Paging = new PagingInfo
                {
                    TotalPages  = content.Paging.AantalPaginas,
                    CurrentPage = content.Paging.HuidigePagina,
                };
                result.TotalObjects = content.TotaalAantalObjecten;
                if (content.Objects != null)
                {
                    result.Offers = content.Objects.Select(o => new Offer
                    {
                        Id           = o.Id,
                        MakelaarId   = o.MakelaarId,
                        MakelaarNaam = o.MakelaarNaam,
                    });
                }
            }

            return(result);
        }
 private async Task <IActionResult> ProxyTo(string url)
 => await _policy.ExecuteAsync(async() => Content(await _httpClient.GetStringAsync(url)));
        /// <summary>
        /// This method performs the call to the cached service if no value is available in the cache.
        /// </summary>
        /// <param name="serviceInfo">Information about the service to call</param>
        /// <param name="cacheRegion">The cache region to look for an existing response and to look for values for post parameters under in</param>
        /// <param name="cancellationToken">Cancellation token to cancel the request</param>
        /// <param name="additionalParameters">Additional post parameters to include in the request body</param>
        /// <returns>A service response representing the result of the call to the cached service</returns>
        protected override async Task <ServiceResponse> CallServiceInternal(CalledServiceInfo serviceInfo, string cacheRegion, CancellationToken cancellationToken,
                                                                            IEnumerable <KeyValuePair <string, string> > additionalParameters)
        {
            SemaphoreSlim semaphore = _semaphores.GetOrAdd($"{cacheRegion}-{serviceInfo.CacheKey}", _ => new SemaphoreSlim(1, 1));

            try
            {
                await semaphore.WaitAsync(cancellationToken);

                if (cancellationToken.IsCancellationRequested)
                {
                    return(new ServiceResponse
                    {
                        ServiceId = serviceInfo.Id,
                        Status = ServiceResponseStatus.Timeout
                    });
                }

                CacheEntry <string> cacheResult = Cache.Get <string>(cacheRegion, serviceInfo.CacheKey);

                if (cacheResult != null)
                {
                    Log.Debug("Read value for service {ServiceName} from cache. Entry has value: {HasValue}",
                              serviceInfo.Name, cacheResult.Value != null);

                    ServiceResponse serviceResponse = new ServiceResponse
                    {
                        ServiceId = serviceInfo.Id,
                        Status    = ServiceResponseStatus.Success,
                        Value     = cacheResult.Value
                    };

                    if (string.IsNullOrEmpty(serviceResponse.Value))
                    {
                        return(serviceResponse);
                    }

                    serviceResponse.TokenResponses =
                        _tokenService.ParseTokens(cacheRegion, cacheResult.Value, serviceInfo.Tokens);

                    foreach (TokenResponse token in serviceResponse.TokenResponses)
                    {
                        Cache.Set(cacheRegion, token.CacheKey, token.Value);
                    }

                    return(serviceResponse);
                }

                AsyncPolicyWrap <ServiceResponse> breaker = GetCircuitBreakerPolicy(serviceInfo);

                return(await breaker.ExecuteAsync(async (cancelToken) =>
                {
                    IEnumerable <KeyValuePair <string, string> > postParameters =
                        GetPostParameters(serviceInfo, cacheRegion, additionalParameters);

                    HttpClientResponse response =
                        await _httpClientWrapper.PostAsync(serviceInfo.Endpoint, postParameters, cancelToken);
                    var serviceResponse = new ServiceResponse
                    {
                        ServiceId = serviceInfo.Id
                    };

                    if (response.HttpStatusCode.IsOkStatus())
                    {
                        serviceResponse.Value = response.Response;
                        serviceResponse.Status = ServiceResponseStatus.Success;
                        serviceResponse.TokenResponses =
                            _tokenService.ParseTokens(cacheRegion, response.Response, serviceInfo.Tokens);

                        foreach (TokenResponse token in serviceResponse.TokenResponses)
                        {
                            Cache.Set(cacheRegion, token.CacheKey, token.Value);
                        }

                        Cache.Set(cacheRegion, serviceInfo.CacheKey, response.Response);
                    }
                    else
                    {
                        Cache.Set <string>(cacheRegion, serviceInfo.CacheKey, null);
                        serviceResponse.Status = ServiceResponseStatus.Error;
                    }

                    return serviceResponse;
                }, cancellationToken : cancellationToken));
            }
            catch (TaskCanceledException)
            {
                return(new ServiceResponse
                {
                    ServiceId = serviceInfo.Id,
                    Status = ServiceResponseStatus.Timeout
                });
            }
            finally
            {
                if (semaphore.CurrentCount == 0)
                {
                    semaphore.Release();
                }
            }
        }
Пример #24
0
 public async Task ExecuteAsync(Func <Task> operation, CancellationToken cancellationToken = default)
 {
     await _asyncRetryPolicy.ExecuteAsync(operation);
 }
 protected override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request,
                                                         CancellationToken cancellationToken)
 => _circuitBreakerPolicy
 .ExecuteAsync(
     async ct => await base.SendAsync(request, ct),
     cancellationToken);
 private Task <T> HttpInvoker <T>(Func <Task <T> > action) =>
 // Executes the action applying all
 // the policies defined in the wrapper
 _policyWrapper.ExecuteAsync(() => action());
        public override async Task ExecuteAsync(CancellationToken cancellationToken, IProgress <Progress> progress)
        {
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }
            if (progress == null)
            {
                throw new ArgumentNullException(nameof(progress));
            }

            // Llama el servicio web de la API para hacer peticiones repetitivas al servidor.
            // El servicio esta programado para fallar despues de 3 peticiones en 5 segundos.

            eventualSuccesses = 0;
            retries           = 0;
            eventualFailuresDueToCircuitBreaking = 0;
            eventualFailuresForOtherReasons      = 0;

            progress.Report(ProgressWithMessage(typeof(Wrap_Fallback_WaitAndRetry_CircuitBreaker_Async).Name));
            progress.Report(ProgressWithMessage("======"));
            progress.Report(ProgressWithMessage(string.Empty));

            Stopwatch watch = null;

            // Definimos nuestro waitAndRetry policy: sigue intentando con intervalos de 200ms.
            var waitAndRetryPolicy = Policy
                                     .Handle <Exception>(e => !(e is BrokenCircuitException)) // Filtrado de excepción! No reintentamos si el circuit-breaker determina que el sistema invocado está fuera de servicio!
                                     .WaitAndRetryForeverAsync(
                attempt => TimeSpan.FromMilliseconds(200),
                (exception, calculatedWaitDuration) =>
            {
                progress.Report(ProgressWithMessage(".Log,vuelva e intentar: " + exception.Message, Color.Yellow));
                retries++;
            });

            // Definimos nuestro CircuitBreaker policy: cortar si la acción falla 4 veces seguidas.
            var circuitBreakerPolicy = Policy
                                       .Handle <Exception>()
                                       .CircuitBreakerAsync(
                exceptionsAllowedBeforeBreaking: 4,
                durationOfBreak: TimeSpan.FromSeconds(3),
                onBreak: (ex, breakDelay) =>
            {
                progress.Report(ProgressWithMessage(".Breaker logging: Cortando el circuito por " + breakDelay.TotalMilliseconds + "ms!", Color.Magenta));
                progress.Report(ProgressWithMessage("..debido a: " + ex.Message, Color.Magenta));
            },
                onReset: () => progress.Report(ProgressWithMessage(".Breaker logging: Llamado ok! Se cierra el circuito nuevamente!", Color.Magenta)),
                onHalfOpen: () => progress.Report(ProgressWithMessage(".Breaker logging: Half-open: el proximo llamado es de prueba!", Color.Magenta))
                );

            // Definimos un fallback policy: provee un buen mensaje de reemplazo para el usuario, si encontramos que el circuito estaba cortado.
            AsyncFallbackPolicy <string> fallbackForCircuitBreaker = Policy <string>
                                                                     .Handle <BrokenCircuitException>()
                                                                     .FallbackAsync(
                fallbackValue: "Por favor intente mas tarde [mensaje substituido por fallback policy]",
                onFallbackAsync: async b =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback capto llamada fallida por: " + b.Exception.Message
                                                    + " (despues de " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresDueToCircuitBreaking++;
            }
                );

            // Definimos un fallback policy: provee un buen mensaje substituto para el usuario, para cualquier excepcion.
            AsyncFallbackPolicy <string> fallbackForAnyException = Policy <string>
                                                                   .Handle <Exception>()
                                                                   .FallbackAsync(
                fallbackAction: async ct =>
            {
                await Task.FromResult(true);
                /* logica extra que se desee aquí */
                return("Por favor intente mas tarde [Fallback para cualquier excepción]");
            },
                onFallbackAsync: async e =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback captura eventualmented fallido por: " + e.Exception.Message
                                                    + " (despues de " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresForOtherReasons++;
            }
                );

            // Combinamos el waitAndRetryPolicy y circuitBreakerPolicy en un PolicyWrap
            AsyncPolicyWrap myResilienceStrategy = Policy.WrapAsync(waitAndRetryPolicy, circuitBreakerPolicy);

            // Envuelve los dos fallback policies en el frente del wrap existente. Demuestra el hecho de que el PolicyWrap myResilienceStrategy de arriba es solo otro Policy, el cual puede ser envuelto también.
            // Con este patron, se puede construir una estrategia general programaticamente, reusando algunas partes en común (ej. Policy Wrap myResilienceStrategy) pero variendo otras partes (ej. Fallback) individualmente para diferentes llamados.
            AsyncPolicyWrap <string> policyWrap = fallbackForAnyException.WrapAsync(fallbackForCircuitBreaker.WrapAsync(myResilienceStrategy));

            // Para info: equivalente a: AsyncPolicyWrap<string> policyWrap = Policy.WrapAsync(fallbackForAnyException, fallbackForCircuitBreaker, waitAndRetryPolicy, circuitBreakerPolicy);

            totalRequests = 0;

            using (var client = new HttpClient())
            {
                bool internalCancel = false;
                // Hacer lo siguiente hasta que una tecla sea presionada
                while (!internalCancel && !cancellationToken.IsCancellationRequested)
                {
                    totalRequests++;
                    watch = new Stopwatch();
                    watch.Start();

                    try
                    {
                        // Maneja el llamado acorde al policy wrap
                        string response = await policyWrap.ExecuteAsync(ct =>
                                                                        client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + totalRequests), cancellationToken);

                        watch.Stop();

                        // Muestra la respuesta en la consola
                        progress.Report(ProgressWithMessage("Respuesta : " + response + " (despues de " + watch.ElapsedMilliseconds + "ms)", Color.Green));

                        eventualSuccesses++;
                    }
                    catch (Exception e) // try-catch innecesario ahora que tenemos un Fallback.Handle<Exception>. Sólo está aquí para demostrar que nunca llega hasta este codigo.
                    {
                        throw new InvalidOperationException("Nunca debería llegar hasta aquí.  Uso de fallbackForAnyException debería proveer un buen mensaje devuelta al usuario para cualquier excepción.", e);
                    }

                    // Espera medio segundo
                    await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken);

                    internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
                }
            }
        }
Пример #28
0
        public async Task <string> GetGoodbyeMessage()
        {
            Trace.WriteLine($"Circuit State: {_circuitBreakerPolicy.CircuitState}");

            return(await _policyWrap.ExecuteAsync(async() => await _messageRepository.GetGoodbyeMessage()));
        }
        /// <inheritdoc/>
        public async Task <int> CountQueryAsync(
            string queryString,
            bool queryAll = false,
            CancellationToken cancellationToken = default)
        {
            var mContext = new Context
            {
                [_policyContextMethod] = nameof(CountQueryAsync)
            };

            return(await _policy.ExecuteAsync(
                       async (context, token) =>
            {
                var client = _forceClient.Value().Result;
                return await client.CountQuery(queryString, queryAll);
            },
                       mContext,
                       cancellationToken));
        }
Пример #30
0
        public override async Task ExecuteAsync(CancellationToken cancellationToken, IProgress <DemoProgress> progress)
        {
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }
            if (progress == null)
            {
                throw new ArgumentNullException(nameof(progress));
            }

            // Let's call a web api service to make repeated requests to a server.
            // The service is programmed to fail after 3 requests in 5 seconds.

            eventualSuccesses = 0;
            retries           = 0;
            eventualFailuresDueToCircuitBreaking = 0;
            eventualFailuresForOtherReasons      = 0;

            progress.Report(ProgressWithMessage(typeof(AsyncDemo07_WaitAndRetryNestingCircuitBreakerUsingPolicyWrap).Name));
            progress.Report(ProgressWithMessage("======"));
            progress.Report(ProgressWithMessage(String.Empty));

            // Define our waitAndRetry policy: keep retrying with 200ms gaps.
            var waitAndRetryPolicy = Policy
                                     .Handle <Exception>(e => !(e is BrokenCircuitException)) // Exception filtering!  We don't retry if the inner circuit-breaker judges the underlying system is out of commission!
                                     .WaitAndRetryForeverAsync(
                attempt => TimeSpan.FromMilliseconds(200),
                (exception, calculatedWaitDuration) =>
            {
                // This is your new exception handler!
                // Tell the user what they've won!
                progress.Report(ProgressWithMessage(".Log,then retry: " + exception.Message, Color.Yellow));
                retries++;
            });

            // Define our CircuitBreaker policy: Break if the action fails 4 times in a row.
            var circuitBreakerPolicy = Policy
                                       .Handle <Exception>()
                                       .CircuitBreakerAsync(
                exceptionsAllowedBeforeBreaking: 4,
                durationOfBreak: TimeSpan.FromSeconds(3),
                onBreak: (ex, breakDelay) =>
            {
                progress.Report(ProgressWithMessage(".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", Color.Magenta));
                progress.Report(ProgressWithMessage("..due to: " + ex.Message, Color.Magenta));
            },
                onReset: () => progress.Report(ProgressWithMessage(".Breaker logging: Call ok! Closed the circuit again!", Color.Magenta)),
                onHalfOpen: () => progress.Report(ProgressWithMessage(".Breaker logging: Half-open: Next call is a trial!", Color.Magenta))
                );

            // New for demo07: combine the waitAndRetryPolicy and circuitBreakerPolicy into a PolicyWrap.
            AsyncPolicyWrap policyWrap = Policy.WrapAsync(waitAndRetryPolicy, circuitBreakerPolicy);

            using (var client = new HttpClient())
            {
                totalRequests = 0;
                bool internalCancel = false;
                // Do the following until a key is pressed
                while (!internalCancel && !cancellationToken.IsCancellationRequested)
                {
                    totalRequests++;
                    Stopwatch watch = new Stopwatch();
                    watch.Start();

                    try
                    {
                        // Retry the following call according to the policy wrap
                        string response = await policyWrap.ExecuteAsync <String>(ct =>
                        {
                            // This code is executed through both policies in the wrap: WaitAndRetry outer, then CircuitBreaker inner.  Demo 06 shows a broken-out version of what this is equivalent to.

                            return(client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + totalRequests));
                        }, cancellationToken);

                        watch.Stop();

                        // Display the response message on the console
                        progress.Report(ProgressWithMessage("Response : " + response
                                                            + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Green));

                        eventualSuccesses++;
                    }
                    catch (BrokenCircuitException b)
                    {
                        watch.Stop();

                        progress.Report(ProgressWithMessage("Request " + totalRequests + " failed with: " + b.GetType().Name
                                                            + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));

                        eventualFailuresDueToCircuitBreaking++;
                    }
                    catch (Exception e)
                    {
                        watch.Stop();

                        progress.Report(ProgressWithMessage("Request " + totalRequests + " eventually failed with: " + e.Message
                                                            + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));

                        eventualFailuresForOtherReasons++;
                    }

                    // Wait half second
                    await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken);

                    internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
                }
            }
        }