I'm having some trouble finding the right way to remove a core in my application. It seems that I am removing a core "too early". Here is a simplification of my app design.
- Shell S has a state machine, with a linear set of transitions, A > B > C > D
- S instantiates module M when it sees a state-specific changed notification from B
- M has its own state machine, with a linear set of transitions, E > F
- Some time later, M dispatches an Event.COMPLETE when it reaches the end state, F (internally triggered by a state-specific changed notification from F)
- A Mediator for M in S listens for Event.COMPLETE and sends a StateMachine.ACTION that should transition S's state machine from B to C
- A Command registered to F's state-specific changed notification removes M's core.
This appears to be too early because once Facade.removeCore(M.NAME) completes, the long stack of notifications begins to end and eventually after M's state machine sends the state-specific notification for B, it attempts to send a StateMachine.CHANGED notification. Sending the notification triggers a new Facade instance with M's multiton key to be created. I'm left with M having been removed, but an "imposter".
In my first stab to fix this, I changed the dispatching of Event.COMPLETE in M to trigger off of StateMachine.CHANGED, but I ran into a similar problem because another mediator in M is also interested in StateMachine.CHANGED, but its observer comes after.
For now, I perform the clean up in a command triggered by changing to D, but this feels wrong. It looks like I've done something fundamentally wrong with my usage of multicore and statemachines.
The Question:How do I ensure M is done using the facade, or otherwise does not attempt to use its facade after I call removeCore()?
On a loosely related note, what's a best practice in having M communicate to the outside world? Dispatching an event based on the state-specific changed notification leaves the state machine blocked in the middle of transitionTo() and that doesn't seem quite right.