Get progress on expression tree

24 views
Skip to first unread message

Reed Law

unread,
Feb 27, 2012, 1:28:20 PM2/27/12
to ruote
Say I have an expression tree like this:

sequence :tag => 'submission' do
participant 'author', :task => 'overview'
participant 'author', :task => 'author_info'
participant 'author', :task => 'upload_files'
participant 'author', :task => 'gap_analysis'
participant 'author', :task => 'responsibilities'
participant 'author', :task => 'disclosure'
participant 'author', :task => 'copyright'
participant 'author', :task => 'fees'
participant 'author', :task => 'review'
participant 'author', :task => 'submit'
end

I can use
engine.process(wfid).expressions[1].h.original_tree.last.count and see
that there are 10 expressions in the "submission" tag tree. What if I
want to find out how much progress an author has made within the
"submission" tree? So, for example, if the current task is
"upload_files", the author is on step 3 of 10.

I suppose I can put tags on each task (e.g. :tags => '1') but that
seems unnecessary. I guess the best approach would be to have the
workflow definition count the tasks and store it in a workitem field
and then compare the number of remaining tasks with this number.

John Mettraux

unread,
Feb 27, 2012, 3:08:10 PM2/27/12
to openwfe...@googlegroups.com

On Mon, Feb 27, 2012 at 10:28:20AM -0800, Reed Law wrote:
>
> Say I have an expression tree like this:
>
> sequence :tag => 'submission' do
> participant 'author', :task => 'overview'
> participant 'author', :task => 'author_info'
> participant 'author', :task => 'upload_files'
> # ...

> end
>
> I can use
> engine.process(wfid).expressions[1].h.original_tree.last.count and see
> that there are 10 expressions in the "submission" tag tree. What if I
> want to find out how much progress an author has made within the
> "submission" tree? So, for example, if the current task is
> "upload_files", the author is on step 3 of 10.
>
> I suppose I can put tags on each task (e.g. :tags => '1') but that
> seems unnecessary. I guess the best approach would be to have the
> workflow definition count the tasks and store it in a workitem field
> and then compare the number of remaining tasks with this number.

Hello,

you could directly do

sequence :tag => 'submission' do

author :task => 'overview', :progress => '1/10'
author :task => 'author_info', :progress => '2/10'
author :task => 'upload_files', :progress => '3/10'
author :task => 'gap_analysis', :progress => '4/10'
author :task => 'responsibilities', :progress => '5/10'
author :task => 'disclosure', :progress => '6/10'
author :task => 'copyright', :progress => '7/10'
author :task => 'fees', :progress => '8/10'
author :task => 'review', :progress => '9/10'
author :task => 'submit', :progress => '10/10'
end

It's easier (on ruote) than

author :task => 'overview', tag => '1/10'

because ruote doesn't have to keep a copy of the tag.

Tags are more appropriate when you do things like

sequence :tag => 'submission' do

concurrence :tag => '1/2' do
author :task => 'overview'
editor :task => 'guide'
concurrence :tag => '2/2' do
author :task => 'terminate'
editor :task => 'harass'
end
end

where the tags 'propagate' via the workitem. (as seen in
http://ruote.rubyforge.org/common_attributes.html#tag )

Note that if you're using Ruby process definitions, you could do

sequence :tag => 'submission' do

tasks = %w[
overview author_info upload_files gap_analysis responsibilities
disclosure copyright fees review submit
]
tasks.each_with_index { |t, i|
author :task => t, :progress => "#{i + 1}/#{tasks.length}
}
end

It's shorter, but perhaps not immediately graspable.

If your use case is "each time my user receives a workitem, I want to notify
him of his progress", you could do, as you have access to the workitem and
the dashboard:

step = workitem.fei.child_id + 1
exp = dashboard.fetch_flow_expression(workitem)
parent_exp = dashboard.fetch_flow_expression(exp.parent_id)
progress = "#{step}/#{parent_exp.tree[2].length}"

That's OK, but it adds two requests to the dashboard. You could do that right
when the workitem reaches the participant so that you don't have to repeat
the requests each time you display the workitem.

Another way would be to place in a workitem field the "parent length":

sequence :tag => 'submission' do

flag_length
author :task => 'overview', :progress => '1/10'
author :task => 'author_info', :progress => '2/10'
author :task => 'upload_files', :progress => '3/10'
end

where

class FlagLength
include Ruote::LocalParticipant

def on_workitem
parent_exp = fetch_flow_expression(flow_expression().parent_id)
workitem['steps'] = parent_exp.tree[2].length - 1
reply
end
end

then, when handling author workitems, you can do

progress = "#{workitem.fei.child_id}/#{workitem.fields['steps']}"


I hope it helps, best regards,

--
John Mettraux - http://lambda.io/processi

Reed Law

unread,
Feb 27, 2012, 3:50:29 PM2/27/12
to ruote
That helps immensely, thanks.

Manipulating and finding things inside a running process remains
mysterious, but your examples help point me in the right direction. I
am also looking at the source of RuoteKit quite a bit. The ruote
documentation is excellent for the most part, but I keep wishing for
more examples. Has anyone open sourced a recent Rails + Ruote
integration? I'm working on my second such app (closed source I'm
afraid) and the challenge is how to keep things synced up. For
example, a controller action can launch a process that goes to a user
participant to reply to. When the user replies, the workitem needs to
be updated, and often the associated object needs saving as well. So
I'm thinking about storing most of the object in the workitem fields
and then either using a custom participant to sync with the
ActiveModel object or doing it in the controller on each update.
Another issue is that the model needs to keep track of the workflow
and workitems somehow. The way I'm doing it right now is having the
workflow belong to the ActiveModel object and passing around workitem
ids in the views. It seems like a lot of glue and repetition so I'm
looking for ways to DRY it up.

John Mettraux

unread,
Feb 27, 2012, 4:13:09 PM2/27/12
to openwfe...@googlegroups.com

On Mon, Feb 27, 2012 at 12:50:29PM -0800, Reed Law wrote:
>
> Manipulating and finding things inside a running process remains
> mysterious, but your examples help point me in the right direction. I
> am also looking at the source of RuoteKit quite a bit. The ruote
> documentation is excellent for the most part, but I keep wishing for
> more examples.
>
> Has anyone open sourced a recent Rails + Ruote
> integration?
>
> I'm working on my second such app (closed source I'm
> afraid) and the challenge is how to keep things synced up. For
> example, a controller action can launch a process that goes to a user
> participant to reply to. When the user replies, the workitem needs to
> be updated, and often the associated object needs saving as well. So
> I'm thinking about storing most of the object in the workitem fields
> and then either using a custom participant to sync with the
> ActiveModel object or doing it in the controller on each update.
> Another issue is that the model needs to keep track of the workflow
> and workitems somehow. The way I'm doing it right now is having the
> workflow belong to the ActiveModel object and passing around workitem
> ids in the views. It seems like a lot of glue and repetition so I'm
> looking for ways to DRY it up.

Hello,

most of the examples I have are closed source as well.

I tend to avoid storing too much business info in the workitem (only storing
what's useful for routing) and point at business objects (via their primary
key usually).

The participants do a "update the business object and then give the workitem
back". I want them really separated, else I would use a state machine
focusing on the business object. My workflows orchestrate the work of one or
more persons around one or more business objects.


Sorry for being so vague,

Reply all
Reply to author
Forward
0 new messages