spring-projects / spring-statemachine

Spring Statemachine is a framework for application developers to use state machine concepts with Spring.
1.52k stars 598 forks source link

acquire statemachine is overwrite the statemachine to initial state because of the factory createmachine #1098

Open ammar-esrawi opened 1 year ago

ammar-esrawi commented 1 year ago

https://github.com/spring-projects/spring-statemachine/blob/3ad063a80646a1c9974560dcf91a40230338c693/spring-statemachine-core/src/main/java/org/springframework/statemachine/service/DefaultStateMachineService.java#L91

this line is causing the persisted machine to be overwritten with a new machine context before reaching the restore logic so the restored machine is always in the initial state.

I solved this by creating a new impl and replaced the function with the following:

@Override
public StateMachine<S, E> acquireStateMachine(String machineId, boolean start) {
        log.info("Acquiring machine with id " + machineId);
        StateMachine<S, E> stateMachine;
        // naive sync to handle concurrency with release
        synchronized (machines) {
            stateMachine = machines.get(machineId);
            if (stateMachine == null) {

                if (stateMachinePersist != null) {
                    try {
                        StateMachineContext<S, E> stateMachineContext = stateMachinePersist.read(machineId);
                        if(stateMachineContext !=null){
                            log.info("Getting new machine from factory with null id ");
                            stateMachine = stateMachineFactory.getStateMachine();
                            stateMachine = restoreStateMachine(stateMachine, stateMachineContext);
                        }else{
                            log.info("Getting new machine from factory with id " + machineId);
                            stateMachine = stateMachineFactory.getStateMachine(machineId);
                        }
                    } catch (Exception e) {
                        log.error("Error handling context", e);
                        throw new StateMachineException("Unable to read context from store", e);
                    }
                }else{
                    log.info("Getting new machine from factory with id " + machineId);
                    stateMachine = stateMachineFactory.getStateMachine(machineId);
                }
                machines.put(machineId, stateMachine);
            }
        }
        // handle start outside of sync as it might take some time and would block other machines acquire
        return handleStart(stateMachine, start);
    }

please take a look at my changes and suggest a better fix if available