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

Returns a new instance of 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

Returns:

  • (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