lib/openwfe/expressions/fe_wait.rb in ruote-0.9.19 vs lib/openwfe/expressions/fe_wait.rb in ruote-0.9.20

- old
+ new

@@ -1,50 +1,40 @@ -# #-- -# Copyright (c) 2007, John Mettraux, OpenWFE.org -# All rights reserved. +# Copyright (c) 2006-2009, John Mettraux, jmettraux@gmail.com # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -# . Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -# . 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. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. # -# . 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 -# POSSIBILITY OF SUCH DAMAGE. +# Made in Japan. #++ -# -# -# "made in Japan" -# -# John Mettraux at openwfe.org -# -require 'openwfe/expressions/fe_when' - - module OpenWFE # + # Since Ruote 0.9.20, 'sleep' got merged into 'wait' (according to Kenneth + # 'wait' sounds less lazy than 'sleep') + # + # The expression names are interchangeable. + # + # = wait + # # The 'wait' expression simply blocks/waits until the given condition # evaluates to true. # This expression accepts a timeout (else it will block ad eternam). # # sequence do @@ -65,13 +55,129 @@ # # 'wait' is different than 'when' : when it times out (if a timeout is set, # the wait ceases and the flow resumes. On a timeout, 'when' will not # execute its nested 'consequence' child. # + # + # = sleep + # + # The 'sleep' expression expects one attribute, either 'for', either + # 'until'. + # + # <sequence> + # <sleep for="10m12s" /> + # <participant ref="alpha" /> + # </sequence> + # + # will wait for 10 minutes and 12 seconds before sending a workitem + # to participant 'alpha'. + # + # In a Ruby process definition, that might look like : + # + # _sleep :for => "3m" + # _sleep "3m" + # # + # # both meaning 'sleep for 3 minutes' + # + # _sleep :until => "Mon Dec 03 10:41:58 +0900 2007" + # # + # # sleep until the given point in time + # + # If the 'until' attribute points to a time in the past, the sleep + # expression will simply let the process resume. + # + # _sleep needs to be used instead of 'sleep', so it doesn't conflict + # with Ruby's builtin sleep method. + # + # === scheduler tags + # + # Scheduler tags can be set like this : + # + # _sleep "10y", :scheduler_tags => "la_belle_au_bois_dormant" + # + # This is an advanced feature (that most users won't need). + # + # === sleeping for 8 hours + # + # If you tell a process instance to sleep for 8 hours, then shutdown the + # engine for 4 hours, at restart, it will sleep until the 8 hours have + # passed (so it will sleep for four hours). + # + # If the engine is stopped for more than eight hours, at restart, the process + # instance will immediately resume (sleep overdone). + # class WaitExpression < WaitingExpression - names :wait + names :wait, :sleep conditions :until - end + attr_accessor :until + + def apply (workitem) + + # + # is it a sleep ? + + sfor = lookup_string_attribute(:for, workitem) + suntil = lookup_string_attribute(:until, workitem) + + sfor = fetch_text_content(workitem) if sfor == nil and suntil == nil + + @until = if suntil + Rufus.to_ruby_time(suntil) rescue nil + elsif sfor + (Time.new.to_f + Rufus::parse_time_string(sfor)) rescue nil + else + nil # just to be sure + end + + @until ? apply_sleep(workitem) : super(workitem) + end + + def reschedule (scheduler) + + @until ? reschedule_sleep : super(scheduler) + end + + def trigger (params={}) + + @until ? reply_to_parent(@applied_workitem) : super(params) + end + + protected + + def apply_sleep (workitem) #:nodoc# + + @applied_workitem = workitem.dup + + determine_scheduler_tags + + reschedule(get_scheduler) + end + + def reschedule_sleep #:nodoc# + + ldebug do + "[re]schedule() " + + "will sleep until '#{@until}' " + + "(#{Rufus::to_iso8601_date(@until)})" + end + + @scheduler_job_id = "sleep_#{self.fei.to_s}" + + store_itself + + get_scheduler.schedule_at( + @until, + { + :schedulable => self, + :job_id => @scheduler_job_id, + :tags => @scheduler_tags }) + + ldebug do + "[re]schedule() @scheduler_job_id is '#{@scheduler_job_id}' "+ + " (scheduler #{scheduler.object_id})" + end + end + end end