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