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 |
# 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' 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 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 KILL).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 << 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| Process.detach(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
315 316 317 318 |
# File 'lib/forever/base.rb', line 315 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
307 308 309 310 |
# File 'lib/forever/base.rb', line 307 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
323 324 325 |
# File 'lib/forever/base.rb', line 323 def config { :dir => dir, :file => file, :log => log, :pid => pid } end |
#dir(value = nil) ⇒ Object Also known as: workspace
Base working Directory
182 183 184 |
# File 'lib/forever/base.rb', line 182 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
147 148 149 |
# File 'lib/forever/base.rb', line 147 def every(period, ={}, &block) jobs << Forever::Job.new(period, .merge!(:dir => dir), &block) end |
#file(value = nil) ⇒ Object
Caller file
161 162 163 |
# File 'lib/forever/base.rb', line 161 def file(value=nil) value ? @_file = value : @_file end |
#jobs ⇒ Object
Our job list
154 155 156 |
# File 'lib/forever/base.rb', line 154 def jobs @_jobs ||= [] end |
#log(value = nil) ⇒ Object
File were we redirect STOUT and STDERR, can be false.
Default: dir + ‘log/.log’
199 200 201 202 |
# File 'lib/forever/base.rb', line 199 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
168 169 170 |
# File 'lib/forever/base.rb', line 168 def name File.basename(file, '.*') end |
#on_error(&block) ⇒ Object
Callback raised when an error occour
258 259 260 |
# File 'lib/forever/base.rb', line 258 def on_error(&block) block_given? ? @_on_error = block : @_on_error end |
#on_exit(&block) ⇒ Object
Callback raised when at exit
272 273 274 |
# File 'lib/forever/base.rb', line 272 def on_exit(&block) after(:all, &block) end |
#on_limit_exceeded(&block) ⇒ Object
Callback raised when queue limit was exceeded
265 266 267 |
# File 'lib/forever/base.rb', line 265 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)
279 280 281 |
# File 'lib/forever/base.rb', line 279 def on_ready(&block) before(:all, &block) end |
#pid(value = nil) ⇒ Object
File were we store pid
Default: dir + ‘tmp/.pid’
209 210 211 212 |
# File 'lib/forever/base.rb', line 209 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
175 176 177 |
# File 'lib/forever/base.rb', line 175 def queue(value=nil) value ? @_queue = value : @_queue end |
#remove ⇒ Object
Remove the daemon from the config file
248 249 250 251 252 253 |
# File 'lib/forever/base.rb', line 248 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
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/forever/base.rb', line 286 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
233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/forever/base.rb', line 233 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
217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/forever/base.rb', line 217 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
190 191 192 |
# File 'lib/forever/base.rb', line 190 def tmp File.join(dir, 'tmp') end |
#to_s ⇒ Object Also known as: inspect
Convert forever object in a readable string showing current config
330 331 332 |
# File 'lib/forever/base.rb', line 330 def to_s "#<Forever dir:#{dir}, file:#{file}, log:#{log}, pid:#{pid} jobs:#{jobs.size}>" end |