lib/openwfe/expressions/time.rb in ruote-0.9.18 vs lib/openwfe/expressions/time.rb in ruote-0.9.19

- old
+ new

@@ -1,34 +1,34 @@ # #-- # Copyright (c) 2006-2008, John Mettraux, OpenWFE.org # All rights reserved. -# -# Redistribution and use in source and binary forms, with or without +# +# Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # . Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# . Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation +# list of conditions and the following disclaimer. +# +# . Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. -# +# # . Neither the name of the "OpenWFE" nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# 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 +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# 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. #++ # # @@ -41,293 +41,288 @@ require 'openwfe/expressions/timeout' module OpenWFE + # + # A parent class for CronExpression and SleepExpression, is never + # used directly. + # It contains a simple get_scheduler() method simplifying the scheduler + # localization for <sleep/> and <cron/>. + # + class TimeExpression < FlowExpression + include Rufus::Schedulable + # - # A parent class for CronExpression and SleepExpression, is never - # used directly. - # It contains a simple get_scheduler() method simplifying the scheduler - # localization for <sleep/> and <cron/>. + # The workitem received at apply time # - class TimeExpression < FlowExpression - include Rufus::Schedulable + attr_accessor :applied_workitem - # - # The workitem received at apply time - # - attr_accessor :applied_workitem + # + # The job_id in the scheduler for this expression + # + attr_accessor :scheduler_job_id - # - # The job_id in the scheduler for this expression - # - attr_accessor :scheduler_job_id + # + # The tags (if any) for the job in the scheduler + # + attr_accessor :scheduler_tags - # - # The tags (if any) for the job in the scheduler - # - attr_accessor :scheduler_tags + # + # Makes sure to cancel any scheduler job associated with this + # expression + # + def cancel - # - # Makes sure to cancel any scheduler job associated with this - # expression - # - def cancel - #synchronize do + unschedule - ldebug { "cancel()..." } + super() - unschedule + @applied_workitem + end - super() + # + # If the expression has been scheduled, a call to this method + # will make sure it's unscheduled (removed from the scheduler). + # + def unschedule - @applied_workitem - #end - end + ldebug { "unschedule() @scheduler_job_id is #{@scheduler_job_id}" } + sleep get_scheduler.precision + 0.001 # - # If the expression has been scheduled, a call to this method - # will make sure it's unscheduled (removed from the scheduler). - # - def unschedule + # make sure not to unschedule before the actual scheduling + # got done. - ldebug { "unschedule() @scheduler_job_id is #{@scheduler_job_id}" } + get_scheduler.unschedule(@scheduler_job_id) \ + if @scheduler_job_id + end - sleep get_scheduler.precision + 0.001 - # - # make sure not to unschedule before the actual scheduling - # got done. + protected - get_scheduler.unschedule(@scheduler_job_id) \ - if @scheduler_job_id - end + # + # looks up potential scheduler tags in the expression + # attributes + # + def determine_scheduler_tags - protected + @scheduler_tags = lookup_array_attribute( + :scheduler_tags, @applied_workitem) || [] - # - # looks up potential scheduler tags in the expression - # attributes - # - def determine_scheduler_tags + @scheduler_tags << self.class.name - @scheduler_tags = lookup_array_attribute( - :scheduler_tags, @applied_workitem) || [] + @scheduler_tags << fei.to_short_s + @scheduler_tags << fei.parent_wfid + end + end - @scheduler_tags << self.class.name - end - end + # + # A parent class for WhenExpression and WaitExpression. + # + # All the code for managing waiting for something to occur is + # concentrated here. + # + class WaitingExpression < TimeExpression + include ConditionMixin + include TimeoutMixin + attr_accessor :frequency + + uses_template + # - # A parent class for WhenExpression and WaitExpression. + # By default, classes extending this class do poll for their + # condition every 10 seconds. # - # All the code for managing waiting for something to occur is - # concentrated here. + DEFAULT_FREQUENCY = "10s" + # - class WaitingExpression < TimeExpression - include ConditionMixin - include TimeoutMixin + # Don't go under 300 milliseconds. + # + MIN_FREQUENCY = 0.300 - attr_accessor :frequency + # + # Classes extending this WaitingExpression have a 'conditions' class + # method (like 'attr_accessor'). + # + def self.conditions (*attnames) - uses_template + attnames = attnames.collect do |n| + n.to_s.to_sym + end + meta_def :condition_attributes do + attnames + end + end - # - # By default, classes extending this class do poll for their - # condition every 10 seconds. - # - DEFAULT_FREQUENCY = "10s" + def apply (workitem) - # - # Don't go under 300 milliseconds. - # - MIN_FREQUENCY = 0.300 + remove_timedout_flag workitem - # - # Classes extending this WaitingExpression have a 'conditions' class - # method (like 'attr_accessor'). - # - def self.conditions (*attnames) + @applied_workitem = workitem.dup - attnames = attnames.collect do |n| - n.to_s.to_sym - end - meta_def :condition_attributes do - attnames - end - end + @frequency = lookup_attribute( + :frequency, workitem, :default => DEFAULT_FREQUENCY) + @frequency = Rufus::parse_time_string( + @frequency) + @frequency = MIN_FREQUENCY \ + if @frequency < MIN_FREQUENCY - def apply (workitem) + determine_timeout + determine_scheduler_tags - remove_timedout_flag workitem + condition_attribute = determine_condition_attribute( + self.class.condition_attributes) - @applied_workitem = workitem.dup + # + # register consequence - @frequency = lookup_attribute( - :frequency, workitem, :default => DEFAULT_FREQUENCY) - @frequency = Rufus::parse_time_string( - @frequency) - @frequency = MIN_FREQUENCY \ - if @frequency < MIN_FREQUENCY + consequence = condition_attribute ? + raw_children[0] : raw_children[1] - determine_timeout - determine_scheduler_tags + consequence = nil if consequence.is_a?(String) - condition_attribute = determine_condition_attribute( - self.class.condition_attributes) + get_expression_pool.tprepare_child( + self, + consequence, + 0, + true, # please register child + nil # no vars + ) if consequence - # - # register consequence + # + # go east... - consequence = condition_attribute ? - raw_children[0] : raw_children[1] - - get_expression_pool.tprepare_child( - self, - consequence, - 0, - true, # please register child - nil # no vars - ) if consequence + store_itself - # - # go east... + trigger + end - store_itself + def reply (workitem) - trigger - end + result = workitem.get_result - def reply (workitem) + if result + apply_consequence workitem + else + reschedule get_scheduler + end + end - result = workitem.get_result + # + # Cancels this expression (takes care of unscheduling a timeout + # if there is one). + # + def cancel - if result - apply_consequence workitem - else - reschedule get_scheduler - end - end + unschedule_timeout + super() + end + def trigger (params={}) + + ldebug { "trigger() #{@fei.to_debug_s} params : #{params.inspect}" } + + if params[:do_timeout!] # - # Cancels this expression (takes care of unscheduling a timeout - # if there is one). + # do timeout... # - def cancel + set_timedout_flag @applied_workitem + reply_to_parent @applied_workitem + return + end - unschedule_timeout - super() - end + @scheduler_job_id = nil - def trigger (params={}) + evaluate_condition + end - ldebug { "trigger() #{@fei.to_debug_s} params : #{params.inspect}" } + def reschedule (scheduler) - if params[:do_timeout!] - # - # do timeout... - # - set_timedout_flag @applied_workitem - reply_to_parent @applied_workitem - return - end + @scheduler_job_id = "waiting_#{fei.to_s}" - @scheduler_job_id = nil + scheduler.schedule_in( + @frequency, + { + :schedulable => self, + :job_id => @scheduler_job_id, + :tags => @scheduler_tags }) - evaluate_condition - end + ldebug { "reschedule() @scheduler_job_id is #{@scheduler_job_id}" } - def reschedule (scheduler) + to_reschedule scheduler + end - @scheduler_job_id = "waiting_#{fei.to_s}" + def reply_to_parent (workitem) - scheduler.schedule_in( - @frequency, - { - :schedulable => self, - :job_id => @scheduler_job_id, - :tags => @scheduler_tags }) + unschedule + unschedule_timeout - ldebug { "reschedule() @scheduler_job_id is #{@scheduler_job_id}" } + super workitem + end - to_reschedule scheduler - end + protected - def reply_to_parent (workitem) + # + # The code for the condition evalution is here. + # + # This method is overriden by the WhenExpression. + # + def evaluate_condition - unschedule - unschedule_timeout + condition_attribute = determine_condition_attribute( + self.class.condition_attributes) - super workitem - end + if condition_attribute - protected + c = eval_condition condition_attribute, @applied_workitem - # - # The code for the condition evalution is here. - # - # This method is overriden by the WhenExpression. - # - def evaluate_condition + do_reply c + return + end - condition_attribute = determine_condition_attribute( - self.class.condition_attributes) + # else, condition is nested as a child - if condition_attribute + #if @children.size < 1 + if raw_children.size < 1 + # + # no condition attribute and no child attribute, + # simply reply to parent + # + reply_to_parent @applied_workitem + return + end - c = eval_condition condition_attribute, @applied_workitem + # trigger the first child (the consequence child) - do_reply c - return - end + get_expression_pool.tlaunch_child( + self, + raw_children.first, + (Time.new.to_f * 1000).to_i, + @applied_workitem.dup, + false) # not registering as a child + end - # else, condition is nested as a child + # + # Used when replying to self after an attribute condition + # got evaluated + # + def do_reply (result) - #if @children.size < 1 - if raw_children.size < 1 - # - # no condition attribute and no child attribute, - # simply reply to parent - # - reply_to_parent @applied_workitem - return - end + @applied_workitem.set_result result + reply @applied_workitem + end - # trigger the first child (the condition child) + # + # This method is overriden by WhenExpression. WaitExpression + # doesn't override it. + # This default implementation simply directly replies to + # the parent expression. + # + def apply_consequence (workitem) - #get_expression_pool.launch_template( - # self, - # @environment_id, - # @condition_sub_id, - # @children[0], - # @applied_workitem) - get_expression_pool.tlaunch_child( - self, - raw_children.first, - (Time.new.to_f * 1000).to_i, - @applied_workitem.dup, - false) # not registering as a child - end - - # - # Used when replying to self after an attribute condition - # got evaluated - # - def do_reply (result) - - @applied_workitem.set_result result - reply @applied_workitem - end - - # - # This method is overriden by WhenExpression. WaitExpression - # doesn't override it. - # This default implementation simply directly replies to - # the parent expression. - # - def apply_consequence (workitem) - - reply_to_parent workitem - end - end + reply_to_parent workitem + end + end end