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
-~----------~----~----~----~------~----~------~--~---