Behavior - wait until ready

16 views
Skip to first unread message

miv

unread,
Jun 2, 2009, 7:16:41 AM6/2/09
to god.rb
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.
Reply all
Reply to author
Forward
0 new messages