A Statemachine as defined in MDriven is great way to keep the dynamics of an object in order. You set guards and transitions to really enforce your business rules. Once you start to use them you see how your if/then/else code sort of melts away.
You cannot break the rules of the statemachine - even if you are the developer.
So going from State1 straight to State3 without passing State2 is not possible. Not possible thru the framework that is. You can always update the state attribute in the database.
And this rounding the framework thru the database has been fine up until now.
As we introduced the Slave and HistorySlave MDrivenServer-configurations we really do not want to mess with the database from outside the framework. Since if we do the change will not be recorded in the MDrivenServerSynk table – and thus it will not propagate to the slaves and it will not be recorded with a timestamp in the HistorySlave.
But still you will get into situation where you have not interpreted the business correct – so that you find that you need to fix something by twitching the statemachines in the production environment.
Earlier today a user asked me why she could not revive a thing that had been accidently set to Discarded:
Well I did not have a good answer – so I said – donowillfix. So adding the transition took 2 seconds. But the next planned release is 2 weeks away – she needs it Monday… I could do an “out of plan release” – but I want to release evenings to avoid production disturbance – and I am taking the family skiing over the weekend… You know – the usual excuses – the usual life.
Things like this will happen in the future as well.
The solution I decided upon is to introduce an elevation – to allow you the developer to bypass the rules of the statemachines.
This is how:
The new operation stateMachineForceMode(nameofstateattribute) can be called just before attacking the state attribute just as if it had been a normal attribute.
The stateMachineForceMode is only good for 1 write so this will fail on the 3 line:
self.stateMachineForceMode('State'); self.State:='State3'; self.State:='State3'But this will work: