I have a lot of database consuming processes which i don't want to
start/restart simultaneously. So i wrote this behavior. It put all
your watches into queue and give every watch some private time so it
don't disturbed by other starting watches.

I still haven't resolved one problem: if while watch in this queue
you'll ask it to go to another state it will not do so until it time
will come (for ex.: if you ask watch to start and then to stop it will
wait it time in queue, then start, and then stop).

module God
  module Behaviors

    class WaitUntilReady < Behavior
      attr_accessor :wait_in, :wait_me, :interval, :mode, :stop_me


      def initialize
        super
        self.stop_me = false
      end

      def valid?
        valid = true
        valid &= complain("Attribute 'wait_in' must be specified",
self) unless self.wait_in
        valid &= complain("Attribute 'wait_me' must be specified",
self) unless self.wait_me
        valid
      end

      def before_start
        pending_cycle
      end

      def after_start
        eval("#{wait_in_mode}[:watches].shift")
      end

      def before_restart
        pending_cycle
      end

      def after_restart
        eval("#{wait_in_mode}[:watches].shift")
      end

      def before_stop
        stop_and_erase_queue
      end

      private

      def init_me
        eval("#{wait_in_mode}||={}")
        eval("#{wait_in_mode}[:time]||=Time.now")
        eval("#{wait_in_mode}[:watches]||=[]")
        eval("#{wait_in_mode}[:watches] << '#{self.watch.name}'")
      end

      def stop_and_erase_queue
        self.mode = 'start'
        eval("#{wait_in_mode}={}")

        self.mode = 'restart'
        eval("#{wait_in_mode}||={}")
      end

      def my_turn?
        eval("#{wait_in_mode}[:watches].first == '#
{self.watch.name}'")
      end

      def is_it_time?
        Time.now >= eval("#{wait_in_mode}[:time]")
      end

      def whos_next?
        eval("#{wait_in_mode}[:watches][1]")
      end

      def update_time_for_next_watch
        eval("#{wait_in_mode}[:time] = Time.now+#
{self.wait_me}.seconds")
      end

      def wait_in_mode
        self.wait_in+"_"+self.mode.to_s
      end

      def pending_cycle
        self.mode = self.watch.state
        init_me

        pending = true

        while pending and self.watch.state==self.mode
          if my_turn? and is_it_time?
            update_time_for_next_watch
            applog(self.watch, :info, "\t[#{wait_in_mode}] the time
has come to execute #{self.watch.name}")

            if nxt = whos_next?
              applog(self.watch, :info, "\t[#{wait_in_mode}] next one
will be executed #{nxt} in #{self.wait_me} seconds")
            else
              applog(self.watch, :info, "\t[#{wait_in_mode}] no one to
execute next")
            end

            pending = false
          else
            applog(self.watch, :info, "still waiting to execute #
{self.watch.name}")
            sleep(self.interval)
          end
        end
      end
    end

  end
end

You can use it like this:

God.watch do |w|

...

    w.behavior(:wait_until_ready) do |b|
      b.interval = 1.second
      b.wait_in = "$thin_time_watch"
      b.wait_me = 10.seconds
    end

...

end

interval - how often to check
wait_in - some global variable in which queue will be stored (you
don't need to instantiate it beforehand)
wait_me - how much time will next process wait. it's kind like grace
time only for queue.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"god.rb" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/god-rb?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to