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

[Docs] Improve FSM hygiene #5680

Merged
merged 2 commits into from
Feb 22, 2022
Merged
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
38 changes: 3 additions & 35 deletions docs/articles/actors/finite-state-machine.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,31 +99,15 @@ The `stateFunction` argument is a `delegate State<TState, TData> StateFunction(E

Each `FSM` needs a starting point, which is declared using

```csharp
StartWith(state, data[, timeout])
```
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?name=StartWith)]

The optionally given timeout argument overrides any specification given for the desired initial state. If you want to cancel a default timeout, use `null`.

### Unhandled Events

If a state doesn't handle a received event a warning is logged. If you want to do something else in this case you can specify that with `WhenUnhandled(stateFunction)`:

```csharp
WhenUnhandled(state =>
{
if (state.FsmEvent is Queue x)
{
_log.Info("Received unhandled event: " + x);
return Stay();
}
else
{
_log.Warning("Received unknown event: " + state.FsmEvent);
return Goto(new Error());
}
});
```
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?name=UnhandledHandler)]

Within this handler the state of the `FSM` may be queried using the stateName method.

Expand Down Expand Up @@ -163,23 +147,7 @@ OnTransition(handler)

which associates actions with a transition instead of with a state and event. The handler is a delegate `void TransitionHandler(TState initialState, TState nextState)` function which takes a pair of states as input; no resulting state is needed as it is not possible to modify the transition in progress.

```csharp
OnTransition((initialState, nextState) =>
{
if (initialState == State.Active && nextState == State.Idle)
{
SetTimer("timeout", new Tick(), TimeSpan.FromSeconds(1), repeat: true);
}
else if (initialState == State.Active)
{
CancelTimer("timeout");
}
else if (nextState == State.Idle)
{
_log.Info("entering Idle from " + initialState);
}
});
```
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?name=TransitionHandler)]

The handlers registered with this method are stacked, so you can intersperse `OnTransition` blocks with when blocks as suits your design. It should be noted, however, that all handlers will be invoked for each transition, not only the first matching one. This is designed specifically so you can put all transition handling for a certain aspect into one place without having to worry about earlier declarations shadowing later ones; the actions are still executed in declaration order, though.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public class ExampleFSMActor : FSM<State, IData>

public ExampleFSMActor()
{
// <StartWith>
StartWith(State.Idle, Uninitialized.Instance);
// </StartWith>

#region FSMHandlers
When(State.Idle, state =>
Expand Down