Class: Resque::WebRunner

Inherits:
Object
  • Object
show all
Defined in:
lib/resque/web_runner.rb

Defined Under Namespace

Classes: Parser

Constant Summary collapse

PORT =
5678
HOST =
WINDOWS ? 'localhost' : '0.0.0.0'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*runtime_args) ⇒ WebRunner



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
# File 'lib/resque/web_runner.rb', line 22

def initialize(*runtime_args)
  @options = runtime_args.last.is_a?(Hash) ? runtime_args.pop : {}

  self.class.logger.level = options[:debug] ? Logger::DEBUG : Logger::INFO

  @app      = Resque::Server
  @app_name = 'resque-web'
  @filesystem_friendly_app_name = @app_name.gsub(/\W+/, "_")

  @args = load_options(runtime_args)

  @rack_handler = (s = options[:rack_handler]) ? Rack::Handler.get(s) : setup_rack_handler

  case option_parser.command
  when :help
    puts option_parser
  when :kill
    kill!
  when :status
    status
  when :version
    puts "resque #{Resque::VERSION}"
    puts "rack #{Rack::VERSION.join('.')}"
    puts "sinatra #{Sinatra::VERSION}" if defined?(Sinatra)
  else
    before_run
    start unless options[:start] == false
  end
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



16
17
18
# File 'lib/resque/web_runner.rb', line 16

def app
  @app
end

#app_nameObject (readonly)

Returns the value of attribute app_name.



16
17
18
# File 'lib/resque/web_runner.rb', line 16

def app_name
  @app_name
end

#argsObject (readonly)

Returns the value of attribute args.



16
17
18
# File 'lib/resque/web_runner.rb', line 16

def args
  @args
end

#filesystem_friendly_app_nameObject (readonly)

Returns the value of attribute filesystem_friendly_app_name.



16
17
18
# File 'lib/resque/web_runner.rb', line 16

def filesystem_friendly_app_name
  @filesystem_friendly_app_name
end

#optionsObject (readonly)

Returns the value of attribute options.



16
17
18
# File 'lib/resque/web_runner.rb', line 16

def options
  @options
end

#portObject (readonly)

Returns the value of attribute port.



16
17
18
# File 'lib/resque/web_runner.rb', line 16

def port
  @port
end

#rack_handlerObject (readonly)

Returns the value of attribute rack_handler.



16
17
18
# File 'lib/resque/web_runner.rb', line 16

def rack_handler
  @rack_handler
end

Class Method Details

.loggerObject



259
260
261
262
263
264
265
266
267
# File 'lib/resque/web_runner.rb', line 259

def self.logger
  @logger ||= LOGGER if defined?(LOGGER)
  if !@logger
    @logger           = Logger.new(STDOUT)
    @logger.formatter = Proc.new {|s, t, n, msg| "[#{t}] #{msg}\n"}
    @logger
  end
  @logger
end

.logger=(logger) ⇒ Object



255
256
257
# File 'lib/resque/web_runner.rb', line 255

def self.logger=(logger)
  @logger = logger
end

Instance Method Details

#announce_port_attemptedObject



140
141
142
# File 'lib/resque/web_runner.rb', line 140

def announce_port_attempted
  logger.info "trying port #{port}..."
end

#app_dirObject



60
61
62
63
64
65
# File 'lib/resque/web_runner.rb', line 60

def app_dir
  if !options[:app_dir] && !ENV['HOME']
    raise ArgumentError.new("nor --app-dir neither ENV['HOME'] defined")
  end
  options[:app_dir] || File.join(ENV['HOME'], filesystem_friendly_app_name)
end

#before_runObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/resque/web_runner.rb', line 87

def before_run
  if (redis_conf = options[:redis_conf])
    logger.info "Using Redis connection '#{redis_conf}'"
    Resque.redis = redis_conf
  end
  if (namespace = options[:redis_namespace])
    logger.info "Using Redis namespace '#{namespace}'"
    Resque.redis.namespace = namespace
  end
  if (url_prefix = options[:url_prefix])
    logger.info "Using URL Prefix '#{url_prefix}'"
    Resque::Server.url_prefix = url_prefix
  end
  app.set(options.merge web_runner: self)
  path = (ENV['RESQUECONFIG'] || args.first)
  load_config_file(path.to_s.strip) if path
end

#check_for_running(path = nil) ⇒ Object



164
165
166
167
168
169
170
171
172
173
# File 'lib/resque/web_runner.rb', line 164

def check_for_running(path = nil)
  if File.exist?(pid_file) && File.exist?(url_file)
    running_url = File.read(url_file)
    if !port_open?(running_url)
      logger.warn "'#{app_name}' is already running at #{running_url}"
      launch!(running_url, path)
      exit!(1)
    end
  end
end

#daemon_executeObject



209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/resque/web_runner.rb', line 209

def daemon_execute
  File.umask 0000
  FileUtils.touch log_file
  STDIN.reopen    log_file
  STDOUT.reopen   log_file, "a"
  STDERR.reopen   log_file, "a"

  logger.debug "Child Process: #{Process.pid}"

  File.open(pid_file, 'w') {|f| f.write("#{Process.pid}") }
  at_exit { delete_pid! }
end

#daemonize!Object

Adapted from Rackup



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/resque/web_runner.rb', line 191

def daemonize!
  if JRUBY
    # It's not a true daemon but when executed with & works like one
    thread = Thread.new {daemon_execute}
    thread.join

  elsif RUBY_VERSION < "1.9"
    logger.debug "Parent Process: #{Process.pid}"
    exit!(0) if fork
    logger.debug "Child Process: #{Process.pid}"
    daemon_execute

  else
    Process.daemon(true, true)
    daemon_execute
  end
end

#find_portObject



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/resque/web_runner.rb', line 121

def find_port
  if @port = options[:port]
    announce_port_attempted

    unless port_open?
      logger.warn "Port #{port} is already in use. Please try another. " +
                  "You can also omit the port flag, and we'll find one for you."
    end
  else
    @port = PORT
    announce_port_attempted

    until port_open?
      @port += 1
      announce_port_attempted
    end
  end
end

#hostObject



79
80
81
# File 'lib/resque/web_runner.rb', line 79

def host
  options.fetch(:host) { HOST }
end

#kill!Object



228
229
230
231
232
233
234
# File 'lib/resque/web_runner.rb', line 228

def kill!
  pid = File.read(pid_file)
  logger.warn "Sending #{kill_command} to #{pid.to_i}"
  Process.kill(kill_command, pid.to_i)
rescue => e
  logger.warn "pid not found at #{pid_file} : #{e}"
end

#launch!(specific_url = nil, path = nil) ⇒ Object



222
223
224
225
226
# File 'lib/resque/web_runner.rb', line 222

def launch!(specific_url = nil, path = nil)
  return if options[:skip_launch]
  cmd = WINDOWS ? "start" : "open"
  system "#{cmd} #{specific_url || url}#{path}"
end

#launch_pathObject



52
53
54
55
56
57
58
# File 'lib/resque/web_runner.rb', line 52

def launch_path
  if options[:launch_path].respond_to?(:call)
    options[:launch_path].call(self)
  else
    options[:launch_path]
  end
end

#load_config_file(config_path) ⇒ Object

Loads a config file at config_path and evals it in the context of the @app.



247
248
249
250
251
252
253
# File 'lib/resque/web_runner.rb', line 247

def load_config_file(config_path)
  abort "Can not find config file at #{config_path}" if !File.readable?(config_path)
  config = File.read(config_path)
  # trim off anything after __END__
  config.sub!(/^__END__\n.*/, '')
  @app.module_eval(config)
end

#log_fileObject



75
76
77
# File 'lib/resque/web_runner.rb', line 75

def log_file
  options[:log_file] || File.join(app_dir, "#{filesystem_friendly_app_name}.log")
end

#loggerObject



269
270
271
# File 'lib/resque/web_runner.rb', line 269

def logger
  self.class.logger
end

#pid_fileObject



67
68
69
# File 'lib/resque/web_runner.rb', line 67

def pid_file
  options[:pid_file] || File.join(app_dir, "#{filesystem_friendly_app_name}.pid")
end

#port_open?(check_url = nil) ⇒ Boolean



144
145
146
147
148
149
150
151
152
# File 'lib/resque/web_runner.rb', line 144

def port_open?(check_url = nil)
  begin
    check_url ||= url
    options[:no_proxy] ? uri_open(check_url, :proxy => nil) : uri_open(check_url)
    false
  rescue Errno::ECONNREFUSED, Errno::EPERM, Errno::ETIMEDOUT
    true
  end
end

#run!Object



175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/resque/web_runner.rb', line 175

def run!
  logger.info "Running with Rack handler: #{@rack_handler.inspect}"

  rack_handler.run app, :Host => host, :Port => port do |server|
    kill_commands.each do |command|
      trap(command) do
        ## Use thins' hard #stop! if available, otherwise just #stop
        server.respond_to?(:stop!) ? server.stop! : server.stop
        logger.info "'#{app_name}' received INT ... stopping"
        delete_pid!
      end
    end
  end
end

#start(path = launch_path) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/resque/web_runner.rb', line 105

def start(path = launch_path)
  logger.info "Running with Windows Settings" if WINDOWS
  logger.info "Running with JRuby" if JRUBY
  logger.info "Starting '#{app_name}'..."

  check_for_running(path)
  find_port
  write_url
  launch!(url, path)
  daemonize! unless options[:foreground]
  run!
rescue RuntimeError => e
  logger.warn "There was an error starting '#{app_name}': #{e}"
  exit
end

#statusObject



236
237
238
239
240
241
242
243
244
# File 'lib/resque/web_runner.rb', line 236

def status
  if File.exist?(pid_file)
    logger.info "'#{app_name}' running"
    logger.info "PID #{File.read(pid_file)}"
    logger.info "URL #{File.read(url_file)}" if File.exist?(url_file)
  else
    logger.info "'#{app_name}' not running!"
  end
end

#uri_open(*args) ⇒ Object



154
155
156
# File 'lib/resque/web_runner.rb', line 154

def uri_open(*args)
  (RbConfig::CONFIG['ruby_version'] < '2.7') ? open(*args) : URI.open(*args)
end

#urlObject



83
84
85
# File 'lib/resque/web_runner.rb', line 83

def url
  "http://#{host}:#{port}"
end

#url_fileObject



71
72
73
# File 'lib/resque/web_runner.rb', line 71

def url_file
  options[:url_file] || File.join(app_dir, "#{filesystem_friendly_app_name}.url")
end

#write_urlObject



158
159
160
161
162
# File 'lib/resque/web_runner.rb', line 158

def write_url
  # Make sure app dir is setup
  FileUtils.mkdir_p(app_dir)
  File.open(url_file, 'w') {|f| f << url }
end