(Migrated) Transitions state machine

(This message has been automatically imported from the retired mailing list)

Hello,

work to add a state machine to support checking the
correctness of transitions across business states of in-flight processes
will start soon now.

Consider this config file.

[Order]
supports=order,priority_order
initial=new
canceled=canceled,rejected
new=submitted
submitted=ready
ready=sent_to_client
sent_to_client=client_confirmed, client_rejected
client_rejected=updated
updated=ready

This is a simple flow of statuses concerning two business objects:
orders and priority orders.

  • Initial state is ‘new’.

  • At any time objects may enter states ‘canceled’ and ‘rejected’
    quitting a given flow instance immediately.

  • Following transitions are possible:

  • new -> submitted (customer submits order)

  • submitted -> ready (backoffice prepared what was needed)

  • ready -> sent_to_client (a package was sent)

  • sent_to_client -> client_confirmed (all went fine, ends flow)

  • sent_to_client -> client_rejected (something wrong with package)

  • client_rejected -> updated (backoffice update the package)

  • updated -> ready (package can be re-sent, enter ‘ready’ again)

If a state is a leaf (such as client_confirmed) it means it ends the flow.

In terms of a programmer’s API this would be something like:

def handle(self):

with self.transition.to(‘updated’, ‘order’, order_id) as t:

# Perform business operation here
pass

# Adds arbitrary data possibly needed later on
t.add_context(any_data)

Now the ‘with’ call would:

  • Check in DB that there exists an ‘order’ object whose instance as
    identified by order_id can enter the ‘updated’ state.

If it cannot, the with block won’t execute at all.

If it can, the block will execute and upon exiting it this business
object’s status will be set to ‘updated’.

The ‘t.add_context’ call lets one store arbitrary opaque data alongside
each individual transition.

A few utility functions will be provided …

  • self.transition.is_allowed(state, object_type, object_id)

  • self.transition.transit(state, object_type, object_id)

  • self.transition.get_history(object_type, object_id)

… the first two are basically what the with block will do under the
hood split available as individual calls whereas the third one returns a
list of transitions + context for each one.

For now the feature will go to zato-labs …

https://github.com/zatosource/zato-labs

… in the scope pretty much as above but I’d like to spark a discussion
on what else in your opinion could be added before it’s fully ported to
the core for the next major release.

Hot-deployment of definitions + GUI of some sort spring to mind, but
what else would you find useful and convenient to have?

thanks,