spring-statemachine icon indicating copy to clipboard operation
spring-statemachine copied to clipboard

Optimistic Locking for Persistence

Open mdmccann opened this issue 6 years ago • 2 comments

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

mdmccann avatar Nov 23 '18 09:11 mdmccann

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.

nnurmano avatar Mar 13 '19 13:03 nnurmano

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().

masch712 avatar Mar 14 '22 20:03 masch712