Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1712 Bump to Polly 8.0 #1714

Merged
merged 10 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions src/Ocelot.Provider.Polly/CircuitBreaker.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
using Polly;

namespace Ocelot.Provider.Polly
{
public class CircuitBreaker
{
private readonly List<IAsyncPolicy> _policies = new();

public CircuitBreaker(params IAsyncPolicy[] policies)
{
foreach (var policy in policies.Where(p => p != null))
{
_policies.Add(policy);
}
Policies = policies.Where(p => p != null).ToArray();
}

public IAsyncPolicy[] Policies => _policies.ToArray();
public IAsyncPolicy[] Policies { get; }
}
}
2 changes: 1 addition & 1 deletion src/Ocelot.Provider.Polly/Ocelot.Provider.Polly.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Polly" Version="7.2.3" />
<PackageReference Include="Polly" Version="8.0.0" />
RaynaldM marked this conversation as resolved.
Show resolved Hide resolved
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
Expand Down
16 changes: 7 additions & 9 deletions src/Ocelot.Provider.Polly/OcelotBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,13 @@ public static IOcelotBuilder AddPolly(this IOcelotBuilder builder)
{typeof(BrokenCircuitException), e => new RequestTimedOutError(e)},
};

builder.Services.AddSingleton(errorMapping);

static DelegatingHandler QosDelegatingHandlerDelegate(DownstreamRoute route, IOcelotLoggerFactory logger)
{
return new PollyCircuitBreakingDelegatingHandler(new PollyQoSProvider(route, logger), logger);
}

builder.Services.AddSingleton((QosDelegatingHandlerDelegate)QosDelegatingHandlerDelegate);
builder.Services
.AddSingleton(errorMapping)
.AddSingleton<QosDelegatingHandlerDelegate>(GetDelegatingHandler);
return builder;
}
}

private static DelegatingHandler GetDelegatingHandler(DownstreamRoute route, IOcelotLoggerFactory logger)
=> new PollyCircuitBreakingDelegatingHandler(new PollyQoSProvider(route, logger), logger);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Ocelot.Logging;
using Ocelot.Provider.Polly.Interfaces;
using Polly;
using Polly.CircuitBreaker;

namespace Ocelot.Provider.Polly
Expand Down Expand Up @@ -28,7 +27,7 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
return await base.SendAsync(request, cancellationToken);
}

IAsyncPolicy policy = policies.Length > 1
var policy = policies.Length > 1
? Policy.WrapAsync(policies)
: policies[0];

Expand Down
73 changes: 31 additions & 42 deletions src/Ocelot.Provider.Polly/PollyQoSProvider.cs
Original file line number Diff line number Diff line change
@@ -1,65 +1,54 @@
using Ocelot.Configuration;
using Ocelot.Logging;
using Ocelot.Provider.Polly.Interfaces;
using Polly;
using Polly.CircuitBreaker;
using Polly.Timeout;
using Ocelot.Configuration;
using Ocelot.Logging;
using Ocelot.Provider.Polly.Interfaces;
using Polly.CircuitBreaker;
using Polly.Timeout;

namespace Ocelot.Provider.Polly
{
public class PollyQoSProvider : IPollyQoSProvider
{
private readonly AsyncCircuitBreakerPolicy _circuitBreakerPolicy;
private readonly AsyncTimeoutPolicy _timeoutPolicy;
private readonly IOcelotLogger _logger;

public PollyQoSProvider(AsyncCircuitBreakerPolicy circuitBreakerPolicy, AsyncTimeoutPolicy timeoutPolicy, IOcelotLogger logger)
{
_circuitBreakerPolicy = circuitBreakerPolicy;
_timeoutPolicy = timeoutPolicy;
_logger = logger;
}

public PollyQoSProvider(DownstreamRoute route, IOcelotLoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<PollyQoSProvider>();

_ = Enum.TryParse(route.QosOptions.TimeoutStrategy, out TimeoutStrategy strategy);

_timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(route.QosOptions.TimeoutValue), strategy);

AsyncCircuitBreakerPolicy circuitBreakerPolicy = null;
if (route.QosOptions.ExceptionsAllowedBeforeBreaking > 0)
{
_circuitBreakerPolicy = Policy
{
var info = $"Route: {GetRouteName(route)}; Breaker logging in {nameof(PollyQoSProvider)}: ";
var logger = loggerFactory.CreateLogger<PollyQoSProvider>();
circuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.Or<TimeoutRejectedException>()
.Or<TimeoutException>()
.CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: route.QosOptions.ExceptionsAllowedBeforeBreaking,
durationOfBreak: TimeSpan.FromMilliseconds(route.QosOptions.DurationOfBreak),
onBreak: (ex, breakDelay) =>
{
_logger.LogError(
".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex);
},
onBreak: (ex, breakDelay) =>
logger.LogError(info + $"Breaking the circuit for {breakDelay.TotalMilliseconds} ms!", ex),
onReset: () =>
{
_logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again.");
},
logger.LogDebug(info + "Call OK! Closed the circuit again."),
onHalfOpen: () =>
{
_logger.LogDebug(".Breaker logging: Half-open; next call is a trial.");
}
logger.LogDebug(info + "Half-open; Next call is a trial.")
);
}
else
{
_circuitBreakerPolicy = null;
}

CircuitBreaker = new CircuitBreaker(_circuitBreakerPolicy, _timeoutPolicy);
_ = Enum.TryParse(route.QosOptions.TimeoutStrategy, out TimeoutStrategy strategy);
var timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(route.QosOptions.TimeoutValue), strategy);
CircuitBreaker = new CircuitBreaker(circuitBreakerPolicy, timeoutPolicy);
}

private const string ObsoleteConstructorMessage = $"Use the constructor {nameof(PollyQoSProvider)}({nameof(DownstreamRoute)} route, {nameof(IOcelotLoggerFactory)} loggerFactory)!";

[Obsolete(ObsoleteConstructorMessage)]
public PollyQoSProvider(AsyncCircuitBreakerPolicy circuitBreakerPolicy, AsyncTimeoutPolicy timeoutPolicy, IOcelotLogger logger)
{
throw new NotSupportedException(ObsoleteConstructorMessage);
}

public CircuitBreaker CircuitBreaker { get; }
public CircuitBreaker CircuitBreaker { get; }

private static string GetRouteName(DownstreamRoute route)
=> string.IsNullOrWhiteSpace(route.ServiceName)
? route.UpstreamPathTemplate?.Template ?? route.DownstreamPathTemplate?.Value ?? string.Empty
: route.ServiceName;
}
}
2 changes: 0 additions & 2 deletions src/Ocelot.Provider.Polly/Usings.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// Default Microsoft.NET.Sdk namespaces
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Net.Http;
global using System.Threading;
global using System.Threading.Tasks;

// Project extra global namespaces
global using Ocelot;
global using Polly;
2 changes: 1 addition & 1 deletion test/Ocelot.UnitTests/Ocelot.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
<PackageReference Include="CacheManager.Core" Version="2.0.0-beta-1629" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="2.0.0-beta-1629" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
<PackageReference Include="Polly" Version="7.2.3" />
<PackageReference Include="Polly" Version="8.0.0" />
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>
10 changes: 8 additions & 2 deletions test/Ocelot.UnitTests/Polly/PollyQoSProviderTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Ocelot.Configuration.Builder;
using Ocelot.Logging;
using Ocelot.Provider.Polly;

using Polly.CircuitBreaker;
using Polly.Timeout;

namespace Ocelot.UnitTests.Polly
{
public class PollyQoSProviderTests
Expand All @@ -18,7 +20,11 @@ public void Should_build()
.Build();
var factory = new Mock<IOcelotLoggerFactory>();
var pollyQoSProvider = new PollyQoSProvider(route, factory.Object);
pollyQoSProvider.CircuitBreaker.ShouldNotBeNull();
var policies = pollyQoSProvider.CircuitBreaker.ShouldNotBeNull()
.Policies.ShouldNotBeNull();
policies.Length.ShouldBeGreaterThan(0);
policies.ShouldContain(p => p is AsyncCircuitBreakerPolicy);
policies.ShouldContain(p => p is AsyncTimeoutPolicy);
}
}
}