Class: Forever::Base
- Inherits:
-
Object
- Object
- Forever::Base
- Defined in:
- lib/forever/base.rb
Instance Attribute Summary collapse
-
#started_at ⇒ Object
readonly
Returns the value of attribute started_at.
Instance Method Summary collapse
-
#after(filter, &block) ⇒ Object
After :all or :each jobs hook.
-
#before(filter, &block) ⇒ Object
Before :all or :each jobs hook.
-
#config ⇒ Object
Return config of current worker in a hash.
-
#dir(value = nil) ⇒ Object
(also: #workspace)
Base working Directory.
-
#every(period, options = {}, &block) ⇒ Object
Define a new job task.
-
#file(value = nil) ⇒ Object
Caller file.
-
#initialize(options = {}, &block) ⇒ Base
constructor
A new instance of Base.
-
#jobs ⇒ Object
Our job list.
-
#log(value = nil) ⇒ Object
File were we redirect STOUT and STDERR, can be false.
-
#name ⇒ Object
Daemon name.
-
#on_error(&block) ⇒ Object
Callback raised when an error occour.
-
#on_exit(&block) ⇒ Object
Callback raised when at exit.
-
#on_limit_exceeded(&block) ⇒ Object
Callback raised when queue limit was exceeded.
-
#on_ready(&block) ⇒ Object
Callback to fire when the daemon start (blocking, not in thread).
-
#pid(value = nil) ⇒ Object
File were we store pid.
-
#queue(value = nil) ⇒ Object
Queue size.
-
#remove ⇒ Object
Remove the daemon from the config file.
-
#running?(silent = false) ⇒ Boolean
Returns true if the pid exist and the process is running.
-
#stop ⇒ Object
Perform a soft stop.
-
#stop! ⇒ Object
Search if there is a running process and stop it.
-
#tmp ⇒ Object
Temp directory, used to store pids and jobs status.
-
#to_s ⇒ Object
(also: #inspect)
Convert forever object in a readable string showing current config.
Constructor Details
#initialize(options = {}, &block) ⇒ Base
Returns a new instance of Base.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/forever/base.rb', line 8 def initialize(={}, &block) @options = forking = .delete(:fork) # Run others methods .each { |k,v| send(k, v) if respond_to?(k) } instance_eval(&block) # Setup directories Dir.chdir(dir) Dir.mkdir(tmp) unless File.exist?(tmp) Dir.mkdir(File.dirname(log)) if log && !File.exist?(File.dirname(log)) write_config! case ARGV[0] when 'config' print config.to_yaml exit when 'start', 'restart', 'up', nil stop when 'run', 'live' detach = false stop when 'stop' stop exit when 'kill' stop! exit when 'update' print "[\e[90m%s\e[0m] Config written in \e[1m%s\e[0m\n" % [name, FOREVER_PATH] exit when 'remove' stop remove exit else print <<-RUBY.gsub(/ {10}/,'') % name Usage: \e[1m./%s\e[0m [start|stop|kill|restart|config|update] Commands: start stop (if present) the daemon and perform a start live run in no-deamon mode stop stop the daemon if a during when it is idle restart same as start kill force stop by sending a KILL signal to the process config show the current daemons config update update the daemon config remove removes the daemon config RUBY exit end clean_tmp! # Enable REE - http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=) maybe_fork(detach) do Process.setsid if detach != false $0 = "Forever: #{$0}" unless ENV['DONT_TOUCH_PS'] print "[\e[90m%s\e[0m] Process %s with pid \e[1m%d\e[0m with \e[1m%s\e[0m and Forever v.%s\n" % [name, detach != false ? :daemonized : :running, Process.pid, forking ? :fork : :thread, Forever::VERSION] %w(INT TERM).each { |signal| trap(signal) { stop! } } trap(:HUP) do IO.open(1, 'w'){ |s| s.puts config } end File.open(pid, "w") { |f| f.write(Process.pid.to_s) } if pid stream = log ? File.new(log, @options[:append_log] ? 'a' : 'w') : File.open('/dev/null', 'w') stream.sync = true STDOUT.reopen(stream) STDERR.reopen(STDOUT) @started_at = Time.now # Invoke our before :all filters filters[:before][:all].each { |block| safe_call(block) } # Store pids of childs pids = [] # Start deamons until stopping? current_queue = 1 jobs.each do |job| next unless job.time?(Time.now) if queue && current_queue > queue puts "\n\nThe queue limit of #{queue} has been exceeded.\n\n" on_limit_exceeded ? on_limit_exceeded.call : sleep(60) break end if forking begin GC.start pids << Process.detach(fork { job_call(job) }) rescue Errno::EAGAIN puts "\n\nWait all processes since os cannot create a new one\n\n" Process.waitall end else Thread.new { job_call(job) } end current_queue += 1 end # Detach zombies, our ps will be happier pids.delete_if { |p| p.stop? } sleep 0.5 end # Invoke our after :all filters filters[:after][:all].each { |block| safe_call(block) } # If we are here it means we are exiting so we can remove the pid and pending stop.txt clean_tmp! end self end |
Instance Attribute Details
#started_at ⇒ Object (readonly)
Returns the value of attribute started_at.
6 7 8 |
# File 'lib/forever/base.rb', line 6 def started_at @started_at end |
Instance Method Details
#after(filter, &block) ⇒ Object
After :all or :each jobs hook
316 317 318 319 |
# File 'lib/forever/base.rb', line 316 def after(filter, &block) raise "Filter #{filter.inspect} not supported, available options are: :each, :all" unless [:each, :all].include?(filter) filters[:after][filter] << block end |
#before(filter, &block) ⇒ Object
Before :all or :each jobs hook
308 309 310 311 |
# File 'lib/forever/base.rb', line 308 def before(filter, &block) raise "Filter #{filter.inspect} not supported, available options are: :each, :all" unless [:each, :all].include?(filter) filters[:before][filter] << block end |
#config ⇒ Object
Return config of current worker in a hash
324 325 326 |
# File 'lib/forever/base.rb', line 324 def config { :dir => dir, :file => file, :log => log, :pid => pid } end |
#dir(value = nil) ⇒ Object Also known as: workspace
Base working Directory
183 184 185 |
# File 'lib/forever/base.rb', line 183 def dir(value=nil) value ? @_dir = value : @_dir end |
#every(period, options = {}, &block) ⇒ Object
Define a new job task
Example:
every 1.second, :at => '12:00' do
my_long_task
end
148 149 150 |
# File 'lib/forever/base.rb', line 148 def every(period, ={}, &block) jobs << Forever::Job.new(period, .merge!(:dir => dir), &block) end |
#file(value = nil) ⇒ Object
Caller file
162 163 164 |
# File 'lib/forever/base.rb', line 162 def file(value=nil) value ? @_file = value : @_file end |
#jobs ⇒ Object
Our job list
155 156 157 |
# File 'lib/forever/base.rb', line 155 def jobs @_jobs ||= [] end |
#log(value = nil) ⇒ Object
File were we redirect STOUT and STDERR, can be false.
Default: dir + ‘log/.log’
200 201 202 203 |
# File 'lib/forever/base.rb', line 200 def log(value=nil) @_log ||= File.join(dir, "log/#{name}.log") if exists?(dir, file) value.nil? ? @_log : @_log = value end |
#name ⇒ Object
Daemon name
169 170 171 |
# File 'lib/forever/base.rb', line 169 def name File.basename(file, '.*') end |
#on_error(&block) ⇒ Object
Callback raised when an error occour
259 260 261 |
# File 'lib/forever/base.rb', line 259 def on_error(&block) block_given? ? @_on_error = block : @_on_error end |
#on_exit(&block) ⇒ Object
Callback raised when at exit
273 274 275 |
# File 'lib/forever/base.rb', line 273 def on_exit(&block) after(:all, &block) end |
#on_limit_exceeded(&block) ⇒ Object
Callback raised when queue limit was exceeded
266 267 268 |
# File 'lib/forever/base.rb', line 266 def on_limit_exceeded(&block) block_given? ? @_on_limit_exceeded = block : @_on_limit_exceeded end |
#on_ready(&block) ⇒ Object
Callback to fire when the daemon start (blocking, not in thread)
280 281 282 |
# File 'lib/forever/base.rb', line 280 def on_ready(&block) before(:all, &block) end |
#pid(value = nil) ⇒ Object
File were we store pid
Default: dir + ‘tmp/.pid’
210 211 212 213 |
# File 'lib/forever/base.rb', line 210 def pid(value=nil) @_pid ||= File.join(tmp, "#{name}.pid") if exists?(dir, file) value.nil? ? @_pid : @_pid = value end |
#queue(value = nil) ⇒ Object
Queue size
176 177 178 |
# File 'lib/forever/base.rb', line 176 def queue(value=nil) value ? @_queue = value : @_queue end |
#remove ⇒ Object
Remove the daemon from the config file
249 250 251 252 253 254 |
# File 'lib/forever/base.rb', line 249 def remove print "[\e[90m%s\e[0m] Removed the daemon from the config " % name config_was = File.exist?(FOREVER_PATH) ? YAML.load_file(FOREVER_PATH) : [] config_was.delete_if { |conf| conf[:file] == file } File.open(FOREVER_PATH, "w") { |f| f.write config_was.to_yaml } end |
#running?(silent = false) ⇒ Boolean
Returns true if the pid exist and the process is running
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/forever/base.rb', line 287 def running?(silent=false) if exists?(pid) current = File.read(pid).to_i print "[\e[90m%s\e[0m] Found pid \e[1m%d\e[0m...\n" % [name, current] unless silent else print "[\e[90m%s\e[0m] Pid \e[1mnot found\e[0m, process seems doesn't exist!\n" % name unless silent return false end is_running = begin Process.kill(0, current) rescue Errno::ESRCH false end is_running end |
#stop ⇒ Object
Perform a soft stop
234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/forever/base.rb', line 234 def stop if running? print "[\e[90m%s\e[0m] Waiting the daemon\'s death " % name FileUtils.touch(stop_txt) while running?(true) print '.'; $stdout.flush sleep 1 end print " \e[1mDONE\e[0m\n" end end |
#stop! ⇒ Object
Search if there is a running process and stop it
218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/forever/base.rb', line 218 def stop! FileUtils.rm_f(stop_txt) if running? pid_was = File.read(pid).to_i print "[\e[90m%s\e[0m] Killing process \e[1m%d\e[0m...\n" % [name, pid_was] filters[:after][:all].each { |block| safe_call(block) } clean_tmp! Process.kill(:KILL, pid_was) else print "[\e[90m%s\e[0m] Process with \e[1mnot found\e[0m" % name end end |
#tmp ⇒ Object
Temp directory, used to store pids and jobs status
191 192 193 |
# File 'lib/forever/base.rb', line 191 def tmp File.join(dir, 'tmp') end |
#to_s ⇒ Object Also known as: inspect
Convert forever object in a readable string showing current config
331 332 333 |
# File 'lib/forever/base.rb', line 331 def to_s "#<Forever dir:#{dir}, file:#{file}, log:#{log}, pid:#{pid} jobs:#{jobs.size}>" end |