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

Interrupt execution #51

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions src/Voxel.MiddyNet.HttpCorsMiddleware/HttpCorsMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public HttpCorsMiddleware(CorsOptions corsOptions)
this.corsOptions = corsOptions;
}

public bool InterruptsExecution => false;

private const string DefaultAccessControlAllowOrigin = "*";
private const string AllowOriginHeader = "Access-Control-Allow-Origin";
private const string AllowHeadersHeader = "Access-Control-Allow-Headers";
Expand Down
2 changes: 2 additions & 0 deletions src/Voxel.MiddyNet.HttpCorsMiddleware/HttpV2CorsMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public HttpV2CorsMiddleware(CorsOptions corsOptions)
this.corsOptions = corsOptions;
}

public bool InterruptsExecution => false;

private const string DefaultAccessControlAllowOrigin = "*";
private const string AllowOriginHeader = "Access-Control-Allow-Origin";
private const string AllowHeadersHeader = "Access-Control-Allow-Headers";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ public abstract class HttpJsonBodyParserMiddleware
}
public class HttpJsonBodyParserMiddleware<T> : HttpJsonBodyParserMiddleware, ILambdaMiddleware<APIGatewayProxyRequest, APIGatewayProxyResponse> where T : new()
{

public HttpJsonBodyParserMiddleware(bool interruptsExecution)
{
InterruptsExecution = interruptsExecution;
}

public HttpJsonBodyParserMiddleware() : this(false){}

public bool InterruptsExecution { get; }

public Task Before(APIGatewayProxyRequest lambdaEvent, MiddyNetContext context)
{
if (!HasJsonContentHeaders(lambdaEvent))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ namespace Voxel.MiddyNet.HttpJsonMiddleware
{
public class HttpV2JsonBodyParserMiddleware<T> : HttpJsonBodyParserMiddleware, ILambdaMiddleware<APIGatewayHttpApiV2ProxyRequest, APIGatewayHttpApiV2ProxyResponse>
{
public HttpV2JsonBodyParserMiddleware(bool interruptsExecution)
{
InterruptsExecution = interruptsExecution;
}

public HttpV2JsonBodyParserMiddleware() : this(false) { }

public bool InterruptsExecution { get; }

public Task Before(APIGatewayHttpApiV2ProxyRequest lambdaEvent, MiddyNetContext context)
{
if (!HasJsonContentHeaders(lambdaEvent))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class ProblemDetailsMiddleware : ILambdaMiddleware<APIGatewayProxyRequest
public ProblemDetailsMiddleware(ProblemDetailsMiddlewareOptions options = null) =>
this.options = options ?? new ProblemDetailsMiddlewareOptions();

public bool InterruptsExecution => false;

public Task Before(APIGatewayProxyRequest lambdaEvent, MiddyNetContext context) => Task.CompletedTask;

public Task<APIGatewayProxyResponse> After(APIGatewayProxyResponse lambdaResponse, MiddyNetContext context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class ProblemDetailsMiddlewareV2 : ILambdaMiddleware<APIGatewayHttpApiV2P
public ProblemDetailsMiddlewareV2(ProblemDetailsMiddlewareOptions options = null) =>
this.options = options ?? new ProblemDetailsMiddlewareOptions();

public bool InterruptsExecution => false;

public Task Before(APIGatewayHttpApiV2ProxyRequest lambdaEvent, MiddyNetContext context) => Task.CompletedTask;

public Task<APIGatewayHttpApiV2ProxyResponse> After(APIGatewayHttpApiV2ProxyResponse lambdaResponse, MiddyNetContext context)
Expand Down
2 changes: 2 additions & 0 deletions src/Voxel.MiddyNet.SSMMiddleware/SSMMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public SSMMiddleware(SSMOptions ssmOptions, Func<IAmazonSimpleSystemsManagement>
this.timeProvider = timeProvider;
}

public bool InterruptsExecution => false;

public async Task Before(TReq lambdaEvent, MiddyNetContext context)
{
foreach (var parameter in ssmOptions.ParametersToGet)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class ApiGatewayHttpApiV2TracingMiddleware : ILambdaMiddleware<APIGateway

public static string TraceContextKey = "TraceContext";

public bool InterruptsExecution => false;

public Task Before(APIGatewayHttpApiV2ProxyRequest apiGatewayEvent, MiddyNetContext context)
{
var traceParentHeaderValue = string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class ApiGatewayTracingMiddleware : ILambdaMiddleware<APIGatewayProxyRequ

public static string TraceContextKey = "TraceContext";

public bool InterruptsExecution => false;

public Task Before(APIGatewayProxyRequest apiGatewayEvent, MiddyNetContext context)
{
var traceParentHeaderValue = string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public class SNSTracingMiddleware<TRes> : ILambdaMiddleware<SNSEvent, TRes>
private const string TraceStateHeaderName = "tracestate";
private const string TraceIdHeaderName = "trace-id";

public bool InterruptsExecution => false;

public Task Before(SNSEvent snsEvent, MiddyNetContext context)
{
var snsMessage = snsEvent.Records.First().Sns;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public class SQSTracingMiddleware<TRes> : ILambdaMiddleware<SQSEvent, TRes>
private const string TraceStateHeaderName = "tracestate";
private const string TraceIdHeaderName = "trace-id";

public bool InterruptsExecution => false;

public Task Before(SQSEvent sqsEvent, MiddyNetContext context)
{
var sqsMessage = sqsEvent.Records.First();
Expand Down
2 changes: 2 additions & 0 deletions src/Voxel.MiddyNet/ILambdaMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ public interface ILambdaMiddleware<in TReq, TRes>
Task Before(TReq lambdaEvent, MiddyNetContext context);

Task<TRes> After(TRes lambdaResponse, MiddyNetContext context);

bool InterruptsExecution { get; }
}
}
14 changes: 11 additions & 3 deletions src/Voxel.MiddyNet/MiddyNet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ public async Task<TRes> Handler(TReq lambdaEvent, ILambdaContext context)
{
InitialiseMiddyContext(context);

await ExecuteBeforeMiddlewares(lambdaEvent);
var beforeMiddlewaresExecutedWithoutErrors = await ExecuteBeforeMiddlewares(lambdaEvent);

var response = await SafeHandleLambdaEvent(lambdaEvent).ConfigureAwait(false);
var response = default(TRes);

if (beforeMiddlewaresExecutedWithoutErrors)
{
response = await SafeHandleLambdaEvent(lambdaEvent).ConfigureAwait(false);
}

response = await ExecuteAfterMiddlewares(response);

Expand Down Expand Up @@ -66,7 +71,7 @@ private async Task<TRes> ExecuteAfterMiddlewares(TRes response)
return response;
}

private async Task ExecuteBeforeMiddlewares(TReq lambdaEvent)
private async Task<bool> ExecuteBeforeMiddlewares(TReq lambdaEvent)
{
foreach (var middleware in middlewares)
{
Expand All @@ -77,8 +82,11 @@ private async Task ExecuteBeforeMiddlewares(TReq lambdaEvent)
catch (Exception ex)
{
MiddyContext.MiddlewareBeforeExceptions.Add(ex);
if (middleware.InterruptsExecution) return false;
}
}

return true;
}

private void InitialiseMiddyContext(ILambdaContext context)
Expand Down
44 changes: 38 additions & 6 deletions test/Voxel.MiddyNet.Tests/MiddyNetShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ public class TestLambdaFunction : MiddyNet<int, int>
{
private readonly bool withFailingHandler;

public TestLambdaFunction(List<string> logLines, List<string> contextLogLines, int numberOfMiddlewares, bool withFailingMiddleware = false, bool withFailingHandler = false)
: this(logLines, contextLogLines, numberOfMiddlewares, withFailingMiddleware, withFailingMiddleware, withFailingHandler) { }
public TestLambdaFunction(List<string> logLines, List<string> contextLogLines, int numberOfMiddlewares, bool withFailingMiddleware = false, bool withFailingHandler = false, bool withInterruptingMiddleware = false)
: this(logLines, contextLogLines, numberOfMiddlewares, withFailingMiddleware, withFailingMiddleware, withFailingHandler, withInterruptingMiddleware) { }

public TestLambdaFunction(List<string> logLines, List<string> contextLogLines, int numberOfMiddlewares, bool withFailingBeforeMiddleware, bool withFailingAfterMiddleware, bool withFailingHandler)
public TestLambdaFunction(List<string> logLines, List<string> contextLogLines, int numberOfMiddlewares, bool withFailingBeforeMiddleware, bool withFailingAfterMiddleware, bool withFailingHandler, bool withInterruptingMiddleware)

{
LogLines = logLines;
ContextLogLines = contextLogLines;
for (var i = 0; i < numberOfMiddlewares; i++)
{
Use(new TestBeforeMiddleware(logLines, i + 1, withFailingBeforeMiddleware));
Use(new TestBeforeMiddleware(logLines, i + 1, withFailingBeforeMiddleware, withInterruptingMiddleware));
Use(new TestAfterMiddleware(logLines, i + 1, withFailingAfterMiddleware));
}

Expand Down Expand Up @@ -62,12 +62,16 @@ public class MiddlewareException : Exception { }
public class TestBeforeMiddleware : ILambdaMiddleware<int, int>
{
private readonly int position;
private readonly bool interrupts = false;
public List<string> LogLines { get; }
public bool Failing { get; }

public TestBeforeMiddleware(List<string> logLines, int position, bool failing)
public bool InterruptsExecution => interrupts;

public TestBeforeMiddleware(List<string> logLines, int position, bool failing, bool interrupts)
{
this.position = position;
this.interrupts = interrupts;
LogLines = logLines;
Failing = failing;
}
Expand All @@ -94,6 +98,8 @@ public class TestAfterMiddleware : ILambdaMiddleware<int, int>
public List<string> LogLines { get; }
public bool Failing { get; }

public bool InterruptsExecution => false;

public TestAfterMiddleware(List<string> logLines, int position, bool failing)
{
this.position = position;
Expand Down Expand Up @@ -205,7 +211,7 @@ public void IncludeHandlerExceptionOnAfterErrorNotifications(int numberOfMiddlew
[InlineData(false, false, true)]
public void ThrowSpecificExceptionWhenOnlyOnePresent(bool throwBeforeException, bool throwAfterException, bool throwHandlerException)
{
var lambdaFunction = new TestLambdaFunction(logLines, contextLines, 1, throwBeforeException, throwAfterException, throwHandlerException);
var lambdaFunction = new TestLambdaFunction(logLines, contextLines, 1, throwBeforeException, throwAfterException, throwHandlerException, false);
Func<Task> act = async () => await lambdaFunction.Handler(0, new FakeLambdaContext());

act.Should().NotThrow<AggregateException>();
Expand All @@ -223,6 +229,30 @@ public async Task LetMiddlewaresChangeTheFunctionResult()
result.Should().Be(9);
}

[Fact]
public void StopEvaluatingBeforeMiddlewaresIfInterruptExecutionSetToTrueAndExceptionHappens()
{
var lambdaFunction = new TestLambdaFunction(logLines, contextLines, 2, true, false, true);
Func<Task> act = async () => await lambdaFunction.Handler(0, new FakeLambdaContext());

act.Should().Throw<MiddlewareException>();

logLines.Should().Contain($"{MiddlewareBeforeLog}-1");
logLines.Should().NotContain($"{MiddlewareBeforeLog}-2");

}

[Fact]
public void NotExecuteLambdaIfInterruptExecutionSetToTrueAndExceptionHappens()
{
var lambdaFunction = new TestLambdaFunction(logLines, contextLines, 2, true, false, true);
Func<Task> act = async () => await lambdaFunction.Handler(0, new FakeLambdaContext());

act.Should().Throw<MiddlewareException>();
logLines.Should().NotContain(FunctionLog);

}

private class AddsTwo : MiddyNet<int, int>
{
protected override Task<int> Handle(int lambdaEvent, MiddyNetContext context)
Expand All @@ -233,6 +263,8 @@ protected override Task<int> Handle(int lambdaEvent, MiddyNetContext context)

private class SquareIt : ILambdaMiddleware<int, int>
{
public bool InterruptsExecution => false;

public Task<int> After(int lambdaResponse, MiddyNetContext context)
{
return Task.FromResult(lambdaResponse * lambdaResponse);
Expand Down