state machine
“where are we in the process ?” is a question often heard (in the realm of workflow / process engines). A way of thinking about workflow is the “state machine” way, thus dividing the concept among “states” and “transitions”. Most of the time, this works out well.
With a state machine, it is a rather easy question to answer. OpenWFE[ru] is not based on state machines, it’s rather an interpreter.
Someone will still ask the question.
participants, at the surface
With OpenWFE[ru], I always sticked to the “you’re where there is a workitem that surfaced” explanation, that means, the state of a process instance is determined by the set of its workitems currently held by the participants.
# some setup (OpenWFEru 0.9.17) require 'openwfe/def' require 'openwfe/engine' require 'openwfe/participants' engine = OpenWFE::Engine.new alice = engine.register_participant( :alice, OpenWFE::HashParticipant) bob = engine.register_participant( :bob, OpenWFE::HashParticipant) class MyDefinition < OpenWFE::ProcessDefinition sequence do alice bob end end # later ... fei = engine.launch MyDefinition # fei will hold the id to the root expression # of the newly launched process instance sleep 0.050 # it's asynchronous, so... puts "alice holds #{alice.size} workitem(s)" puts "bob holds #{bob.size} workitem(s)" # (not doing anything meaningful with the workitem # in this example...) [/sourcecode] will produce something like <pre style="font-size:12px;border:1px dotted gray;"> alice holds 1 workitem(s) bob holds 0 workitem(s) </pre> We have one process instance and its "state" is at "alice". But now, what if the workitem is asleep, somewhere in a <a href="http://openwferu.rubyforge.org/expressions.html#exp_sleep">sleep expression</a>, or in a <a href="http://openwferu.rubyforge.org/expressions.html#exp_when">when expression</a> ? Only workitems in a participant would be listed, thus a sleeping process instance would be "nowhere". <strong>expressions, just under the surface</strong> Not all participants may be accessible and I've just mentioned this sleep issue. It also seems more natural to ask directly to the engine about the "state" of a process instance than trying to determine that from potentially scattered participants. puts engine.process_status(fei)
will yield something like :
-- OpenWFE::ProcessStatus -- wfid : 20071203-gidushipamo expressions : (fei 0.9.17 engine field:__definition My 0 20071203-gidushipamo alice 0.0.0) tags : errors : 0 paused : false
Now, we know that our process instance “20071203-gidushipamo” is currently at the “alice” participant (see the ‘expressions’ in the output.
But what if the participant “alice” appears at different ‘stages’ in our [business] process ? The expression id (position in the process definition tree) is “0.0.0”, OK, but what if the process changes ? (It will). What if we wanted something more expressive, something like a “state label” ? It could even encompass more than one participant / expression.
using process variables
We could use a variable bound at the process instance level (“/state”) and update it whenever our process enters a new stage.
class My2ndDefinition < OpenWFE::ProcessDefinition sequence do at :state => "redaction" alice at :state => "correction" bob alice at :state => "approval" charly end process_definition :name => "at" do set :var => "/state", :val => "${state}" end end fei = engine.launch My2ndDefinition sleep 0.050 puts "state : " + engine.lookup_variable( 'state', fei.workflow_instance_id)
will produce :
state : redaction
I have used here a [sub-]process definition, it’s perfectly fine to think of it as a function.
Not a bad technique. I should perhaps include an ‘at’ or an ‘entering’ expression to OpenWFEru (entering :stage => "x"
)… I’ll think about it.
In business process management, there is an ongoing effort to turn sequential processes into sets of concurrent processes. It could mean we have a process instance that has multiple states. It doesn’t seem too difficult to cope with this, but…
abusing tags, just under the surface
The OpenWFEru process definition language has redo and undo expressions. They use a :tag facility, any expression may be tagged and later redone or undone. A tag, behind the scenes, is just a variable like any other. With a “/” (slash) prefix, you can bind a tag at the process level (like the “/state” variable in the previous section).
This tag system being already available, why not using it for denoting state ?
That leads us to :
class My3rdDefinition < OpenWFE::ProcessDefinition sequence do alice :tag => "redaction" sequence :tag => "correction" do bob alice end charly :tag => "approval" end end fei = engine.launch My3rdDefinition sleep 0.050 puts "state : " + engine.process_status( fei.workflow_instance_id).tags.inspect
which outputs :
state : ["redaction"]
We thus have an array of tags (tag names). We can use tags with “undo” and “redo” to easily track some state in the business processes.
conclusion
I have shown three techniques for tracking state. The first one, focusing on participants only was what I initially thought for OpenWFE[ru].
The second and third techniques show a “state” concept that (1) doesn’t require querying the participants, (2) spans multiple participants or expressions.
I hope this long post also shed some light on the OpenWFEru [business] process engine. Questions are welcome on the OpenWFEru users mailing list.
blah?
Nikc
December 3, 2007 at 12:06 pm
Hi Nikc,
this is fixed. Though I still feel like rewriting the conclusion… Nice website btw, I like the mainframe picture :)
Thanks a lot,
John
John Mettraux
December 3, 2007 at 12:14 pm
“But what if the participant “alice” appears at different ’stages’ in our [business] process ?” — Having a single human being performing multiple tasks within one large business model, is exactly what I use most. Using any of the techniques above solves the issue, but I think it would be great to have a single documented (preferred) way to label tasks.
For example: maybe some future version of Densha’s fluo would want to show some task label within the rounded BPMN activity boxes. For that, it would need to know what specific tag or variable name is to be used.
So, even though OpenWFE[ru] is based on participants, maybe denote the “:tag” as being the preferred way to label tasks?
Arjan van Bentem
April 12, 2008 at 1:28 pm
Hello Arjan,
:tag can denote any expression in the process definitions.
But I will let Fluo use :tag as well as the current :activity for an “activity label”
http://rubyforge.org/tracker/index.php?func=detail&aid=19457&group_id=2609&atid=10195
Feel free to join the OpenWFEru users mailing list for further discussions
http://groups.google.com/group/openwferu-users
Thanks for your suggestion, best regards
John Mettraux
April 12, 2008 at 2:31 pm