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

Added ThenAsync faulted action activity #69

Closed
wants to merge 1 commit into from
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
13 changes: 13 additions & 0 deletions src/Automatonymous.Tests/Exception_Specs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public void Should_have_called_the_async_if_block()
Assert.IsTrue(_instance.CalledThenClauseAsync);
}

[Test]
public void Should_have_called_the_async_then_block()
{
Assert.IsTrue(_instance.ThenAsyncShouldBeCalled);
}

[Test]
public void Should_have_called_the_exception_handler()
{
Expand Down Expand Up @@ -126,6 +132,8 @@ public Instance()
public bool ElseShouldBeCalled { get; set; }
public bool ThenAsyncShouldNotBeCalled { get; set; }
public bool ElseAsyncShouldBeCalled { get; set; }

public bool ThenAsyncShouldBeCalled { get; set; }
}


Expand Down Expand Up @@ -159,6 +167,11 @@ public InstanceStateMachine()
context.Instance.ExceptionMessage = context.Exception.Message;
context.Instance.ExceptionType = context.Exception.GetType();
})
.ThenAsync(context =>
{
context.Instance.ThenAsyncShouldBeCalled = true;
return Task.CompletedTask;
})
.TransitionTo(Failed))
.Catch<Exception>(ex => ex
.Then(context => context.Instance.ShouldNotBeCalled = true)));
Expand Down
97 changes: 97 additions & 0 deletions src/Automatonymous/Activities/AsyncFaultedActionActivity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
namespace Automatonymous.Activities
{
using System;
using System.Threading.Tasks;
using GreenPipes;


public class AsyncFaultedActionActivity<TInstance, TException> :
Activity<TInstance>
where TException : Exception
{
readonly Func<BehaviorExceptionContext<TInstance, TException>, Task> _asyncAction;

public AsyncFaultedActionActivity(Func<BehaviorExceptionContext<TInstance, TException>, Task> asyncAction)
{
_asyncAction = asyncAction;
}

void Visitable.Accept(StateMachineVisitor visitor)
{
visitor.Visit(this);
}

public void Probe(ProbeContext context)
{
context.CreateScope("then-async-faulted");
}

Task Activity<TInstance>.Execute(BehaviorContext<TInstance> context, Behavior<TInstance> next)
{
return next.Execute(context);
}

Task Activity<TInstance>.Execute<TData>(BehaviorContext<TInstance, TData> context, Behavior<TInstance, TData> next)
{
return next.Execute(context);
}

async Task Activity<TInstance>.Faulted<T>(BehaviorExceptionContext<TInstance, T> context, Behavior<TInstance> next)
{
var exceptionContext = context as BehaviorExceptionContext<TInstance, TException>;
if (exceptionContext != null)
await _asyncAction(exceptionContext);

await next.Faulted(context);
}

async Task Activity<TInstance>.Faulted<TData, T>(BehaviorExceptionContext<TInstance, TData, T> context,
Behavior<TInstance, TData> next)
{
var exceptionContext = context as BehaviorExceptionContext<TInstance, TData, TException>;
if (exceptionContext != null)
await _asyncAction(exceptionContext);

await next.Faulted(context);
}
}


public class AsyncFaultedActionActivity<TInstance, TData, TException> :
Activity<TInstance, TData>
where TInstance : class
where TException : Exception
{
readonly Func<BehaviorExceptionContext<TInstance, TData, TException>, Task> _asyncAction;

public AsyncFaultedActionActivity(Func<BehaviorExceptionContext<TInstance, TData, TException>, Task> asyncAction)
{
_asyncAction = asyncAction;
}

void Visitable.Accept(StateMachineVisitor visitor)
{
visitor.Visit(this);
}

public void Probe(ProbeContext context)
{
context.CreateScope("then-async-faulted");
}

Task Activity<TInstance, TData>.Execute(BehaviorContext<TInstance, TData> context, Behavior<TInstance, TData> next)
{
return next.Execute(context);
}

async Task Activity<TInstance, TData>.Faulted<T>(BehaviorExceptionContext<TInstance, TData, T> context,
Behavior<TInstance, TData> next)
{
var exceptionContext = context as BehaviorExceptionContext<TInstance, TData, TException>;
if (exceptionContext != null)
await _asyncAction(exceptionContext);

await next.Faulted(context);
}
}
}
32 changes: 32 additions & 0 deletions src/Automatonymous/ThenExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,21 @@ public static ExceptionActivityBinder<TInstance, TException> Then<TInstance, TEx
return binder.Add(new FaultedActionActivity<TInstance, TException>(action));
}

/// <summary>
/// Adds a asynchronous delegate activity to the event's behavior
/// </summary>
/// <typeparam name="TInstance">The state machine instance type</typeparam>
/// <typeparam name="TException">The exception type</typeparam>
/// <param name="binder">The event binder</param>
/// <param name="asyncAction">The asynchronous delegate</param>
public static ExceptionActivityBinder<TInstance, TException> ThenAsync<TInstance, TException>(
this ExceptionActivityBinder<TInstance, TException> binder, Func<BehaviorExceptionContext<TInstance, TException>, Task> asyncAction)
where TInstance : class
where TException : Exception
{
return binder.Add(new AsyncFaultedActionActivity<TInstance, TException>(asyncAction));
}

/// <summary>
/// Adds an asynchronous delegate activity to the event's behavior
/// </summary>
Expand Down Expand Up @@ -80,6 +95,23 @@ public static ExceptionActivityBinder<TInstance, TData, TException> Then<TInstan
return binder.Add(new FaultedActionActivity<TInstance, TData, TException>(action));
}

/// <summary>
/// Adds a asynchronous delegate activity to the event's behavior
/// </summary>
/// <typeparam name="TInstance">The state machine instance type</typeparam>
/// <typeparam name="TException">The exception type</typeparam>
/// <typeparam name="TData">The event data type</typeparam>
/// <param name="binder">The event binder</param>
/// <param name="asyncAction">The asynchronous delegate</param>
public static ExceptionActivityBinder<TInstance, TData, TException> ThenAsync<TInstance, TData, TException>(
this ExceptionActivityBinder<TInstance, TData, TException> binder,
Func<BehaviorExceptionContext<TInstance, TData, TException>, Task> asyncAction)
where TInstance : class
where TException : Exception
{
return binder.Add(new AsyncFaultedActionActivity<TInstance, TData, TException>(asyncAction));
}

/// <summary>
/// Adds an asynchronous delegate activity to the event's behavior
/// </summary>
Expand Down