Module: Nyara

Defined in:
lib/nyara.rb,
lib/nyara/test.rb,
lib/nyara/view.rb,
lib/nyara/part.rb,
lib/nyara/nyara.rb,
lib/nyara/route.rb,
lib/nyara/flash.rb,
lib/nyara/cookie.rb,
lib/nyara/config.rb,
lib/nyara/reload.rb,
lib/nyara/session.rb,
lib/nyara/command.rb,
lib/nyara/request.rb,
lib/nyara/mime_types.rb,
lib/nyara/controller.rb,
lib/nyara/cpu_counter.rb,
lib/nyara/hashes/param_hash.rb,
lib/nyara/view_handlers/erb.rb,
lib/nyara/hashes/header_hash.rb,
lib/nyara/hashes/config_hash.rb,
lib/nyara/view_handlers/slim.rb,
lib/nyara/view_handlers/haml.rb,
lib/nyara/view_handlers/erubis.rb,
ext/nyara.c

Defined Under Namespace

Modules: Cookie, Ext, Reload, Test Classes: Command, ConfigHash, Controller, CpuCounter, Flash, HeaderHash, NyaraConfig, ParamHash, Part, Request, Route, Session, SimpleController, View

Constant Summary collapse

HTTP_STATUS_FIRST_LINES =
Hash[HTTP_STATUS_CODES.map{|k,v|[k, "HTTP/1.1 #{k} #{v}\r\n".freeze]}].freeze
HTTP_REDIRECT_STATUS =
[300, 301, 302, 303, 307]
OK_RESP_HEADER =

Base header response for 200
Caveat: these entries can not be deleted

HeaderHash.new
START_CTX =
{
  0 => $0.dup,
  argv: ARGV.map(&:dup),
  cwd: (begin
    a = File.stat(pwd = ENV['PWD'])
    b = File.stat(Dir.pwd)
    a.ino == b.ino && a.dev == b.dev ? pwd : Dir.pwd
  rescue
    Dir.pwd
  end)
}
Config =

see NyaraConfig for options

NyaraConfig.new

Class Method Summary collapse

Class Method Details

.configObject

Raises:

  • (ArgumentError)

59
60
61
62
# File 'lib/nyara/nyara.rb', line 59

def config
  raise ArgumentError, 'block not accepted, did you mean Nyara::Config.config?' if block_given?
  Config
end

.patch_tcp_socketObject


113
114
115
116
117
118
# File 'lib/nyara/nyara.rb', line 113

def patch_tcp_socket
  if l = logger
    l.info "patching TCPSocket"
  end
  require_relative "patches/tcp_socket"
end

.setupObject


72
73
74
75
76
77
78
# File 'lib/nyara/nyara.rb', line 72

def setup
  Session.init
  Config.init
  Route.compile
  # todo lint if SomeController#request, send_header are re-defined
  View.init
end

.start_development_server(port) ⇒ Object


120
121
122
123
124
125
126
127
128
129
# File 'lib/nyara/nyara.rb', line 120

def start_development_server port
  create_tcp_server port
  @workers = []
  incr_workers nil

  trap :INT, &method(:kill_all)
  trap :QUIT, &method(:kill_all)
  trap :TERM, &method(:kill_all)
  Process.waitall
end

.start_production_server(port) ⇒ Object

Signals:

  • INT - kill -9 all workers, and exit
  • QUIT - graceful quit all workers, and exit if all children terminated
  • TERM - same as QUIT
  • USR1 - restore worker number
  • USR2 - graceful spawn a new master and workers, with all content respawned
  • TTIN - increase worker number
  • TTOUT - decrease worker number

To make a graceful hot-restart:

  1. USR2 -> old master
  2. if good (workers are up, etc), QUIT -> old master, else QUIT -> new master and fail
  3. if good (requests are working, etc), INT -> old master else QUIT -> new master and USR1 -> old master to restore workers
  • NOTE in step 2/3 if an additional fork executed in new master and hangs,
    you may need send an additional INT to terminate it.
  • NOTE hot-restart reloads almost everything, including Gemfile changes and configures except port.
    but, if some critical environment variable or port configure needs change, you still need cold-restart.
  • TODO write to a file to show workers are good
  • TODO detect port config change

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/nyara/nyara.rb', line 154

def start_production_server port
  workers = Config[:workers]

  puts "workers: #{workers}"
  create_tcp_server port

  GC.start
  @workers = []
  workers.times do
    incr_workers nil
  end

  trap :INT,  &method(:kill_all)
  trap :QUIT, &method(:quit_all)
  trap :TERM, &method(:quit_all)
  trap :USR2, &method(:spawn_new_master)
  trap :USR1, &method(:restore_workers)
  trap :TTIN do
    if Config[:workers] > 1
      Config[:workers] -= 1
      decr_workers nil
    end
  end
  trap :TTOU do
    Config[:workers] += 1
    incr_workers nil
  end
  Process.waitall
end

.start_serverObject


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/nyara/nyara.rb', line 80

def start_server
  reconfig_with_command_line_options
  Process.daemon if Config['daemon']
  port = Config['port']
  env = Config['env']

  if l = logger
    l.info "starting #{env} server at 0.0.0.0:#{port}"
  end
  case env.to_s
  when 'production'
    start_production_server port
  when 'test'
    # don't
  else
    start_watch
    start_development_server port
  end
end

.start_watchObject


100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/nyara/nyara.rb', line 100

def start_watch
  if Config['watch_assets']
    Process.fork do
      exec 'bundle exec linner watch'
    end
  end
  if Config['watch']
    require_relative "reload"
    Reload.listen
    @reload = Reload
  end
end