Thanks for your enlightening answers!
> This depends on what you have left out: will the actor do anything else in the LoadingState? Is the dbActor shared between
> more client actors, i.e. not just for this purpose? As I guess that the answer to the second question is probably “yes”, then that actor will do the blocking (otherwise you could just do the blocking call from the FSM). Using Futures should not be necessary unless there could be confusion wrt. the results which you receive back.
Roland, you are right, there are situations where the actor does some more calculations when in LoadingState. However, then this isn't a LoadingState anymore but the problem remains the same. The dbActor is also used by other actors. Moreover, some db calls are writes with potentially lots of data, this might take some minutes, that's why I decided that it's best to always return a future to make this obvious in the api. That way I'm able to control the future timeouts right in my db api where it's obvious how long those things might run in the worst case.
> One thing: your usage of Event() seems a bit confused, because you send it around. That case class is only manufactured by the FSM trait in order to pass the (msg, data) pair into your when-blocks, meaning that you probably want to send to yourself something like LoadingResult(result). Depending on what you want to do in the Left(...) case, you could also use pipeTo instead (import akka.pattern.pipe).
Oh, yeah, you are totally right with the Event() message, this should be my own message type. Regarding the Left() case I might send an alternative event to go into a failure state. But you are probably right with this one too, it might be best to just forward the result and do the logic in the LoadingState. In fact that's the place where the result interpretation should be done, otherwise this is very confusing.
> The way I accomplish this is similar to what you have except you will need to extract and pass along the sender with your messages.
Andy, your pointer to extract the sender makes total sense. However, in my case the fsm only sends messages to itself and the self reference should be stable. It's not necessary to return anything to the original sender once the start of the process is confirmed. The startup process includes the creation of a separate process actor which is feed by the fsm and it's spawn analysis actors and can be queried by any other actor including the original sender later on. After all the whole analysis process might take anything between couple of minutes up to two or three days and is triggered using a spray-based web-interface. You see, the original sender might be gone anyways ;)
> If you are mixing domain state with process state in a single FSM your code will become hopelessly complex because of all the state combinations. Separate your state machines into a domain state machine passed around in StateData and use the FSM for your process state machine.
I have to think about this. Maybe this would ease things a bit. Point is, the loading (and storing) is part of the analysis and hence not always easily to decouple. One solution I'm thinking of right now is to split the analysis fsm itself into smaller sub fsm to handle the intermediate analysis state.
It's time to do some hakking! Lot's of inspiration! Thank you guys!
Steffen