lib/openwfe/expressions/fe_participant.rb in openwferu-0.9.13 vs lib/openwfe/expressions/fe_participant.rb in openwferu-0.9.14

- old
+ new

@@ -28,12 +28,10 @@ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #++ # -# $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $ -# # # "made in Japan" # # John Mettraux at openwfe.org @@ -104,47 +102,90 @@ # 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' + # class ParticipantExpression < FlowExpression include FilterMixin include TimeoutMixin + include ConditionMixin names :participant attr_accessor \ :participant_name, :applied_workitem def apply (workitem) - remove_timedout_flag workitem + conditional = eval_condition(:if, workitem, :unless) - @applied_workitem = workitem.dup + if conditional == false + super_reply_to_parent workitem + return + end @participant_name = lookup_ref workitem @participant_name = fetch_text_content workitem \ unless @participant_name + participant = \ + get_participant_map.lookup_participant(@participant_name) + + raise "No participant named '#{@participant_name}'" \ + unless participant + + remove_timedout_flag workitem + + @applied_workitem = workitem.dup + schedule_timeout() filter_in workitem store_itself() workitem.params = lookup_attributes workitem - get_participant_map.dispatch @participant_name, workitem - get_participant_map.onotify @participant_name, :apply, workitem - # - # these two pmap calls were combined, but with the :reply - # notification in reply_to_parent() it feels more - # elegant like that + # + # threading AFTER the store_itself() + # + Thread.new do + begin + + # these two pmap calls were combined, but with the :reply + # notification in reply_to_parent() it feels more + # elegant like that + + get_participant_map.dispatch( + participant, @participant_name, workitem) + + get_participant_map.onotify( + @participant_name, :apply, workitem) + + rescue Exception => e + + get_expression_pool.notify_error( + e, fei, :do_apply, workitem) + end + end end + alias :super_reply_to_parent :reply_to_parent + def reply_to_parent (workitem) get_participant_map.onotify @participant_name, :reply, workitem # # for 'listen' expressions waiting for replies @@ -163,50 +204,63 @@ # will emit a CancelItem instance towards the participant itself # to notify it of the cancellation. # def cancel - unschedule_timeout() + unschedule_timeout - wi = super() + cancel_participant - return wi unless @applied_workitem - - # - # have to cancel the workitem on the participant side - - cancelitem = OpenWFE::CancelItem.new(@applied_workitem) - get_participant_map.dispatch(@participant_name, cancelitem) - nil end # # Upon timeout, the ParticipantExpression will cancel itself and # the flow will resume. # def trigger (scheduler) - ldebug { "trigger() timeout requested for #{@fei.to_debug_s}" } + linfo { "trigger() timeout requested for #{@fei.to_debug_s}" } begin #@scheduler_job_id = nil # # so that cancel won't unschedule without need - cancel() + cancel_participant - set_timedout_flag(@applied_workitem) + set_timedout_flag @applied_workitem - reply_to_parent(@applied_workitem) + reply_to_parent @applied_workitem rescue lerror do "trigger() problem while timing out\n"+ OpenWFE::exception_to_s($!) end end end + + protected + + # + # Have to cancel the workitem on the participant side + # + def cancel_participant + + return unless @applied_workitem + # + # if there is an applied workitem, it means there + # is a participant to cancel... + + participant = \ + get_participant_map.lookup_participant(@participant_name) + + cancelitem = CancelItem.new(@applied_workitem) + + get_participant_map.dispatch( + participant, @participant_name, cancelitem) + end end end