-
Notifications
You must be signed in to change notification settings - Fork 634
Description
Example of config
@Override
public void configure(StateMachineStateConfigurer<States, Actions> states) throws Exception {
states
.withStates()
.initial(States.BEGIN)
.fork(States.FORK)
.join(States.JOIN)
.state(States.PROCESS_1, processOneStateMachineFactory)
.state(States.PROCESS_2, processTwoStateMachineFactory)
.end(States.END)
.and()
.withStates()
.parent(States.FORK)
.region(Regions.SEQUENTIAL.name())
.initial(States.RECEIVING)
.state(States.RECEIVING, receivingStateMachineFactory)
.end(States.RECEIVING_DONE)
.and()
.withStates()
.parent(States.FORK)
.region(Regions.PARALLEL.name())
.initial(States.OT)
.state(States.OT, otStateMachineFactory)
.end(States.OT_DONE);
}
Example of transitions for FORK and JOIN
@Override
public void configure(StateMachineTransitionConfigurer<States, Actions> transitions) throws Exception {
transitions
.withExternal()
.source(States.BEGIN)
.target(States.FORK)
.event(Actions.START)
.and()
.withFork()
.source(States.FORK)
.target(States.OT)
.target(States.RECEIVING)
.and()
.withJoin()
.source(States.RECEIVING_DONE)
.source(States.OT_DONE)
.target(States.JOIN)
.and()
.withExternal()
.source(States.JOIN)
.target(States.PROCESS_1)
.event(Actions.COMPLETE_JOIN)
.and()
.withExternal()
.source(States.PROCESS_1)
.target(States.PROCESS_2)
.event(Actions.COMPLETE_ PROCESS_1)
.and()
.withExternal()
.source(States.PROCESS_2)
.target(States.END)
.event(Actions.COMPLETE_ PROCESS_2);
}
In this case all work as expected until you have 1 instance of application and application won't be restarted.
But if we restart our application or call SM action on another instance thre we don't have memory context for called SM and one or both of our parallel processes was somewhere in the middle and we restore context from DB repository and proceed all action which set RECEIVING_DONE state and OT_DONE then state JOIN won't happen and SM execution is stuck.
Just for clarification parallel middle state mean what we have 3-4 internal states in RECEIVING or OT state machine and made restart when we was not on initial state.
I found solution how to avoid it but will be great to fix it in next versions.
This is the additional code that fixed this behavior:
@Override
public void configure(StateMachineTransitionConfigurer<States, Actions> transitions) throws Exception {
transitions
.withExternal()
.source(States.BEGIN)
.target(States.FORK)
.event(Actions.START)
.and()
.withFork()
.source(States.FORK)
.target(States.OT)
.target(States.RECEIVING)
.and()
.withJoin()
.source(States.RECEIVING_DONE)
.source(States.OT_DONE)
.target(States.JOIN)
//=====================================================
.and()
.withExternal()
.source(States.RECEIVING_DONE)
.target(States.PROCESS_1)
.guard(someJoinGuard). // guard where I checked what I have both required states as DONE
.and()
.withExternal()
.source(States.OT_DONE)
.target(States.PROCESS_1)
.guard(someJoinGuard) // guard where I checked what I have both required states as DONE
//=====================================================
.and()
.withExternal()
.source(States.JOIN)
.target(States.PROCESS_1)
.and()
.withExternal()
.source(States.PROCESS_1)
.target(States.PROCESS_2)
.event(Actions.COMPLETE_ PROCESS_1)
.and()
.withExternal()
.source(States.PROCESS_2)
.target(States.END)
.event(Actions.COMPLETE_ PROCESS_2)
;
}
someJoinGuard example
public class someJoinGuard implements Guard<States, Actions> {
@Override
public boolean evaluate(StateContext<States, Actions> context) {
return context.getStateMachine().getState().getIds().contains(States.RECEIVING_DONE)
&& context.getStateMachine().getState().getIds().contains(States.OT_DONE);
}
@Override
public String toString() {
return "someJoinGuard";
}
}
PS: If it's required I can create example project sources and provide it.