OpusCapita / fsm-workflow

FSM workflow (for Node.js)
https://demo.core.dev.opuscapita.com/fsm-workflow/master
Apache License 2.0
28 stars 3 forks source link

Add 'release' guards to states #93

Closed estambakio-sc closed 5 years ago

estambakio-sc commented 5 years ago

90

estambakio-sc commented 5 years ago

Basic functionality is done. Now it's time to hook Machine.canRelease to Machine's sendEvent, availableTransitions, can. This requires some discussion @asergeev-sc

According to previous discussions, canRelease should be checked before checking for available transitions. If state cannot release, there's no sense in checking available transitions.

But ability to specify to state in states['mystate'].release introduces complexity. Let me explain.

If to is undefined - this array of guards should be checked both for canRelease({ object }) (without specified target state) and canRelease({ object, to: 'some_target_state' }).

If to: 'some_target_state' is defined (string or array of strings) then this array of guards should be checked for canRelease({ object, to: 'some_target_state' }) only, but not for different values or undefined one.

Now to the point.

If we check release guards before findAvailableTransitions then we have information only about object, and we can check only those release guards which have to === undefined. Information about to state is available only when we have a list of transitions from that state.

Therefore workflow will look like this:

We end up checking to === undefined guards twice. << main concern

Guards can be asynchronous functions, and therefore duplicate calls will create additional unneeded latency if a guard makes HTTP request for example.

I see two options:

asergeev-sc commented 5 years ago

The first option is ok.

Machine.availableTransitions is not related to 'release' guards, so it does not need to be touched. Only can and sendEvent needs to be updated with additional release guards checks.

Logically sendEvent could look like this: loop via all schema transitions where from, to, event correspond to passed parameters; for each found transition, check if the object can be released "from" state in "to" the one found, if yes, then transition specific guards too and if all guards are resolved into true then transition happens. Similar logic could be applied in 'can'.

estambakio-sc commented 5 years ago

for each found transition, check if the object can be released "from" state in "to" the one found

My considerations regarding this line: