Skip to content

Commit

Permalink
Merge pull request #6 from wlindley/command-chain-failure
Browse files Browse the repository at this point in the history
Adding OnFailure to Command chains
  • Loading branch information
wlindley authored Nov 24, 2016
2 parents 36b14ea + 9e6e373 commit fa21f26
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 4 deletions.
6 changes: 6 additions & 0 deletions Bantam/CommandChain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Bantam
public abstract class CommandChain
{
internal List<CommandAllocator> Commands = new List<CommandAllocator>();
internal CommandAllocator FailureCommand;
}

public class CommandChain<T> : CommandChain where T : class, Event
Expand All @@ -18,5 +19,10 @@ public class CommandChain<T> : CommandChain where T : class, Event
Commands.Add(new CommandAllocator<T, U>(initializer));
return this;
}

public void OnFailure<U>(CommandInitializer<U, T> initializer = null) where U : Command, new()
{
FailureCommand = new CommandAllocator<T, U>(initializer);
}
}
}
29 changes: 25 additions & 4 deletions Bantam/CommandChainExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ internal class EventCommandChainExecutor : CommandChainExecutor
private CommandRelay manager;
private Event triggeringEvent;
private List<CommandAllocator>.Enumerator enumerator;
private CommandAllocator failureAllocator;
private CommandAllocator currentAllocator;
private ObjectPool pool;
private Command currentCommand;

Expand All @@ -60,21 +62,24 @@ public void Reset()
currentCommand = null;
pool = null;
enumerator.Dispose();
failureAllocator = null;
currentAllocator = null;
}

internal void Start(Event triggeringEvent, CommandChain chain, CommandRelay manager, ObjectPool pool)
{
this.triggeringEvent = triggeringEvent;
this.manager = manager;
this.pool = pool;
failureAllocator = chain.FailureCommand;
enumerator = chain.Commands.GetEnumerator();
enumerator.MoveNext();
Next();
}

public void CurrentCommandComplete()
{
enumerator.Current.FreeCommand(pool, currentCommand);
currentAllocator.FreeCommand(pool, currentCommand);
currentCommand = null;
if (enumerator.MoveNext())
Next();
Expand All @@ -84,14 +89,30 @@ public void CurrentCommandComplete()

public void CurrentCommandFailed()
{
enumerator.Current.FreeCommand(pool, currentCommand);
currentAllocator.FreeCommand(pool, currentCommand);
currentCommand = null;
manager.CompleteChainExecution<EventCommandChainExecutor>(this);
if (null != failureAllocator)
ExecuteFailureCommand();
else
manager.CompleteChainExecution<EventCommandChainExecutor>(this);
}

private void Next()
{
currentCommand = enumerator.Current.AllocateCommand(pool, triggeringEvent);
currentAllocator = enumerator.Current;
StartCommandFromCurrentAllocator();
}

private void ExecuteFailureCommand()
{
currentAllocator = failureAllocator;
failureAllocator = null;
StartCommandFromCurrentAllocator();
}

void StartCommandFromCurrentAllocator()
{
currentCommand = currentAllocator.AllocateCommand(pool, triggeringEvent);
currentCommand.Start(this);
}
}
Expand Down
27 changes: 27 additions & 0 deletions BantamTest/CommandRelayTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,33 @@ public void LaunchRunsInitializerOnCommandIfProvided()
testObj.Launch<DummyCommand>(cmd => cmd.value = 7500);
Assert.AreEqual(7500, DummyCommand.LastValue);
}

[Test]
public void OnFailureExecutesCommandWhenChainFails()
{
testObj.On<DummyEvent>().Do<FailingCommand>().OnFailure<DummyCommand>();
eventBus.Dispatch<DummyEvent>();
Assert.AreEqual(1, DummyCommand.ExecuteCount);
}

[Test]
public void OnFailureCommandCanFailWithoutCreatingInfiniteRecursion()
{
testObj.On<DummyEvent>().Do<FailingCommand>().OnFailure<FailingCommand>();
eventBus.Dispatch<DummyEvent>();
}

[Test]
public void OnFailureCanTakeAnOptionalInitializerForCommand()
{
var expectedValue = 55;
testObj.On<DummyEvent>().Do<FailingCommand>().OnFailure<DummyCommand>((cmd, evt) =>
{
cmd.value = evt.value;
});
eventBus.Dispatch<DummyEvent>(evt => evt.value = expectedValue);
Assert.AreEqual(expectedValue, DummyCommand.LastValue);
}
}

public class DummyCommand : Command
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ commandRelay.On<LoginEvent>()
.Do<ShowUsernameCommand>((cmd, evt) => cmd.loginEvent = evt)
.Do<ShowOptionsCommand>();

//Handle a failed command chain
commandRelay.On<UserDataRequestEvent>()
.Do<FailingCommand>()
.OnFailure<ResetUserDataCommand>();

//Create a Model.
modelRegistry.Create<UserDataModel>(mdl => mdl.username = "Jane Doe");
```

0 comments on commit fa21f26

Please sign in to comment.