Use connection timeout check in common strategies

This commit is contained in:
Nikita Balabaev 2024-05-07 14:21:43 +02:00 коммит произвёл github-actions
Родитель 72fdb38129
Коммит 6d3eb4ce79
4 изменённых файлов: 24 добавлений и 12 удалений

Просмотреть файл

@ -38,13 +38,8 @@ public static class HttpClientHedgingResiliencePredicates
/// <returns><see langword="true"/> if outcome is transient, <see langword="false"/> if not.</returns>
[Experimental(diagnosticId: DiagnosticIds.Experiments.Resilience, UrlFormat = DiagnosticIds.UrlFormat)]
public static bool IsTransient(Outcome<HttpResponseMessage> outcome, CancellationToken cancellationToken)
=> IsConnectionTimeout(outcome, cancellationToken)
|| IsTransient(outcome);
internal static bool IsConnectionTimeout(in Outcome<HttpResponseMessage> outcome, in CancellationToken cancellationToken)
=> !cancellationToken.IsCancellationRequested
&& outcome.Exception is OperationCanceledException { Source: "System.Private.CoreLib" }
&& outcome.Exception.InnerException is TimeoutException;
=> HttpClientResiliencePredicates.IsHttpConnectionTimeout(outcome, cancellationToken)
|| IsTransient(outcome);
/// <summary>
/// Determines whether an exception should be treated by hedging as a transient failure.

Просмотреть файл

@ -16,7 +16,7 @@ public class HttpHedgingStrategyOptions : HedgingStrategyOptions<HttpResponseMes
/// Initializes a new instance of the <see cref="HttpHedgingStrategyOptions"/> class.
/// </summary>
/// <remarks>
/// By default the options is set to handle only transient failures,
/// By default, the options is set to handle only transient failures,
/// i.e. timeouts, 5xx responses and <see cref="HttpRequestException"/> exceptions.
/// </remarks>
public HttpHedgingStrategyOptions()

Просмотреть файл

@ -2,8 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Net.Http;
using System.Threading;
using Microsoft.Shared.DiagnosticIds;
using Microsoft.Shared.Diagnostics;
using Polly;
using Polly.Timeout;
@ -26,6 +29,17 @@ public static class HttpClientResiliencePredicates
_ => false
};
/// <summary>
/// Determines whether an <see cref="HttpResponseMessage"/> should be treated by resilience strategies as a transient failure.
/// </summary>
/// <param name="outcome">The outcome of the user-specified callback.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> associated with the execution.</param>
/// <returns><see langword="true"/> if outcome is transient, <see langword="false"/> if not.</returns>
[Experimental(diagnosticId: DiagnosticIds.Experiments.Resilience, UrlFormat = DiagnosticIds.UrlFormat)]
public static bool IsTransient(Outcome<HttpResponseMessage> outcome, CancellationToken cancellationToken)
=> IsHttpConnectionTimeout(outcome, cancellationToken)
|| IsTransient(outcome);
/// <summary>
/// Determines whether an exception should be treated by resilience strategies as a transient failure.
/// </summary>
@ -33,10 +47,14 @@ public static class HttpClientResiliencePredicates
{
_ = Throw.IfNull(exception);
return exception is HttpRequestException ||
exception is TimeoutRejectedException;
return exception is HttpRequestException or TimeoutRejectedException;
}
internal static bool IsHttpConnectionTimeout(in Outcome<HttpResponseMessage> outcome, in CancellationToken cancellationToken)
=> !cancellationToken.IsCancellationRequested
&& outcome.Exception is OperationCanceledException { Source: "System.Private.CoreLib" }
&& outcome.Exception.InnerException is TimeoutException;
/// <summary>
/// Determines whether a response contains a transient failure.
/// </summary>
@ -52,7 +70,6 @@ public static class HttpClientResiliencePredicates
return statusCode >= InternalServerErrorCode ||
response.StatusCode == HttpStatusCode.RequestTimeout ||
statusCode == TooManyRequests;
}
private const int InternalServerErrorCode = (int)HttpStatusCode.InternalServerError;

Просмотреть файл

@ -26,7 +26,7 @@ public class HttpRetryStrategyOptions : RetryStrategyOptions<HttpResponseMessage
/// </remarks>
public HttpRetryStrategyOptions()
{
ShouldHandle = args => new ValueTask<bool>(HttpClientResiliencePredicates.IsTransient(args.Outcome));
ShouldHandle = args => new ValueTask<bool>(HttpClientResiliencePredicates.IsTransient(args.Outcome, args.Context.CancellationToken));
BackoffType = DelayBackoffType.Exponential;
ShouldRetryAfterHeader = true;
UseJitter = true;