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