Skip to content

Commit

Permalink
Make Transition Actions Async-First
Browse files Browse the repository at this point in the history
  • Loading branch information
Pentiva committed Sep 2, 2022
1 parent 8029b18 commit eb1bec5
Show file tree
Hide file tree
Showing 20 changed files with 655 additions and 795 deletions.
63 changes: 17 additions & 46 deletions src/Stateless/ActivateActionBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,34 @@ namespace Stateless;

public partial class StateMachine<TState, TTrigger>
{
internal abstract class ActivateActionBehaviour
internal class ActivateActionBehaviour
{
private readonly TState _state;
private readonly TState _state;

private ActivateActionBehaviour(TState state, InvocationInfo actionDescription)
{
_state = state;
Description = actionDescription ?? throw new ArgumentNullException(nameof(actionDescription));
}
private readonly EventCallback _callback = EventCallbackFactory.Empty;

internal InvocationInfo Description { get; }

public abstract void Execute();
public abstract Task ExecuteAsync();
public ActivateActionBehaviour(TState state, Action action, InvocationInfo actionDescription)
: this(state, actionDescription) {
_callback = EventCallbackFactory.Create(action);
}

public class Sync : ActivateActionBehaviour
public ActivateActionBehaviour(TState state, Func<Task> action, InvocationInfo actionDescription)
: this(state, actionDescription)
{
private readonly Action _action;

public Sync(TState state, Action action, InvocationInfo actionDescription)
: base(state, actionDescription)
{
_action = action;
}

public override void Execute()
{
_action();
}

public override Task ExecuteAsync()
{
Execute();
return TaskResult.Done;
}
_callback = EventCallbackFactory.Create(action);
}

public class Async : ActivateActionBehaviour
protected ActivateActionBehaviour(TState state, InvocationInfo actionDescription)
{
private readonly Func<Task> _action;

public Async(TState state, Func<Task> action, InvocationInfo actionDescription)
: base(state, actionDescription)
{
_action = action;
}

public override void Execute()
{
throw new InvalidOperationException(
$"Cannot execute asynchronous action specified in OnActivateAsync for '{_state}' state. Use asynchronous version of Activate [ActivateAsync]");
}
_state = state;
Description = actionDescription ?? throw new ArgumentNullException(nameof(actionDescription));
}

public override Task ExecuteAsync()
{
return _action();
}
public virtual Task ExecuteAsync()
{
return _callback.InvokeAsync();
}
}
}
66 changes: 19 additions & 47 deletions src/Stateless/DeactivateActionBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,35 @@ namespace Stateless;

public partial class StateMachine<TState, TTrigger>
{
internal abstract class DeactivateActionBehaviour
internal class DeactivateActionBehaviour
{
private readonly TState _state;

private DeactivateActionBehaviour(TState state, InvocationInfo actionDescription)
{
_state = state;
Description = actionDescription ?? throw new ArgumentNullException(nameof(actionDescription));
}
private readonly TState _state;

private readonly EventCallback _callback = EventCallbackFactory.Empty;

internal InvocationInfo Description { get; }

public abstract void Execute();
public abstract Task ExecuteAsync();
public DeactivateActionBehaviour(TState state, Action action, InvocationInfo actionDescription)
: this(state, actionDescription) {
_callback = EventCallbackFactory.Create(action);
}

public class Sync : DeactivateActionBehaviour
public DeactivateActionBehaviour(TState state, Func<Task> action, InvocationInfo actionDescription)
: this(state, actionDescription)
{
private readonly Action _action;

public Sync(TState state, Action action, InvocationInfo actionDescription)
: base(state, actionDescription)
{
_action = action;
}

public override void Execute()
{
_action();
}

public override Task ExecuteAsync()
{
Execute();
return TaskResult.Done;
}
_callback = EventCallbackFactory.Create(action);
}

public class Async : DeactivateActionBehaviour
protected DeactivateActionBehaviour(TState state, InvocationInfo actionDescription)
{
private readonly Func<Task> _action;

public Async(TState state, Func<Task> action, InvocationInfo actionDescription)
: base(state, actionDescription)
{
_action = action;
}

public override void Execute()
{
throw new InvalidOperationException(
$"Cannot execute asynchronous action specified in OnDeactivateAsync for '{_state}' state. Use asynchronous version of Deactivate [DeactivateAsync]");
}
_state = state;
Description = actionDescription ?? throw new ArgumentNullException(nameof(actionDescription));
}

public override Task ExecuteAsync()
{
return _action();
}
public virtual Task ExecuteAsync()
{
return _callback.InvokeAsync();
}

}
}
75 changes: 25 additions & 50 deletions src/Stateless/EntryActionBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,81 +4,56 @@ namespace Stateless;

public partial class StateMachine<TState, TTrigger>
{
internal abstract class EntryActionBehavior
internal class EntryActionBehavior
{
private EntryActionBehavior(InvocationInfo description)
private readonly EventCallback<Transition, object?[]> _callback = EventCallbackFactory.Create<Transition, object?[]>(delegate { });

public EntryActionBehavior(Action<Transition, object?[]> action, InvocationInfo description)
: this(description)
{
Description = description;
_callback = EventCallbackFactory.Create(action);
}

public InvocationInfo Description { get; }

public abstract void Execute(Transition transition, object?[] args);
public abstract Task ExecuteAsync(Transition transition, object?[] args);

public class Sync : EntryActionBehavior
public EntryActionBehavior(Func<Transition, object?[], Task> action, InvocationInfo description)
: this(description)
{
private readonly Action<Transition, object?[]> _action;
_callback = EventCallbackFactory.Create(action);
}

public Sync(Action<Transition, object?[]> action, InvocationInfo description) : base(description)
{
_action = action;
}
protected EntryActionBehavior(InvocationInfo description)
{
Description = description;
}

public override void Execute(Transition transition, object?[] args)
{
_action(transition, args);
}
public InvocationInfo Description { get; }

public override Task ExecuteAsync(Transition transition, object?[] args)
{
Execute(transition, args);
return TaskResult.Done;
}
public virtual Task ExecuteAsync(Transition transition, object?[] args)
{
return _callback.InvokeAsync(transition, args);
}

public class SyncFrom<TTriggerType> : Sync
public class From<TTriggerType> : EntryActionBehavior
{
internal TTriggerType Trigger { get; }

public SyncFrom(TTriggerType trigger, Action<Transition, object?[]> action, InvocationInfo description)
public From(TTriggerType trigger, Action<Transition, object?[]> action, InvocationInfo description)
: base(action, description)
{
Trigger = trigger;
}

public override void Execute(Transition transition, object?[] args)
public From(TTriggerType trigger, Func<Transition, object?[], Task> action, InvocationInfo description)
: base(action, description)
{
if (transition.Trigger.Equals(Trigger))
base.Execute(transition, args);
Trigger = trigger;
}

public override Task ExecuteAsync(Transition transition, object?[] args)
{
Execute(transition, args);
if (transition.Trigger.Equals(Trigger))
return base.ExecuteAsync(transition, args);
return TaskResult.Done;
}
}

public class Async : EntryActionBehavior
{
private readonly Func<Transition, object?[], Task> _action;

public Async(Func<Transition, object?[], Task> action, InvocationInfo description) : base(description)
{
_action = action;
}

public override void Execute(Transition transition, object?[] args)
{
throw new InvalidOperationException(
$"Cannot execute asynchronous action specified in OnEntry event for '{transition.Destination}' state. Use asynchronous version of Fire [FireAsync]");
}

public override Task ExecuteAsync(Transition transition, object?[] args)
{
return _action(transition, args);
}
}
}
}
Loading

0 comments on commit eb1bec5

Please sign in to comment.