Class OpenWFE::ParticipantExpression
In: lib/openwfe/expressions/fe_participant.rb
Parent: FlowExpression

Participants sit at the edge between the engine and the external world. The participant expression transmit the workitem applied to it to the Participant instance it looks up in the participant map tied to the engine.

 direct reference to participant alpha :

    <participant ref="alpha" />

 the name of the participant is the value found in
 the field 'target' :

    <participant field-ref="target" />
    <participant ref="${f:target}" />

 the name of the participant is the value found in
 the variable 'target' :

    <participant variable-ref="target" />
    <participant ref="${target}" />

 direct reference to participant 'alpha'
 if a subprocess named 'alpha' has been defined, the
 subprocess will be called instead :

    <alpha />

The Participant expressions includes the FilterMixin and thus understands and applies the "filter" attribute.

Since OpenWFEru 0.9.9, the attributes of the participant expression are set inside a hash field named ‘params’ just available to the participant. Thus in

    <participant ref="toto" task="play golf" location="Minami Center" />

participant ‘toto’ will receive a workitem with a field named ‘params’ containing the hash { "ref"=>"toto", "task"=>"play golf", "location"=>"Minami Center" }.

When the workitem gets back from the participant, the field ‘params’ is deleted.

The participant expressions include the TimeoutMixin, it means that a timeout can be stated :

    <participant ref="toto" timeout="2w1d" />

If after 2 weeks and 1 day (15 days), participant "toto" hasn‘t replied, the workitem will get cancelled and the flow will resume (behind the scene, participant "toto", will receive a CancelItem instance bearing the same FlowExpressionId as the initial workitem and the participant implementation is responsible for the cancel application).

The participant expression accepts an optional ‘if’ (or ‘unless’) attribute. It‘s used for conditional execution of the participant :

    participant :ref => "toto", :if => "${weather} == raining"
        # the participant toto will receive a workitem only if
        # it's raining

    boss :unless => "#{f:matter} == 'very trivial'"
        # the boss will not participate in the proces if the matter
        # is 'very trivial'

Methods

Included Modules

FilterMixin TimeoutMixin ConditionMixin

External Aliases

reply_to_parent -> super_reply_to_parent

Attributes

applied_workitem  [RW] 
participant_name  [RW] 

Public Instance methods

[Source]

     # File lib/openwfe/expressions/fe_participant.rb, line 129
129:         def apply (workitem)
130: 
131:             conditional = eval_condition :if, workitem, :unless
132: 
133:             return super_reply_to_parent(workitem) \
134:                 if conditional == false
135:                     #
136:                     # skip expression 
137:                     # <participant ref="x" if="y" /> (where y evals to false)
138: 
139:             @participant_name = lookup_ref workitem
140: 
141:             @participant_name = fetch_text_content workitem \
142:                 unless @participant_name
143: 
144:             participant =
145:                 get_participant_map.lookup_participant @participant_name
146: 
147:             raise "No participant named '#{@participant_name}'" \
148:                 unless participant
149: 
150:             remove_timedout_flag workitem
151: 
152:             @applied_workitem = workitem.dup
153: 
154:             schedule_timeout()
155: 
156:             filter_in workitem
157: 
158:             store_itself()
159:             
160:             workitem.params = lookup_attributes workitem
161: 
162:             #
163:             # threading AFTER the store_itself()
164:             #
165:             Thread.new do
166:                 begin
167: 
168:                     # these two pmap calls were combined, but with the :reply
169:                     # notification in reply_to_parent() it feels more
170:                     # elegant like that
171: 
172:                     get_participant_map.dispatch(
173:                         participant, @participant_name, workitem)
174: 
175:                     get_participant_map.onotify(
176:                         @participant_name, :apply, workitem)
177: 
178:                 rescue Exception => e
179: 
180:                     get_expression_pool.notify_error(
181:                         e, fei, :do_apply, workitem)
182:                 end
183:             end
184:         end

The cancel() method of a ParticipantExpression is particular : it will emit a CancelItem instance towards the participant itself to notify it of the cancellation.

[Source]

     # File lib/openwfe/expressions/fe_participant.rb, line 208
208:         def cancel
209: 
210:             unschedule_timeout
211: 
212:             cancel_participant
213: 
214:             @applied_workitem
215:         end

[Source]

     # File lib/openwfe/expressions/fe_participant.rb, line 188
188:         def reply_to_parent (workitem)
189: 
190:             get_participant_map.onotify @participant_name, :reply, workitem
191:                 #
192:                 # for 'listen' expressions waiting for replies
193: 
194:             unschedule_timeout()
195: 
196:             workitem.attributes.delete "params"
197: 
198:             filter_out workitem
199: 
200:             super workitem
201:         end

Upon timeout, the ParticipantExpression will cancel itself and the flow will resume.

[Source]

     # File lib/openwfe/expressions/fe_participant.rb, line 221
221:         def trigger (scheduler)
222: 
223:             linfo { "trigger() timeout requested for #{@fei.to_debug_s}" }
224: 
225:             begin
226: 
227:                 #@scheduler_job_id = nil
228:                     #
229:                     # so that cancel won't unschedule without need 
230: 
231:                 cancel_participant
232: 
233:                 set_timedout_flag @applied_workitem
234: 
235:                 reply_to_parent @applied_workitem
236:             rescue
237:                 lerror do
238:                     "trigger() problem while timing out\n"+
239:                     OpenWFE::exception_to_s($!)
240:                 end
241:             end
242:         end

Protected Instance methods

Have to cancel the workitem on the participant side

[Source]

     # File lib/openwfe/expressions/fe_participant.rb, line 249
249:             def cancel_participant
250: 
251:                 return unless @applied_workitem
252:                     #
253:                     # if there is an applied workitem, it means there
254:                     # is a participant to cancel...
255: 
256:                 participant = \
257:                     get_participant_map.lookup_participant(@participant_name)
258: 
259:                 cancelitem = CancelItem.new(@applied_workitem)
260: 
261:                 get_participant_map.dispatch(
262:                     participant, @participant_name, cancelitem)
263:             end

[Validate]