Class: Vegas::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/vegas/runner.rb

Constant Summary collapse

ROOT_DIR =
File.expand_path(File.join('~', '.vegas'))
PORT =
5678
HOST =
WINDOWS ? 'localhost' : '0.0.0.0'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, app_name, set_options = {}, runtime_args = ARGV, &block) ⇒ Runner

Returns a new instance of Runner.



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
# File 'lib/vegas/runner.rb', line 21

def initialize(app, app_name, set_options = {}, runtime_args = ARGV, &block)
  # initialize
  @app                    = app
  @app_name               = app_name
  @options                = set_options || {}
  @runtime_args           = runtime_args
  self.class.logger.level = options[:debug] ? Logger::DEBUG : Logger::INFO
        
  @rack_handler = @app.respond_to?(:detect_rack_handler) ? 
    @app.send(:detect_rack_handler) : Rack::Handler.get('thin')
  # load options from opt parser
  @args = define_options do |opts|
    if block_given?
      opts.separator ''
      opts.separator "#{app_name} options:"
      yield(self, opts, app)
    end
  end

  # set app options
  @host = options[:host] || HOST
  @app.set(options) if @app.respond_to?(:set)
  # initialize app dir
  FileUtils.mkdir_p(app_dir)
  return if options[:start] === false
  # evaluate the launch_path
  path = if options[:launch_path] && options[:launch_path].respond_to?(:call)
    options[:launch_path].call(self)
  else
    options[:launch_path]
  end
  start(path)
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



15
16
17
# File 'lib/vegas/runner.rb', line 15

def app
  @app
end

#app_nameObject (readonly)

Returns the value of attribute app_name.



15
16
17
# File 'lib/vegas/runner.rb', line 15

def app_name
  @app_name
end

#argsObject (readonly)

Returns the value of attribute args.



15
16
17
# File 'lib/vegas/runner.rb', line 15

def args
  @args
end

#hostObject (readonly)

Returns the value of attribute host.



15
16
17
# File 'lib/vegas/runner.rb', line 15

def host
  @host
end

#optionsObject (readonly)

Returns the value of attribute options.



15
16
17
# File 'lib/vegas/runner.rb', line 15

def options
  @options
end

#portObject (readonly)

Returns the value of attribute port.



15
16
17
# File 'lib/vegas/runner.rb', line 15

def port
  @port
end

#rack_handlerObject (readonly)

Returns the value of attribute rack_handler.



15
16
17
# File 'lib/vegas/runner.rb', line 15

def rack_handler
  @rack_handler
end

Class Method Details

.loggerObject



190
191
192
193
194
195
196
197
198
# File 'lib/vegas/runner.rb', line 190

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



186
187
188
# File 'lib/vegas/runner.rb', line 186

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

Instance Method Details

#app_dirObject



55
56
57
# File 'lib/vegas/runner.rb', line 55

def app_dir
  File.join(ROOT_DIR, app_name)
end

#check_for_running(path = nil) ⇒ Object



119
120
121
122
123
124
125
126
127
128
# File 'lib/vegas/runner.rb', line 119

def check_for_running(path = nil)
  if File.exists?(pid_file) && File.exists?(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!
    end
  end
end

#daemonize!Object

Adapted from Rackup



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/vegas/runner.rb', line 142

def daemonize!
  if RUBY_VERSION < "1.9"
    logger.debug "Parent Process: #{Process.pid}"
    exit! if fork
    logger.debug "Child Process: #{Process.pid}"
    Dir.chdir "/"
    File.umask 0000
    FileUtils.touch(log_file)
    STDIN.reopen  log_file
    STDOUT.reopen log_file, "a"
    STDERR.reopen log_file, "a"
  else
    Process.daemon
  end
  logger.debug "Child Process: #{Process.pid}"

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

#find_portObject



91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/vegas/runner.rb', line 91

def find_port
  if @port = options[:port]
    if !port_open?
      logger.warn "Port #{port} is already in use. Please try another or don't use -P, for auto-port"
    end
  else
    @port = PORT
    logger.info "Trying to start #{app_name} on Port #{port}"
    while !port_open?
      @port += 1
      logger.info "Trying to start #{app_name} on Port #{port}"
    end
  end
end

#kill!Object



168
169
170
171
172
173
174
# File 'lib/vegas/runner.rb', line 168

def kill!
  pid = File.read(pid_file)
  logger.warn "Sending INT 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



162
163
164
165
166
# File 'lib/vegas/runner.rb', line 162

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

#log_fileObject



71
72
73
# File 'lib/vegas/runner.rb', line 71

def log_file
  File.join(app_dir, "#{app_name}.log")
end

#loggerObject



200
201
202
# File 'lib/vegas/runner.rb', line 200

def logger
  self.class.logger
end

#pid_fileObject



59
60
61
# File 'lib/vegas/runner.rb', line 59

def pid_file
  File.join(app_dir, "#{app_name}.pid")
end

#port_open?(check_url = nil) ⇒ Boolean

Returns:

  • (Boolean)


106
107
108
109
110
111
112
113
# File 'lib/vegas/runner.rb', line 106

def port_open?(check_url = nil)
  begin
    open(check_url || url)
    false
  rescue Errno::ECONNREFUSED => e
    true
  end
end

#run!Object



130
131
132
133
134
135
136
137
138
139
# File 'lib/vegas/runner.rb', line 130

def run!
  rack_handler.run app, :Host => host, :Port => port do |server|
    trap(kill_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

#start(path = nil) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/vegas/runner.rb', line 75

def start(path = nil)
  logger.info "Running with Windows Settings" if WINDOWS
  logger.info "Starting #{app_name}"
  begin
    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
end

#statusObject



176
177
178
179
180
181
182
183
184
# File 'lib/vegas/runner.rb', line 176

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

#urlObject



67
68
69
# File 'lib/vegas/runner.rb', line 67

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

#url_fileObject



63
64
65
# File 'lib/vegas/runner.rb', line 63

def url_file
  File.join(app_dir, "#{app_name}.url")
end

#write_urlObject



115
116
117
# File 'lib/vegas/runner.rb', line 115

def write_url
  File.open(url_file, 'w') {|f| f << url }
end