===================
Hi,
I'm Keisuke@Tokyo, a beginner of Ruby & Workflow engine.
I have looked for a good workflow engine that works with Ruby on
Rails, and finally I found "Ruote", pretty great framework!
Now I am studying "Ruote" whether it will suite my requirements or
not, and I have some questions.
------------------------------------------------------------------------
Q1: Can we change process definition as dynamically?
------------------------------------------------------------------------
For example, I have a process definition as ruby code like below.
#=== sample process definition 1 ===
class PicSelectionProcess < OpenWFE::ProcessDefinition
sequence do
get_pictures
concurrence :merge_type => 'mix' do
user_alice
user_bob
end
end
end
#=== until here ==================
After lunching this process, can user(or owner of proc) change this process
dynamically? like below..
#=== sample process definition 2 ===
class PicSelectionProcess < OpenWFE::ProcessDefinition
sequence do
get_pictures
concurrence :merge_type => 'mix' do
user_alice ## <== now process stopping here!!
user_bob
user_charly ## <== add this participant after lunching!
end
show_pictures ## <== add this participant after lunching!
end
end
#=== until here ==================
------------------------------------------------------------------------
Q2: Can we add new user or change user's group after lunching?
------------------------------------------------------------------------
This point is correspond with Q1.
New user who signed up after lunching a process, can join the
lunched process's participant?
If there are any result docs or web pages like these very simple and
beginner's questions,
Please let me know.
Thanks!
Hello Keisuke, welcome to the Ruote mailing list,
yes, it's possible to modify a process instance dynamically.
Unfortunately, while it's possible to add participant "show_pictures",
it's not possible to add participant "user_charly" since it belongs to
a concurrence which will have already fired (since the process is
stopped at "user_alice" *and* also at "user_charly"). So all my
explanations focus only on adding "show_pictures".
I also assume you are using a file persisted engine.
1a). manually :
- stop the engine
- locate the expression for the sequence, the file will look like
http://gist.github.com/56816
- edit the file to make it look like http://gist.github.com/56817
- restart the engine
the stop/restart is necessary since most of the time a persisted
engine will cache [recently used] expressions.
Note that the upcoming ruote (0.9.20) will by default store
expressions in a binary format, not YAML, but there will be a tool
(pooltool.rb) for transforming from one format to the other and back.
1b). manually with the web interface (ruote-rest only) :
http://dl.getdropbox.com/u/76595/dynmod.png
ruote-rest (http://github.com/jmettraux/ruote-rest) allows easy
in-flow process modification. This capability will soon be "ported" to
ruote-web2 (http://github.com/jmettraux/ruote-web2).
2). programmatically :
you can write ruby code to modify the running process instance, I've
pasted an example here :
> ------------------------------------------------------------------------
> Q2: Can we add new user or change user's group after launching?
> ------------------------------------------------------------------------
> This point is correspond with Q1.
> New user who signed up after launching a process, can join the
> launched process's participant?
It really depends on how you implemented / integrated ruote. As a Ruby
gem, ruote provides no "user management" nor "user concept".
Ruote-rest has no user concept either, but ruote-web2 has a system of
users and groups. Users belonging to a group may see all the workitems
attributed to a group, even if they were created after the workitem
reached the workitem store.
> If there are any result docs or web pages like these very simple and
> beginner's questions,
> Please let me know.
In-flow process modification is not that easy ;) Most of the time it's
better to have dynamic processes (and sub-processes) than dynamically
modifying processes.
Best regards,
--
John Mettraux - http://jmettraux.wordpress.com
Hi Keisuke,
you're welcome.
before answering, let's agree on a common vocabulary
(http://openwferu.rubyforge.org/glossary.html) :
* a process definition *
is a document (or a data structure) describing a way of automating a
[business] process
* a process instance *
is a running 'automation' of a [business] process, created on the base
of a process definition (usually).
> I clearly understood about the ways for changing definition.
I have explained you how to change a running process instance.
Changing a [process] definition is easy, you change the document (or
the data structure) that the process definition *is*.
What I have explained you is how to substitute the DNA
(http://ja.wikipedia.org/wiki/%E3%83%87%E3%82%AA%E3%82%AD%E3%82%B7%E3%83%AA%E3%83%9C%E6%A0%B8%E9%85%B8)
of a running process instance.
Changing a [process] definition is simply like modifying DNA before it
is used to build a living cell (process instance).
Sorry for the biological images.
> But small questions are occurred again.
>
> You wrote:
>
>>> In-flow process modification is not that easy ;) Most of the time it's
>>> better to have dynamic processes (and sub-processes) than dynamically
>>> modifying processes.
>
> What do you mean "dynamic processes"? Is it different with
> "dynamically modifying processes"?
> Is it the other feature of Ruote?
Sometimes there is no need to modify a process instance on the fly,
you can simply make it dynamic.
A static process :
<sequence>
<participant ref="alpha" />
<participant ref="bravo" />
</sequence>
This example always goes from "alpha" to "bravo", very static.
More dynamic :
<sequence>
<set field="final_participant" value="bravo" />
<participant ref="alpha" />
<participant ref="${f:final_participant} />
</sequence>
In this example, it goes from "alpha" to "bravo" except if the
participant alpha changed the value of the field "final_participant"
to the name of another participant.
This is not limited to participants :
<sequence>
<set field="final_stage"
value="http://documents.example.org/process_definitions/default_final_stage.xml"
/>
<participant ref="alpha" />
<subprocess ref="${f:final_stage} />
</sequence>
Here, a subprocess is launched, and the participant alpha may choose
yet another subprocess.
Let's focus on subprocesses and step back to static a bit :
<sequence>
<participant ref="alpha" />
<subprocess ref="http://documents.example.org/process_definitions/default_final_stage.xml"
/>
</sequence>
Is this really static ? Yes, no ? It depends. If the sub process
definition (the document) at
http://documents.example.org/process_definitions/default_final_stage.xml
changes you have achieved some dynamicity.
Here the URL is rather simple, but you can point to a version control
system (which replies with the latest version) or you could point to a
web application and the returned process definitions are potentially
always different...
More info at :
http://openwferu.rubyforge.org/expressions.html#exp_subprocess
http://openwferu.rubyforge.org/patterns.html
http://openwferu.rubyforge.org/expressions.html#exp_eval
...
> And also I have a fundamental question about workflow engine
> frameworks include Ruote.
>
> I assume that almost all engines can import XPDL or BPEL, Ruby DSL
> ;-)... and store it in memory object. It means "In-flow process
> modification is not that easy ;)".
Storing "in-memory" is OK for very short lived process instances. But
usually workflow engines want to run process instances that live a
long time (hour, day, week, month), so a persistence mechanism is a
must.
In-flow process [instance] modification is not easy (but it's not
necessarily hard). It's simply not a "common" task. If you have to do
it too often, it could mean your process definitions (and hence the
process instances) are not agile enough.
And then, there are questions like "should the modification affect
only 1 instance or all the instances coming from that process
definitions ?"
With "dynamic processes" "in-flight" modifications are coming from the
inside, while with "process instances dynamically modified", changes
are coming from the outside.
> But if the process definitions are stored in RDB, will it be more easy
> changing processes (of course, we can change only not started tasks.)
> and easy permanentizing?
Storing process definitions in a database is OK. I guess you meant
storing the runtime data / process instances in a relational database.
> The RDB structure will be simple, like below.
>
> Graph Table
> -------------------------------------------
> id task_id parent_task_id
> 1 1 0
> 2 2 1
> 3 2 3
> 4 3 1
> 5 4 2
> ...
>
> If there are any suggestion about the reasons why workflow engines
> usually NOT store digraph structure in RDB table, please let me know.
It depends on the workflow engine architecture / implementation (for
instance, Ruote behaves like an interpreter and not like a state
machine driver).
I don't understand where you want to go with this digraph idea. Do you
want to implement it by yourself ?
It's somehow not a bad idea. I use "decision participants / tables" to
make my processes more dynamic
(http://jmettraux.wordpress.com/2008/01/28/rufus-decision-csv-decision-tables/
http://jmettraux.wordpress.com/2007/10/12/decision-accumulation/ or
http://jmettraux.wordpress.com/2007/08/06/ruby-decision-table-quickstart/)
It's not reading a database table but a CSV file (or a google
spreadsheet) to modify [dynamically] the flow of a process.
> Sorry, I know this is stupid question because I have not studied any
> computer science..
Please don't worry about asking questions. I probably learn more from
your questions than your learn from my answers.
Are you a business analyst ?
Sounds very interesting.
Let's have a coffee one of these days.