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'
reply_to_parent | -> | super_reply_to_parent |
applied_workitem | [RW] | |
participant_name | [RW] |
# 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.
# 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
# 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.
# 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
Have to cancel the workitem on the participant side
# 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