Hi Stephen,
here's a
modified
example that demonstrates how to persist FSMs that deal with
"awaiting" states. Please note that this is only one out of several
options how to solve the problem. The most important things to
consider when using services (child actors) that return futures are:
- that service must be considered as "external service" (more on
that in
this
blog post). Therefore you should use a channel when
communicating with that service
- any reply message from the service (or returned future) must be
journaled (i.e. self ! Message(result) instead of self ! result):
This ensures that you keep *past* results in the journal which are
required to consistently recover the FSM. In your example, the
asynchronous/future results got recomputed and are sent to the FSM
concurrently to the replayed messages. This was leading to the
problem of receiving several messages in the "awaiting" state.
- in my example, I let the service (worker) confirm the receipt of
the message (see Confirm trait). A further delayed confirmation
could also be done by the FSM when receiving the result.
Furthermore, the example ensures that non-blocking recovery
successfully completes before processing any new messages, using a
simple buffer. Also recovery is delayed to receiving the first new
message. In your example, processing of new messages can occur while
recovery is still running, which is probably not what you want.
Hope that helps.
Cheers,
Martin