Fix infinite loop after resetting state machine #1151
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Glossary
Description of unit test state names:
S8_1
- itintial stateS8_2
- custom start state that we pass with default contextS8_5
- end stateS8_3
,S8_4
- transit statesProblem description
In some situations (e.g. app crash) we need to start state machine from custom state in order to resume execution. To do that we are following next steps:
stopReactively
;S8_2
);startReactively
;Expected behavior
Transitions from
S8_2
toS8_5
with state machine stopActual behavior
Infinite loop with transitions
S8_2 -> S8_3 -> S8_4 -> S8_5 -> S8_2 -> S8_3 -> ...
as decribed in #1011What causes the problem
lastState
field being filled with custom value that we passed in context (S8_2
)S8_5
)ReactiveStateMachineExecutor
checks triggerless transitions.spring-statemachine/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/ReactiveStateMachineExecutor.java
Line 141 in 4495c7d
spring-statemachine/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/ReactiveStateMachineExecutor.java
Lines 364 to 385 in 4495c7d
With not null
lastState
field we'll get its value instead ofcurrentState
because ofisComplete()
returningtrue
.spring-statemachine/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/AbstractStateMachine.java
Lines 184 to 194 in 4495c7d
Comparing
S8_2
assource
withS8_2
ascurrentState
returns true, causing this check to be skipped and transitiont
now passing to flatMap. This transition will be called again and again.spring-statemachine/spring-statemachine-core/src/main/java/org/springframework/statemachine/support/ReactiveStateMachineExecutor.java
Lines 373 to 375 in 4495c7d
Fix description
Main goal of this fix is guaranteed returning of
currentState
while state machine is in running life cycle.Triggerless state machines do all work inside
STARTING
state duringstartReactively
call, so we can count it as a part of running life cycle.Existing tests was not affected by this change and passed successfully.
Commenting running check from
getState
will cause added test to run in infinite loop.