Skip to content

Commit

Permalink
Add DI FileGlobalConfiguration. PollyQoSProvider, PollyQoSResilienceP…
Browse files Browse the repository at this point in the history
…ipelineProvider add DefaultRequestTimeoutSeconds
  • Loading branch information
hogwartsdeveloper committed May 28, 2024
1 parent c361677 commit 2993d4c
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 23 deletions.
24 changes: 17 additions & 7 deletions src/Ocelot.Provider.Polly/PollyQoSResiliencePipelineProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Ocelot.Configuration;
using Ocelot.Configuration.File;
using Ocelot.Logging;
using Ocelot.Provider.Polly.Interfaces;
using Polly.CircuitBreaker;
Expand All @@ -14,9 +15,20 @@ public class PollyQoSResiliencePipelineProvider : PollyQoSProviderBase, IPollyQo
{
private readonly ResiliencePipelineRegistry<OcelotResiliencePipelineKey> _resiliencePipelineRegistry;
private readonly IOcelotLogger _logger;

public const int DefaultRequestTimeoutSeconds = 90;
private int _requestTimeoutSeconds;

public int RequestTimeoutSeconds
{
get => _requestTimeoutSeconds > 0 ? _requestTimeoutSeconds : DefaultRequestTimeoutSeconds;
set => _requestTimeoutSeconds = value > 0 ? value : DefaultRequestTimeoutSeconds;
}

public PollyQoSResiliencePipelineProvider(IOcelotLoggerFactory loggerFactory,
ResiliencePipelineRegistry<OcelotResiliencePipelineKey> resiliencePipelineRegistry)
public PollyQoSResiliencePipelineProvider(
IOcelotLoggerFactory loggerFactory,
ResiliencePipelineRegistry<OcelotResiliencePipelineKey> resiliencePipelineRegistry,
FileGlobalConfiguration fileGlobalConfigure)
{
_resiliencePipelineRegistry = resiliencePipelineRegistry;
_logger = loggerFactory.CreateLogger<PollyQoSResiliencePipelineProvider>();
Expand Down Expand Up @@ -48,11 +60,9 @@ private void PollyResiliencePipelineWrapperFactory(ResiliencePipelineBuilder<Htt
{
var options = route.QosOptions;

// Add TimeoutStrategy if TimeoutValue is not int.MaxValue and greater than 0
if (options.TimeoutValue != int.MaxValue && options.TimeoutValue > 0)
{
builder.AddTimeout(TimeSpan.FromMilliseconds(options.TimeoutValue));
}
builder.AddTimeout(options.TimeoutValue == 0
? TimeSpan.FromSeconds(RequestTimeoutSeconds)
: TimeSpan.FromMilliseconds(options.TimeoutValue));

// Add CircuitBreakerStrategy only if ExceptionsAllowedBeforeBreaking is greater than 0
if (options.ExceptionsAllowedBeforeBreaking <= 0)
Expand Down
22 changes: 15 additions & 7 deletions src/Ocelot.Provider.Polly/v7/PollyQoSProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Ocelot.Configuration;
using Ocelot.Configuration.File;
using Ocelot.Logging;
using Polly.CircuitBreaker;
using Polly.Timeout;
Expand All @@ -14,13 +15,21 @@ public class PollyQoSProvider : PollyQoSProviderBase, IPollyQoSProvider<HttpResp

private readonly object _lockObject = new();
private readonly IOcelotLogger _logger;

// TODO: This should be configurable and available as global config parameter in ocelot.json

public const int DefaultRequestTimeoutSeconds = 90;

private int _requestTimeoutSeconds;

public int RequestTimeoutSeconds
{
get => _requestTimeoutSeconds > 0 ? _requestTimeoutSeconds : DefaultRequestTimeoutSeconds;
set => _requestTimeoutSeconds = value > 0 ? value : DefaultRequestTimeoutSeconds;
}

public PollyQoSProvider(IOcelotLoggerFactory loggerFactory)
public PollyQoSProvider(IOcelotLoggerFactory loggerFactory, FileGlobalConfiguration fileGlobalConfiguration)
{
_logger = loggerFactory.CreateLogger<PollyQoSProvider>();
RequestTimeoutSeconds = fileGlobalConfiguration.RequestTimeoutSeconds ?? 0;
}

[Obsolete("Due to new v8 policy definition in Polly 8 (use GetResiliencePipeline in PollyQoSResiliencePipelineProvider)")]
Expand Down Expand Up @@ -60,11 +69,10 @@ private PollyPolicyWrapper<HttpResponseMessage> PollyPolicyWrapperFactory(Downst

// No default set for polly timeout at the minute.
// Since a user could potentially set timeout value = 0, we need to handle this case.
// TODO throw an exception if the user sets timeout value = 0 or at least return a warning
// TODO the design in DelegatingHandlerHandlerFactory should be reviewed
var timeoutPolicy = Policy
.TimeoutAsync<HttpResponseMessage>(
TimeSpan.FromMilliseconds(route.QosOptions.TimeoutValue),
.TimeoutAsync<HttpResponseMessage>(route.QosOptions.TimeoutValue == 0
? TimeSpan.FromSeconds(RequestTimeoutSeconds)
: TimeSpan.FromMilliseconds(route.QosOptions.TimeoutValue),
TimeoutStrategy.Pessimistic);

return new PollyPolicyWrapper<HttpResponseMessage>(exceptionsAllowedBeforeBreakingPolicy, timeoutPolicy);
Expand Down
6 changes: 5 additions & 1 deletion src/Ocelot/DependencyInjection/OcelotBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ public OcelotBuilder(IServiceCollection services, IConfiguration configurationRo
Configuration = configurationRoot;
Services = services;
Services.Configure<FileConfiguration>(configurationRoot);

Services.TryAddSingleton(
sp => sp
.GetRequiredService<IOptions<FileConfiguration>>()
.Value.GlobalConfiguration);

Services.TryAddSingleton<IHttpResponseHeaderReplacer, HttpResponseHeaderReplacer>();
Services.TryAddSingleton<IHttpContextRequestHeaderReplacer, HttpContextRequestHeaderReplacer>();
Services.TryAddSingleton<IHeaderFindAndReplaceCreator, HeaderFindAndReplaceCreator>();
Expand Down
3 changes: 1 addition & 2 deletions src/Ocelot/Requester/MessageInvokerPool.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Options;
using Ocelot.Configuration;
using Ocelot.Configuration;
using Ocelot.Configuration.File;
using Ocelot.Logging;
using System.Net.Security;
Expand Down
9 changes: 5 additions & 4 deletions test/Ocelot.UnitTests/Polly/PollyQoSProviderTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
using Ocelot.Logging;
using Ocelot.Provider.Polly.v7;
using Polly;
Expand All @@ -21,7 +22,7 @@ public void Should_build()
var route = new DownstreamRouteBuilder().WithQosOptions(options)
.Build();
var factory = new Mock<IOcelotLoggerFactory>();
var pollyQoSProvider = new PollyQoSProvider(factory.Object);
var pollyQoSProvider = new PollyQoSProvider(factory.Object, new FileGlobalConfiguration());
var policy = pollyQoSProvider.GetPollyPolicyWrapper(route).ShouldNotBeNull()
.AsyncPollyPolicy.ShouldNotBeNull();
policy.ShouldNotBeNull();
Expand Down Expand Up @@ -134,7 +135,7 @@ public async Task Should_not_throw_broken_circuit_exception_if_status_code_ok()
Assert.Equal(HttpStatusCode.OK, (await pollyPolicyWrapper.AsyncPollyPolicy.ExecuteAsync(() => Task.FromResult(response))).StatusCode);
}

[Fact(Skip = "TODO", DisplayName = "TODO " + nameof(Should_throw_and_before_delay_should_not_allow_requests))]
[Fact(Skip = "TODO", DisplayName = "TODO " + nameof(Should_throw_and_before_delay_should_not_allow_requests))]
[Trait("TODO", "Fix after the release")]
public async Task Should_throw_and_before_delay_should_not_allow_requests()
{
Expand Down Expand Up @@ -212,7 +213,7 @@ private static PollyQoSProvider PollyQoSProviderFactory()
var factory = new Mock<IOcelotLoggerFactory>();
factory.Setup(x => x.CreateLogger<PollyQoSProvider>())
.Returns(new Mock<IOcelotLogger>().Object);
return new PollyQoSProvider(factory.Object);
return new PollyQoSProvider(factory.Object, new FileGlobalConfiguration());
}

private static PollyPolicyWrapper<HttpResponseMessage> PolicyWrapperFactory(string routeTemplate, PollyQoSProvider pollyQoSProvider, bool inactiveExceptionsAllowedBeforeBreaking = false)
Expand All @@ -239,4 +240,4 @@ private static PollyPolicyWrapper<HttpResponseMessage> PolicyWrapperFactory(stri

return pollyPolicyWrapper;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
using Ocelot.Logging;
using Ocelot.Provider.Polly;
using Polly.CircuitBreaker;
Expand All @@ -26,7 +27,10 @@ public void Should_build()

var loggerFactoryMock = new Mock<IOcelotLoggerFactory>();
var resiliencePipelineRegistry = new ResiliencePipelineRegistry<OcelotResiliencePipelineKey>();
var pollyQoSResiliencePipelineProvider = new PollyQoSResiliencePipelineProvider(loggerFactoryMock.Object, resiliencePipelineRegistry);
var pollyQoSResiliencePipelineProvider = new PollyQoSResiliencePipelineProvider(
loggerFactoryMock.Object,
resiliencePipelineRegistry,
new FileGlobalConfiguration());
var resiliencePipeline = pollyQoSResiliencePipelineProvider.GetResiliencePipeline(route);
resiliencePipeline.ShouldNotBeNull();
}
Expand Down Expand Up @@ -222,7 +226,10 @@ private static PollyQoSResiliencePipelineProvider PollyQoSResiliencePipelineProv
.Returns(new Mock<IOcelotLogger>().Object);
var resiliencePipelineRegistry = new ResiliencePipelineRegistry<OcelotResiliencePipelineKey>();

var pollyQoSResiliencePipelineProvider = new PollyQoSResiliencePipelineProvider(loggerFactoryMock.Object, resiliencePipelineRegistry);
var pollyQoSResiliencePipelineProvider = new PollyQoSResiliencePipelineProvider(
loggerFactoryMock.Object,
resiliencePipelineRegistry,
new FileGlobalConfiguration());
return pollyQoSResiliencePipelineProvider;
}

Expand Down

0 comments on commit 2993d4c

Please sign in to comment.