Skip to content

Commit

Permalink
ready for release
Browse files Browse the repository at this point in the history
  • Loading branch information
jmettraux committed Dec 20, 2012
1 parent 204d9ac commit 53780de
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 26 deletions.
2 changes: 1 addition & 1 deletion _layouts/post.html
Expand Up @@ -19,7 +19,7 @@ <h1>{{ page.title }}
{{ content }}

<div class="cr">
&copy; 2011-2012 John Mettraux
&copy; 2011-2013 John Mettraux
</div>
</div>

77 changes: 52 additions & 25 deletions _posts/2012-12-14-ruote-and-the-await-attribute.md
Expand Up @@ -4,11 +4,11 @@ title: ruote and the :await attribute
---

_tl;dr_<br/>
ruote has got a new "await" attribute (can be placed on any expression) that suspends the application of the expression until a condition (entering or leaving a tag or a participant) realizes. Useful to express acyclic graphs.
ruote has got a new "await" attribute (can be placed on any expression) that suspends the application of the expression until a condition (entering or leaving a tag or a participant) realizes. Useful when expressing graphs.

&nbsp;

[Ruote](http://ruote.rubyforge.org) is a Ruby workflow engine. It's mostly about orchestrating tasks, routing work among participants. The most interesting questions people come up with are the ones about "how to model that flow in ruote?".
[Ruote](http://ruote.rubyforge.org) is a Ruby workflow engine. It's about orchestrating tasks, routing work among participants. The most interesting questions people come up with are the ones about "how to model that flow in ruote?".

The other day on IRC (freenode #ruote), Typedef asked me how one could model this in ruote:

Expand Down Expand Up @@ -37,28 +37,14 @@ end
{% endhighlight %}
</div>

The rectangle is the top sequence, when the concurrence is done, C gets applied. The concurrence makes sure A and B are applied in parallel, the inner sequence align D after B and the :forget flag is here to let the B branch reply to the concurrence right after B finishes.
The rectangle is the top sequence, when the concurrence is done, C gets applied. The concurrence makes sure A and B are applied concurrently, the inner sequence align D after B and the :forget flag is here to let the B branch reply to the concurrence right after B finishes.

<img src="images/2012-12-14-abc_d.png" align="right" style="margin: 0;" />

But, conceptually, that is more like the graph on the right, where D becomes an orphan and the main flow goes on without waiting for it. It's not explicitely demanded but I think that this piece of flow ends when all its tasks completed (hence the rectangle I draw).
But, conceptually, that is more like the graph on the right, where D becomes an orphan and the main flow goes on without waiting for it. It's not explicitely required, but I think that this piece of flow should end when all its tasks completed (hence the rectangle I draw).

So I went back to the coding board. I wrote the four tasks in a concurrence and told myself: "this is great, the four tasks exist in the same space, when all four of them terminate, the concurrence terminates..."

<div class="half-code">
{% highlight ruby linenos %}
#
# everybody at the same time
#
concurrence do
a
b
c
d
end
{% endhighlight %}
</div>

I wondered how I could materialize Typedef's arrows. And I realized that he was probably right trying to apply [await](http://ruote.rubyforge.org/exp/await.html), this expression could shine in this scenario.

This "await" expression is a rework of the [listen](http://ruote.rubyforge.org/exp/listen.html) expression. It's meant for waiting for events to happen in other branches of the workflow execution tree.
Expand Down Expand Up @@ -89,9 +75,7 @@ end

There are 3 kind of events "await" can listen to: participant (on apply and on reply), tag (on entering and on leaving) and errors.

The problem with this definition is that it nevers exits, the two await expressions behave like little daemons, wait for the that to be left. That's how "await" (and "listen") are supposed to work, when they have a block they become daemons.

The solution would be to use "await" without a block. It then behaves like a lock, waiting for the event to happen to let the flow resume.
The problem with this definition is that it never exits, the two await expressions behave like little daemons, that's how "await" (and "listen") are supposed to work, when they have a block they become daemons.

<div class="half-code">
{% highlight ruby linenos %}
Expand All @@ -116,16 +100,16 @@ end
{% endhighlight %}
</div>

But, although it behaves as we wanted, it feels clunky compared to the "daemons" version above.
The solution would be to use "await" without a block. It then behaves like a lock, waiting for the event to happen to let the flow resume.

So I went ahead and added an :await attribute to the ruote expressions. When an expression sports it, it waits for the described event before applying for real (it stays in a paused state until the event occurs).
But, although it runs as we wanted, the definition feels clunky compared to the "daemons" version above.

The resulting process definition looks like:
So I went ahead and added an :await attribute to the ruote expressions. When an expression sports it, it waits for the described event before applying for real (it stays in a paused state until the event occurs).

<div class="half-code-right">
{% highlight ruby linenos %}
#
# xxx
# using the new :await attribute
#
concurrence do
sequence :tag => 'ab' do
Expand All @@ -142,3 +126,46 @@ end
{% endhighlight %}
</div>


This new "await" attribute can express things like

* ```:await => "left_tag:x"```
* ```:await => "reached_participant:alfred"```

The bare

```:await => "b"```

is a shortcut for

```:await => "left_tag:b"```

I think this "wait for a tagged region to terminate" scenario is important and deserves a short notation.

<div class="half-code">
{% highlight ruby linenos %}
#
# short version
#
concurrence do
sequence :tag => 'ab' do
a
b :tag => 'b'
end
c :await => 'ab'
d :await => 'b'
end
{% endhighlight %}
</div>

I've added some documentation about this new "await attribute" to the [common attributes](http://ruote.rubyforge.org/common_attributes.html) page and to the [await expression](http://ruote.rubyforge.org/exp/await.html) documentation.

Here are the main links for ruote:

* [http://ruote.rubyforge.org](http://ruote.rubyforge.org) (site)
* [https://github.com/jmettraux/ruote](https://github.com/jmettraux/ruote) (source)
* [http://groups.google.com/group/openwferu-users](http://groups.google.com/group/openwferu-users) (mailing list)
* freenode #ruote (irc)

I wish you a Merry Christmas and a Happy New Year!

2 changes: 2 additions & 0 deletions css/style.css
Expand Up @@ -107,10 +107,12 @@ img {
width: 47%;
float: left;
margin-right: 0.7em;
margin-bottom: 0.2em;
}
.half-code-right {
width: 47%;
float: right;
margin-left: 0.7em;
margin-bottom: 0.2em;
}

0 comments on commit 53780de

Please sign in to comment.