listen

Listens for activity (incoming or outgoing workitems) on a (set of)
participant(s).

This expression is an advanced one. It allows for cross process instance
communication or at least cross branch communication within the same
process instance.

DO NOT confuse the listen expression with the ‘listener’ concept. They are
not directly related. The listen expression listens to workitem activity
inside of the engine, while a listener listens for workitems or launchitems
from sources external to the ruote workflow engine.

It can be used in two ways : ‘blocking’ or ‘triggering’. In both cases
the listen expression ‘reacts’ upon activity (incoming or outgoing workitem)
happening on a channel (a participant name or a tag name).

blocking

A blocking example :

              sequence do
                participant 'alice'
                listen :to => 'bob'
                participant 'charly'
              end
            

Once the listen expression got applied, this process will block until a
workitem (in any other process instance in the same engine) is dispatched
to participant ‘bob’. It then proceeds to charly.

triggering

This way of using ‘listen’ is useful for launching processes that “stalk”
other processes :

              Ruote.process_definition :name => 'stalker' do
                listen :to => 'bob' do
                  participant :ref => 'charly'
                end
              end
            

This small process will never exits and will send a workitem to charly
each time the ruote engine sends a workitem to bob.

The workitems passed to charly will be copies of the workitem initially
applied to the ‘listen’ expression, but with a copy of the fields of the
workitem passed to bob, merged in.

Note : for now, the triggered segments of processes are ‘forgotten’. The
‘listen’ expression doesn’t keep track of them. This also means that in
case of cancel, the triggered segments will not get cancelled.

:merge

By default, :merge is set to true, the listened for workitems see their
values merged into a copy of the workitem held in the listen expression
and this copy is delivered to the expressions that are client to the
‘listen’.

:merge can be set to ‘override’ where the event’s workitem fields are
used or some value which isn’t true or ‘true’, in which case the
workitem fields of the ‘listen’ expression is used as is (as it was
when the flow reached the ‘listen’ expression).

:upon

There are two kinds of main events in ruote, apply and reply. Thus,
a listen expression may listen to ‘apply’ and to ‘reply’ and this is
defined by the :upon attribute.

By default, listens upon ‘apply’ (engine handing workitem to participant).

Can be set to ‘reply’, to react on workitems being handed back to the
engine by the participant.

Setting :upon to ‘entering’ or ‘leaving’ tells the listen to focus on
tag events.

              sequence do
                sequence :tag => 'phase_one' do
                  alpha
                end
                sequence :tag => 'phase_two' do
                  bravo
                end
              end
            

In this dummy process definition, there are four tag events :

  • ‘entering’ ‘phase_one’
  • ‘leaving’ ‘phase_one’
  • ‘entering’ ‘phase_two’
  • ‘leaving’ ‘phase_two’

When listening to tags, absolute paths can be given.

              concurrence do
                sequence :tag => 'a' do
                  alpha
                  sequence :tag => 'b' do
                    bravo
                  end
                end
                sequence do
                  listen :to => 'a/b', :upon => 'entering'
                  charly
                end
               end
              end
            

Charly will be next when the flow is about to reach bravo.

:to and :on

The :to attribute has already been seen, it can be replaced by the :on one.

              listen :to => 'alpha'
            

is equivalent to

              listen :on => 'alpha'
            
            

:to (:on) and regular expressions

It’s OK to write things like :

              listen :to => "/^user\_.+/"
            

or

              listen :to => /^user\_.+/
            

To listen for workitems for all the participant whose name start with
“user_”.

:wfid

By default, a listen expression listens for any workitem/participant event
in the engine. Setting the :wfid attribute to ‘true’ or ‘same’ or ‘current’
will make the listen expression only care for events belonging to the
same process instance (same wfid).

:where

The :wfid can be considered a ‘guard’. Another tool for guarding listen
is to use the :where attribute.

              listen :to => 'alpha', :where => '${customer.state} == CA'
            

The listen will trigger only if the workitem has a customer field with
a subfield state containing the value “CA”.

The documentation about the dollar notation and the one about common
attributes :if and :unless applies for the :where attribute.

listen :to => :errors

The listen expression can be made to listen to errors.

              listen :to => errors do
                participant 'supervisor_sms', :task => 'verify system'
              end
            

Whenever an error happens in the process with this listen stance,
the listen will trigger.

“listen :to => :errors” only works with errors in the same process instance
(same wfid).

“listen :to => :errors” doesn’t trigger when the error is caught (via
:on_error).

listen :to => :errors, :class => ‘ArgumentError’

One can restrict the listen to certain classes of errors.
Passing a list of error classes separated by a comma is OK.

listen :to => :errors, :message => /x/

One can restrict the error listening to errors matching a certain regex
or equal to a certain string. The attribute is :message or :msg. The
value is a String (strict equality) or a Regex (matching).