spring-statemachine
spring-statemachine copied to clipboard
Optimistic Locking for Persistence
My state machine will be managing 'Order' objects and persisting them to the database using StateMachineRuntimePersister with JpaStateMachineRepository.
As I could have multiple requests trying to move the single 'Order' instance along the workflow, I would love some Optimistic Locking solution.
I have did a test and identified that below is the current behaviour:
ida = a; StateMachine smRef1 = stateMachineFactory.getStateMachine(id); StateMachine smRef2 = stateMachineFactory.getStateMachine(id);
smRef1.sendEvent(SUBMIT); //entity is updated in database to SUBMITTED state smRef1.sendEvent(APPROVE); //entity is updated in database to APPROVED state
smRef2.sendEvent(SUBMIT); //entity is updated in database to SUBMITTED state
I would prefer to see this being rejected by the database as the data being used by smRef2 is now stale
Should this be handled on transitions level? I mean, if your transition allows moving from APPROVED state to SUBMITTED state, then I don't see any issue here. Also, you could use guards to protect unneeded transitions.
Should this be handled on transitions level? I mean, if your transition allows moving from APPROVED state to SUBMITTED state, then I don't see any issue here. Also, you could use guards to protect unneeded transitions.
I think unless locking is done at the database level (via JPA Optimistic Locking, for example), there will always be risk of a race condition.
I tried to implement optimistic locking by creating subclasses of JpaRepositoryStateMachinePersist and several other classes, but this quickly spiraled out of control and I was still unable to get things to work.
I think if the StateMachineContext had an instance field for a version token, then a custom JpaRepositoryStateMachinePersist subclass could populate that token from the database on read()
, and JPA / the database would validate that token on write()
.