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

Issue 38 httpclientsettings refactoring #42

Closed
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ public class CircuitBreakerTests
public void Should_break_after_4_concurrent_calls()
{
const int minimumThroughput = 2;
var retrySettings = new SimpleRetrySettings(
retryCount: 5,
sleepDurationProvider: i => TimeSpan.FromMilliseconds(50));
var retrySettings = new SimpleRetrySettings
{
RetryCount = 5,
SleepDurationProvider = i => TimeSpan.FromMilliseconds(50)
};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithStatusCode(HttpStatusCode.ServiceUnavailable)
.WithTimeoutOverall(TimeSpan.FromSeconds(5))
Expand All @@ -37,9 +39,11 @@ public void Should_break_after_4_concurrent_calls()
public async Task Should_Open_Circuit_Breaker_for_RU_and_do_not_affect_EE()
{
const int minimumThroughput = 2;
var retrySettings = new SimpleRetrySettings(
retryCount: 5,
sleepDurationProvider: i => TimeSpan.FromMilliseconds(50));
var retrySettings = new SimpleRetrySettings
{
RetryCount = 5,
SleepDurationProvider = i => TimeSpan.FromMilliseconds(50)
};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithHostAndStatusCode("ru-prod.com", HttpStatusCode.ServiceUnavailable)
.WithHostAndStatusCode("ee-prod.com", HttpStatusCode.OK)
Expand All @@ -61,11 +65,13 @@ await Helper.InvokeMultipleHttpRequests(wrapper.Client, taskCount,

private static ICircuitBreakerSettings BuildCircuitBreakerSettings(int throughput)
{
return new CircuitBreakerSettings.CircuitBreakerSettings(
failureThreshold: 0.5,
minimumThroughput: throughput,
durationOfBreak: TimeSpan.FromMinutes(1),
samplingDuration: TimeSpan.FromMilliseconds(20));
return new CircuitBreakerSettings.CircuitBreakerSettings
{
FailureThreshold = 0.5,
MinimumThroughput = throughput,
DurationOfBreak = TimeSpan.FromMinutes(1),
SamplingDuration = TimeSpan.FromMilliseconds(20)
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Dodo.HttpClientResiliencePolicies.CircuitBreakerSettings;
using Dodo.HttpClientResiliencePolicies.RetrySettings;
using Dodo.HttpClientResiliencePolicies.Tests.Fakes;
using Dodo.HttpClientResiliencePolicies.TimeoutPolicySettings;
using Microsoft.Extensions.DependencyInjection;

namespace Dodo.HttpClientResiliencePolicies.Tests.DSL
Expand Down Expand Up @@ -93,20 +94,24 @@ public HttpClientWrapper PleaseHostSpecific()
return new HttpClientWrapper(client, handler);
}

private HttpClientSettings BuildClientSettings()
private ResiliencePoliciesSettings BuildClientSettings()
{
var defaultCircuitBreakerSettings = _circuitBreakerSettings ?? new CircuitBreakerSettings.CircuitBreakerSettings(
failureThreshold: 0.5,
minimumThroughput: int.MaxValue,
durationOfBreak: TimeSpan.FromMilliseconds(1),
samplingDuration: TimeSpan.FromMilliseconds(20)
);
var defaultCircuitBreakerSettings = _circuitBreakerSettings ??
new CircuitBreakerSettings.CircuitBreakerSettings
{
FailureThreshold = 0.5,
MinimumThroughput = int.MaxValue,
DurationOfBreak = TimeSpan.FromMilliseconds(1),
SamplingDuration = TimeSpan.FromMilliseconds(20)
};

return new HttpClientSettings(
timeoutOverall: _timeoutOverall,
timeoutPerTry: _timeoutPerTry,
retrySettings: _retrySettings ?? JitterRetrySettings.Default(),
circuitBreakerSettings: defaultCircuitBreakerSettings);
return new ResiliencePoliciesSettings
{
OverallTimeoutPolicySettings = new OverallTimeoutPolicySettings{Timeout = _timeoutOverall},
TimeoutPerTryPolicySettings = new TimeoutPerTryPolicySettings{Timeout = _timeoutPerTry},
RetrySettings = _retrySettings ?? new JitterRetrySettings(),
CircuitBreakerSettings = defaultCircuitBreakerSettings
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void AddJsonClient_WithNullClientName_ConfiguresDefaultJsonClient()
// Act1
serviceCollection.AddJsonClient<IMockJsonClient, MockJsonClient>(
new Uri("http://example.com/"),
HttpClientSettings.Default());
new ResiliencePoliciesSettings());

var services = serviceCollection.BuildServiceProvider();

Expand All @@ -41,7 +41,7 @@ public void AddJsonClient_WithSpecificClientName_ConfiguresSpecificJsonClient()
// Act1
serviceCollection.AddJsonClient<IMockJsonClient, MockJsonClient>(
new Uri("http://example.com/"),
HttpClientSettings.Default(),
new ResiliencePoliciesSettings(),
"specificName");

var services = serviceCollection.BuildServiceProvider();
Expand Down
20 changes: 13 additions & 7 deletions src/Dodo.HttpClient.ResiliencePolicies.Tests/RetryPolicyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class RetryPolicyTests
public async Task Should_retry_3_times_when_client_returns_503()
{
const int retryCount = 3;
var retrySettings = new SimpleRetrySettings(retryCount);
var retrySettings = new SimpleRetrySettings {RetryCount = retryCount};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithStatusCode(HttpStatusCode.ServiceUnavailable)
.WithRetrySettings(retrySettings)
Expand All @@ -35,7 +35,11 @@ public async Task Should_retry_6_times_for_two_threads_when_client_returns_503()
{
const int retryCount = 3;
var retrySettings =
new JitterRetrySettings(retryCount, medianFirstRetryDelay: TimeSpan.FromMilliseconds(50));
new JitterRetrySettings
{
RetryCount = retryCount,
SleepDurationProvider = JitterRetrySettings._defaultSleepDurationProvider(retryCount, TimeSpan.FromMilliseconds(50))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not the same logic here as it was before. Actually we should fill absent MedianFirstRetryDelay and do not set SleepDurationProvider at all, because JutterRetrySettings will take correct provider by default. We should discuss it.

};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithStatusCode(HttpStatusCode.ServiceUnavailable)
.WithRetrySettings(retrySettings)
Expand All @@ -52,10 +56,12 @@ public async Task Should_separately_distribute_retry_attempts_for_multiple_tasks
{
const int retryCount = 3;
var retryAttempts = new Dictionary<string, List<TimeSpan>>();
var retrySettings = new JitterRetrySettings(
retryCount,
medianFirstRetryDelay: TimeSpan.FromMilliseconds(50),
onRetry: BuildOnRetryAction(retryAttempts));
var retrySettings = new JitterRetrySettings
{
RetryCount = retryCount,
SleepDurationProvider = JitterRetrySettings._defaultSleepDurationProvider(retryCount, TimeSpan.FromMilliseconds(50)),
OnRetry = BuildOnRetryAction(retryAttempts)
};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithStatusCode(HttpStatusCode.ServiceUnavailable)
.WithRetrySettings(retrySettings)
Expand All @@ -71,7 +77,7 @@ public async Task Should_separately_distribute_retry_attempts_for_multiple_tasks
public async Task Should_retry_when_client_returns_500()
{
const int retryCount = 3;
var retrySettings = new SimpleRetrySettings(retryCount);
var retrySettings = new SimpleRetrySettings{RetryCount = retryCount};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithStatusCode(HttpStatusCode.InternalServerError)
.WithRetrySettings(retrySettings)
Expand Down
34 changes: 21 additions & 13 deletions src/Dodo.HttpClient.ResiliencePolicies.Tests/TimeoutPolicyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ public class TimeoutPolicyTests
public void Should_retry_5_times_200_status_code_because_of_per_try_timeout()
{
const int retryCount = 5;
var retrySettings = new SimpleRetrySettings(
retryCount,
sleepDurationProvider: i => TimeSpan.FromMilliseconds(200));
var retrySettings = new SimpleRetrySettings
{
RetryCount = retryCount,
SleepDurationProvider = i => TimeSpan.FromMilliseconds(200)
};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithStatusCode(HttpStatusCode.OK)
.WithResponseLatency(TimeSpan.FromMilliseconds(200))
Expand Down Expand Up @@ -50,9 +52,11 @@ public void Should_fail_on_HttpClient_timeout()
public void Should_fail_on_HttpClient_timeout_with_retry()
{
const int retryCount = 5;
var retrySettings = new SimpleRetrySettings(
retryCount,
sleepDurationProvider: i => TimeSpan.FromMilliseconds(1));
var retrySettings = new SimpleRetrySettings
{
RetryCount = retryCount,
SleepDurationProvider = i => TimeSpan.FromMilliseconds(1)
};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithStatusCode(HttpStatusCode.ServiceUnavailable)
.WithResponseLatency(TimeSpan.FromMilliseconds(50))
Expand Down Expand Up @@ -85,9 +89,11 @@ public void Should_catchTimeout_1_times_because_of_overall_timeout_less_than_per
var overallTimeout = TimeSpan.FromMilliseconds(100);
var perTryTimeout = TimeSpan.FromMilliseconds(200);

var retrySettings = new SimpleRetrySettings(
5,
sleepDurationProvider: i => TimeSpan.FromMilliseconds(200));
var retrySettings = new SimpleRetrySettings
{
RetryCount = 5,
SleepDurationProvider=i => TimeSpan.FromMilliseconds(200)
};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithStatusCode(HttpStatusCode.OK)
.WithResponseLatency(TimeSpan.FromMilliseconds(300))
Expand All @@ -108,10 +114,12 @@ public void When_overall_timeout_greated_than_summ_perTrials_Should_retry_5_time
const int retryCount = 5;
var perTryTimeout = TimeSpan.FromMilliseconds(100);
var overallTimeout = TimeSpan.FromSeconds(2);

var retrySettings = new SimpleRetrySettings(
retryCount,
sleepDurationProvider: i => TimeSpan.FromMilliseconds(200));

var retrySettings = new SimpleRetrySettings
{
RetryCount = retryCount,
SleepDurationProvider = i => TimeSpan.FromMilliseconds(200)
};
var wrapper = Create.HttpClientWrapperWrapperBuilder
.WithStatusCode(HttpStatusCode.OK)
.WithResponseLatency(TimeSpan.FromMilliseconds(200))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,34 @@ namespace Dodo.HttpClientResiliencePolicies.CircuitBreakerSettings
{
public class CircuitBreakerSettings : ICircuitBreakerSettings
{
public double FailureThreshold { get; }
public int MinimumThroughput { get; }
public TimeSpan DurationOfBreak { get; }
public TimeSpan SamplingDuration { get; }
public Action<DelegateResult<HttpResponseMessage>, TimeSpan> OnBreak { get; set; }
public Action OnReset { get; set; }
public Action OnHalfOpen { get; set; }

public CircuitBreakerSettings(
double failureThreshold,
int minimumThroughput,
TimeSpan durationOfBreak,
TimeSpan samplingDuration) : this(failureThreshold, minimumThroughput, durationOfBreak, samplingDuration,
_defaultOnBreak, _defaultOnReset, _defaultOnHalfOpen)
public CircuitBreakerSettings()
DashaBulanova marked this conversation as resolved.
Show resolved Hide resolved
{
}
FailureThreshold = Defaults.CircuitBreaker.FailureThreshold;
MinimumThroughput = Defaults.CircuitBreaker.MinimumThroughput;
DurationOfBreak = TimeSpan.FromMilliseconds(Defaults.CircuitBreaker.DurationOfBreakInMilliseconds);
SamplingDuration = TimeSpan.FromMilliseconds(Defaults.CircuitBreaker.SamplingDurationInMilliseconds);

public CircuitBreakerSettings(
double failureThreshold,
int minimumThroughput,
TimeSpan durationOfBreak,
TimeSpan samplingDuration,
Action<DelegateResult<HttpResponseMessage>, TimeSpan> onBreak,
Action onReset,
Action onHalfOpen)
{
FailureThreshold = failureThreshold;
MinimumThroughput = minimumThroughput;
DurationOfBreak = durationOfBreak;
SamplingDuration = samplingDuration;
OnBreak = onBreak;
OnReset = onReset;
OnHalfOpen = onHalfOpen;
OnBreak = _doNothingOnBreak;
OnReset = _doNothingOnReset;
OnHalfOpen = _doNothingOnHalfOpen;
}

public static ICircuitBreakerSettings Default() =>
new CircuitBreakerSettings(
Defaults.CircuitBreaker.FailureThreshold,
Defaults.CircuitBreaker.MinimumThroughput,
TimeSpan.FromMilliseconds(Defaults.CircuitBreaker.DurationOfBreakInMilliseconds),
TimeSpan.FromMilliseconds(Defaults.CircuitBreaker.SamplingDurationInMilliseconds)
);

private static readonly Action<DelegateResult<HttpResponseMessage>, TimeSpan> _defaultOnBreak = (_, __) => { };
private static readonly Action _defaultOnReset = () => { };
private static readonly Action _defaultOnHalfOpen = () => { };
public double FailureThreshold { get; set; }

public int MinimumThroughput { get; set; }

public TimeSpan DurationOfBreak { get; set; }

public TimeSpan SamplingDuration { get; set; }

public Action<DelegateResult<HttpResponseMessage>, TimeSpan> OnBreak { get; set; }

public Action OnReset { get; set; }

public Action OnHalfOpen { get; set; }

private static readonly Action<DelegateResult<HttpResponseMessage>, TimeSpan> _doNothingOnBreak = (_, __) => { };
private static readonly Action _doNothingOnReset = () => { };
private static readonly Action _doNothingOnHalfOpen = () => { };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ namespace Dodo.HttpClientResiliencePolicies.CircuitBreakerSettings
{
public interface ICircuitBreakerSettings
{
double FailureThreshold { get; }
int MinimumThroughput { get; }
TimeSpan DurationOfBreak { get; }
TimeSpan SamplingDuration { get; }
double FailureThreshold { get; set; }
int MinimumThroughput { get; set; }
TimeSpan DurationOfBreak { get; set; }
TimeSpan SamplingDuration { get; set; }
Action<DelegateResult<HttpResponseMessage>, TimeSpan> OnBreak { get; set; }
Action OnReset { get; set; }
Action OnHalfOpen { get; set; }
Expand Down
Loading