added docs but qos acceptance test not working seems circuit never opens but not sure if it is meant to with timeouts..investigating

This commit is contained in:
TomPallister
2017-02-11 15:11:10 +00:00
parent ce8da4c92d
commit 820673dda8
10 changed files with 235 additions and 31 deletions

View File

@ -8,7 +8,11 @@ namespace Ocelot.Configuration
{
public class QoSOptions
{
public QoSOptions(int exceptionsAllowedBeforeBreaking, int durationofBreak, int timeoutValue, TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
public QoSOptions(
int exceptionsAllowedBeforeBreaking,
int durationofBreak,
int timeoutValue,
TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
{
ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
DurationOfBreak = TimeSpan.FromMilliseconds(durationofBreak);

View File

@ -25,6 +25,7 @@
ServicesAreNullError,
ServicesAreEmptyError,
UnableToFindServiceDiscoveryProviderError,
UnableToFindLoadBalancerError
UnableToFindLoadBalancerError,
RequestTimedOutError
}
}

View File

@ -18,11 +18,17 @@ namespace Ocelot.Requester
private readonly Policy _circuitBreakerPolicy;
private readonly TimeoutPolicy _timeoutPolicy;
public CircuitBreakingDelegatingHandler(int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak,TimeSpan timeoutValue
,TimeoutStrategy timeoutStrategy, IOcelotLogger logger, HttpMessageHandler innerHandler)
public CircuitBreakingDelegatingHandler(
int exceptionsAllowedBeforeBreaking,
TimeSpan durationOfBreak,
TimeSpan timeoutValue,
TimeoutStrategy timeoutStrategy,
IOcelotLogger logger,
HttpMessageHandler innerHandler)
: base(innerHandler)
{
this._exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
this._durationOfBreak = durationOfBreak;
_circuitBreakerPolicy = Policy
@ -39,30 +45,27 @@ namespace Ocelot.Requester
onReset: () => _logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again."),
onHalfOpen: () => _logger.LogDebug(".Breaker logging: Half-open; next call is a trial.")
);
_timeoutPolicy = Policy.TimeoutAsync(timeoutValue, timeoutStrategy);
_logger = logger;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Task<HttpResponseMessage> responseTask = null;
try
{
responseTask = Policy.WrapAsync(_circuitBreakerPolicy, _timeoutPolicy).ExecuteAsync<HttpResponseMessage>(() =>
{
return base.SendAsync(request,cancellationToken);
});
return responseTask;
return await Policy.WrapAsync(_circuitBreakerPolicy, _timeoutPolicy).ExecuteAsync(() => base.SendAsync(request,cancellationToken));
}
catch (BrokenCircuitException ex)
{
_logger.LogError($"Reached to allowed number of exceptions. Circuit is open. AllowedExceptionCount: {_exceptionsAllowedBeforeBreaking}, DurationOfBreak: {_durationOfBreak}",ex);
throw;
}
catch (HttpRequestException)
catch (HttpRequestException ex)
{
return responseTask;
_logger.LogError($"Error in CircuitBreakingDelegatingHandler.SendAync", ex);
throw;
}
}

View File

@ -27,6 +27,7 @@ namespace Ocelot.Requester
{
builder.WithCircuitBreaker(request.Qos, _logger, handler);
}
using (var httpClient = builder.Build(handler))
{
try
@ -34,13 +35,14 @@ namespace Ocelot.Requester
var response = await httpClient.SendAsync(request.HttpRequestMessage);
return new OkResponse<HttpResponseMessage>(response);
}
catch (Exception exception)
catch (Polly.Timeout.TimeoutRejectedException exception)
{
return
new ErrorResponse<HttpResponseMessage>(new List<Error>
{
new UnableToCompleteRequestError(exception)
});
new ErrorResponse<HttpResponseMessage>(new RequestTimedOutError(exception));
}
catch (Exception exception)
{
return new ErrorResponse<HttpResponseMessage>(new UnableToCompleteRequestError(exception));
}
}
}

View File

@ -0,0 +1,13 @@
using System;
using Ocelot.Errors;
namespace Ocelot.Requester
{
public class RequestTimedOutError : Error
{
public RequestTimedOutError(Exception exception)
: base($"Timeout making http request, exception: {exception.Message}", OcelotErrorCode.RequestTimedOutError)
{
}
}
}

View File

@ -22,6 +22,11 @@ namespace Ocelot.Responder
return new OkResponse<int>(403);
}
if (errors.Any(e => e.Code == OcelotErrorCode.RequestTimedOutError))
{
return new OkResponse<int>(408);
}
return new OkResponse<int>(404);
}
}

View File

@ -5,7 +5,13 @@ namespace Ocelot.Responses
{
public class ErrorResponse<T> : Response<T>
{
public ErrorResponse(List<Error> errors) : base(errors)
public ErrorResponse(Error error)
: base(new List<Error> {error})
{
}
public ErrorResponse(List<Error> errors)
: base(errors)
{
}
}