-
-
Save wdspider/a1cf8328dbcf6cd42ea0a889f5427f0b to your computer and use it in GitHub Desktop.
Example of Polly Timeout Policy not working as expected. ( .NET Core 2.1 console app)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>netcoreapp2.1</TargetFramework> | |
<LangVersion>latest</LangVersion> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.6" /> | |
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.1" /> | |
<PackageReference Include="Microsoft.Extensions.Http" Version="2.1.1" /> | |
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.1" /> | |
</ItemGroup> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace PollyTimeoutDemo | |
{ | |
using System; | |
using System.Diagnostics; | |
using System.Net.Http; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.Extensions.DependencyInjection; | |
using Polly; | |
using Polly.Timeout; | |
class Program | |
{ | |
static async Task Main(string[] args) | |
{ | |
try | |
{ | |
Console.WriteLine("Building Service Provider"); | |
TimeoutPolicy<HttpResponseMessage> timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(5, TimeoutStrategy.Optimistic); | |
IServiceCollection services = new ServiceCollection() | |
.AddTransient<ClientLoggingHandler>(); | |
services.AddHttpClient<IMyClient, MyClient>() | |
.AddHttpMessageHandler<ClientLoggingHandler>() | |
.AddPolicyHandler(timeoutPolicy); | |
ServiceProvider serviceProvider = services.BuildServiceProvider(); | |
Console.WriteLine("Getting client"); | |
IMyClient myClient = serviceProvider.GetService<IMyClient>(); | |
ClientResponse response = await myClient.SendRequest(new ClientRequest()); | |
} | |
catch(Exception ex) { PrintException(ex); } | |
Console.ReadKey(); | |
} | |
static void PrintException(Exception ex) | |
{ | |
Console.WriteLine(); | |
while (ex != null) | |
{ | |
Console.WriteLine(ex.ToString()); | |
Console.WriteLine(); | |
ex = ex.InnerException; | |
} | |
} | |
} | |
class ClientResponse { } | |
class ClientRequest { } | |
interface IMyClient | |
{ | |
Task<ClientResponse> SendRequest(ClientRequest request); | |
} | |
class MyClient : IMyClient | |
{ | |
private readonly HttpClient httpClient; | |
public MyClient(HttpClient httpClient) => this.httpClient = httpClient; | |
public async Task<ClientResponse> SendRequest(ClientRequest request) | |
{ | |
HttpResponseMessage response = await httpClient.PostAsJsonAsync("http://www.google.com", request); | |
response.EnsureSuccessStatusCode(); | |
return await response.Content.ReadAsAsync<ClientResponse>(); | |
} | |
} | |
class ClientLoggingHandler : DelegatingHandler | |
{ | |
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | |
{ | |
ValueStopwatch stopwatch = ValueStopwatch.Start(); | |
Console.WriteLine("Starting Request"); | |
await Task.Delay(TimeSpan.FromSeconds(20), cancellationToken); | |
HttpResponseMessage response = await base.SendAsync(request, cancellationToken); | |
TimeSpan duration = stopwatch.Elasped(); | |
Console.WriteLine($"Finished Request: {duration}"); | |
return response; | |
} | |
} | |
public struct ValueStopwatch | |
{ | |
#region Internal State | |
private static readonly double TimestampTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency; | |
private long startTimestamp; | |
#endregion | |
private ValueStopwatch(long startTimestamp) => this.startTimestamp = startTimestamp; | |
#region Methods | |
public static ValueStopwatch Start() => new ValueStopwatch(Stopwatch.GetTimestamp()); | |
public TimeSpan Elasped() | |
{ | |
if (startTimestamp == 0) throw new InvalidOperationException($"{nameof(ValueStopwatch)} has not been initialized yet."); | |
return new TimeSpan((long)(TimestampTicks * (Stopwatch.GetTimestamp() - startTimestamp))); | |
} | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Reverse the order of delegating handlers as below, and the timeout works: