tentative feature: timers

19 views
Skip to first unread message

John Mettraux

unread,
Aug 16, 2011, 1:19:56 PM8/16/11
to ruote
Dear list,

I had a conversation with Lucas from Howcast the other day:

http://ruote-irclogs.s3.amazonaws.com/log_2011-08-11.html

There is always this recurring pattern, I emit a workitem towards a participant and I want it to be reminded of it, like 1 week before the timeout and then a final time, 1 day before the task closes.

Up until now, it involved writing something like:

---8<---
concurrence :count => 1 do
participant 'toto', :task => 'clean the car', :timeout => '4w'
sequence :lose => true do
wait '2w'
participant 'toto', :notification => 'clean the car !'
end
sequence :lose => true do
wait '3w'
participant 'toto', :notification => 'DO CLEAN THE CAR !!'
end
end
--->8---

You can wrap that in a subprocess:

---8<---
define 'do_task' do
concurrence :count => 1 do
participant '${v:target}', :task => '${v:task}', :timeout => '${v:tout}'
sequence :lose => true do
wait '${v:first_reminder}'
participant '${v:target}', :notification => '${v:task} !'
end
sequence :lose => true do
wait '${v:second_reminder}'
participant '${v:target}', :notification => '${v:task} !!'
end
end
end

do_task :target => 'toto', :first_reminder => '2w', :second_reminder => '3w', :tout => '4w'
--->8---

But it becomes quickly rather ugly.

With Lucas, we discussed having something shorter.

---8<---
participant 'toto', :task => 'clean the car', :reminders => '2w, 3w', :timeout => '4w'
--->8---

or

---8<---
participant 'toto', :task => 'clean the car', :reminders => '2w: first_reminder, 3w: second_reminder, 4w: timeout'

define 'first_reminder' do
participant '${v:text}', :msg => '1st reminder'
end
define 'second_reminder' do
concurrence do
participant '${v:text}', :msg => '2nd reminder'
participant 'supervisor', :msg => '2nd reminder for ${v:text} / ${v:task}'
end
end
--->8---

These are not always reminders, and it could be beneficial to attach them to other things that only participant expression. Let's try with "timers":

---8<---
sequence :timers => '2w: notify, 3w: timeout' do
participant 'toto'
participant 'doug'
end
--->8---

In this short example, the sequence has a timeout of three weeks, and after two weeks, the subprocess (or participant) named 'notify' is triggered.

I'm working on this feature right now, here is a summary of it:

- they are 'timers'
- it's a list than can get attached to any expression
- they trigger participants, subprocesses or the 'timeout' special behaviour
- maybe 'error' is another special behaviour, 'cancel' as well ('redo' ?)

It requires a bit of rework of the timeout infra, fortunately it should be backward compatible.


Thoughts, comments ?

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

Nathan Stults

unread,
Aug 16, 2011, 1:25:57 PM8/16/11
to openwfe...@googlegroups.com
This will be a tremendously useful feature.

Dear list,

http://ruote-irclogs.s3.amazonaws.com/log_2011-08-11.html

or


Thoughts, comments ?

--
you received this message because you are subscribed to the "ruote
users" group.
to post : send email to openwfe...@googlegroups.com to unsubscribe
: send email to openwferu-use...@googlegroups.com
more options : http://groups.google.com/group/openwferu-users?hl=en

Mario Camou

unread,
Aug 16, 2011, 6:03:17 PM8/16/11
to openwfe...@googlegroups.com
Ooohh! Shiny!

Yes, that would be EXTREMELY useful.
-Mario.

--
I want to change the world but they won't give me the source code.

John Mettraux

unread,
Aug 31, 2011, 11:33:43 AM8/31/11
to openwfe...@googlegroups.com
Hello,

the timers feature has been implemented and merged in the ruote 2.2.1 master.

It behaves as previously described in this thread. It's backward compatible.

It lead to the inclusion of a new common attribute, :flank.

| replies to parent ? | cancellable ? |
-------+---------------------+---------------+
forget | immediately | no |
lose | never | yes |
flank | immediately | yes |

(sorry if the ascii table doesn't render properly in your email client).

Timers are "flanking" the expression to which they are tied.

---8<---
sequence :timers => '2d: first_reminder, 3d: final_reminder, 4d: timeout' do
# ...
end
--->8---

(where first_reminder and final_reminder are participants or subprocesses).

Since they replied immediately upon being triggered, the expression keeps track of its "flanks". When an expression is cancelled, its flanks are cancelled as well, they thus shouldn't outlive their expression.

Since :flank is a common attribute, you can write

---8<---
sequence do
sequence :flank => true do
bob :task => 'side work'
end
alice :task => 'main work'
end
--->8---

Where bob is given a task as long as alice is performing the "main work" task.

This could previously be achieved with something like

---8<---
concurrence :count => 1 do

sequence :lose => true do

bob :task => 'side work'
end
alice :task => 'main work'
end
--->8---

which I explained many times in this mailing list.

I'm not sure "flank" is the right word, I wanted to use "side" or "wing", but well, to flank / a flank, to side / a side, to wing, ... It's flank for now, many someone has a convincing suggestion.

I hope the :flank pattern is more readable than its concurrence :count => 1 original.

I will probably make an expression for flank, so that

---8<---
sequence do
flank do
bob :task => 'side work'
charly : task => 'side work, part 2'
end
alice :task => 'main work'
end
--->8---

(forget and lose also have their own expressions).

Now I have to document that.

I hope to release 2.2.1 soon, I have troubles with the CI setting for now.


Comments and suggestions are welcome, thanks to Lucas (Howcast) for triggering this work and sharing his ideas during the inception.

Best regards,

Danny Fullerton

unread,
Aug 31, 2011, 6:02:23 PM8/31/11
to ruote
Great work! This will definitely be very useful! Most of the
complexity of the application i'm working on was based on managing
timers. I'll give it a try.

coffeeaddict

unread,
Sep 2, 2011, 2:52:32 AM9/2/11
to ruote
On Thu, Sep 01, 2011 at 12:33:43AM +0900, John Mettraux wrote:
> Hello,
>
> the timers feature has been implemented and merged in the ruote 2.2.1 master.
>
> It behaves as previously described in this thread. It's backward compatible.

Great stuff! I really need something like this...

> <hartog/20110902; snip: explanation of timers>
>
> I will probably make an expression for flank, so that
>
> ---8<---
> sequence do
> flank do
> bob :task => 'side work'
> charly : task => 'side work, part 2'
> end
> alice :task => 'main work'
> end
> --->8---
>
> (forget and lose also have their own expressions).

Would it not be more sane to have something that describes the main
task before the flanking tasks, like so:


sequence do
1st_ork_platoon :task => "attack gates through valley"

flank do
archers :task => "setup positions in hills"
2nd_ork_platoon :task => "lay low behind hills"
end
lose do
warg_riders :task => "circle compound, attack rear"
end
end



(Although, in this scenario, it would seem that if the 1st ork platoon
loses, the warg riders will attack, but obviously the 2nd ork platoon
must come to battle once the 1st has been wore down - I think I choose
a bad example ;->)

> Now I have to document that.
>
> I hope to release 2.2.1 soon, I have troubles with the CI setting for now.

Good luck with the CI (And the documentation, I hope to put some more
time and effort in to the docs soon)

> <hartog/20110902; snip: footers>


Grtz,
Hartog.

John Mettraux

unread,
Sep 2, 2011, 11:34:24 AM9/2/11
to openwfe...@googlegroups.com

On Thu, Sep 01, 2011 at 11:52:32PM -0700, coffeeaddict wrote:
> On Thu, Sep 01, 2011 at 12:33:43AM +0900, John Mettraux wrote:
> >
> > <aggressive snipping by John>

Hello Hartog,

well spotted. Nice domain for the example, I like it a lot.


What happens with the sequence is that, well, it executes in sequence, so you have to put the flanks first. I could force any expressions with flanking children to grab them and apply them first, but for now I prefer going the simplest way.

---8<---
repeat do
alpha_platoon :task => 'main push'
over :if => '${success}'
commit_reserve :if => '${reserve_available}'
commit_help_unit :if => '${help_available}', :flank => true
over :if => '${failure}'
end
--->8---

In this [contrived] example, help units could come in and "flank", one at a time, ending with more than one flank.

Let's try to solve your issue by using concurrence:

---8<---
concurrence do

1st_ork_platoon :task => "attack gates through valley"

archers :task => "setup positions in hills", :flank => true
2nd_ork_platoon :task => "lay low behind hills", :flank => true
warg_riders :task => "circle compound, attack rear", :flank => true
end
--->8---

This concurrence would be over as soon as the 1st platoon is over with its task. Flanks would be cancelled at that point.

It's close to the initial

---8<---
concurrence :count => 1 do

1st_ork_platoon :task => "attack gates through valley"

archers :task => "setup positions in hills", :lose => true
2nd_ork_platoon :task => "lay low behind hills", :lose => true
warg_riders :task => "circle compound, attack rear", :lose => true
end
--->8---

So I'm not that successful with the introduction of 'flank'...

---8<---
sequence do

# Flanks

archers :task => "setup positions in hills", :flank => true
2nd_ork_platoon :task => "lay low behind hills", :flank => true
warg_riders :task => "circle compound, attack rear", :flank => true

# Schwerpunkt

1st_ork_platoon :task => "attack gates through valley"

end
--->8---

You're right, I'm forcing a potentially non-natural ordering. I think concurrence + flank, doesn't look to bad (at least it removes the :count).


What do you think ?

eric smith

unread,
Sep 6, 2011, 6:10:00 PM9/6/11
to ruote
John,

We have several conditions where we want to be reminded based on a
date relative to a field in a workitem, not necessarily the workitem
date.

task => 'prep orientation package' :remind_me => 5 days before the
[contract date]

Not sure if its part of the same use case but you could also see:
remind me 5 days before the end of the month,quarter year


Thanks
Eric

John Mettraux

unread,
Sep 6, 2011, 6:38:56 PM9/6/11
to openwfe...@googlegroups.com

On Tue, Sep 06, 2011 at 03:10:00PM -0700, eric smith wrote:
>
> We have several conditions where we want to be reminded based on a
> date relative to a field in a workitem, not necessarily the workitem
> date.
>
> task => 'prep orientation package' :remind_me => 5 days before the
> [contract date]

Hello Eric,

I know this is not elegant, but I'd do it this way:

---8<---
alice :task => 'prep package', :timers => '${r:Time.at(wi.fields['contract_date']) - 5.days}: reminder'
--->8---

(note I've used ActiveSupport #days in this example).

> Not sure if its part of the same use case but you could also see:
> remind me 5 days before the end of the month,quarter year

That would require a good temporal language in ruote.

Others have implemented such languages in Ruby, I was thinking people would simply use the one they prefer in their participants (or in ${r:x} constructs).

https://github.com/mojombo/chronic
https://github.com/bokmann/business_time
https://github.com/dcparker/temporals
...

One thing I could do is checking whether the participant class responds to a #timers method and call it if present. This is currently only implemented for timeouts (via a #rtimeout method (since JRuby forces a #timeout method on every object)).

We currently only have

---8<---
class MyParticipant
include Ruote::LocalParticipant

def rtimeout(workitem)
(Time.at(workitem.fields['contract_date']) + 10.days).to_s
end
end
--->8---

we could thus have also

---8<---
class MyParticipant
include Ruote::LocalParticipant

def timers(workitem)
(Time.at(workitem.fields['contract_date']) - 5.days).to_s + ': ' +
'reminder'
end
end
--->8---


Not sure if my answer makes sense, kind regards,

Eric Smith

unread,
Sep 8, 2011, 12:23:09 PM9/8/11
to ruote
Yes that would do it. Thanks
Eric Smith

John Mettraux

unread,
Sep 11, 2011, 8:11:02 PM9/11/11
to openwfe...@googlegroups.com

On Thu, Sep 08, 2011 at 09:23:09AM -0700, Eric Smith wrote:
> Yes that would do it. Thanks

OK, it's in

https://github.com/jmettraux/ruote/commit/edd797ed5078dc09a4f46a5d89a164c817d3cc41


Best regards,

Reply all
Reply to author
Forward
0 new messages