puma 0.8.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- data/Manifest.txt +6 -18
- data/Rakefile +86 -8
- data/bin/puma +1 -0
- data/bin/pumactl +12 -0
- data/lib/puma.rb +0 -3
- data/lib/puma/app/status.rb +37 -0
- data/lib/puma/cli.rb +161 -5
- data/lib/puma/const.rb +35 -2
- data/lib/puma/control_cli.rb +112 -0
- data/lib/puma/events.rb +18 -0
- data/lib/puma/null_io.rb +35 -0
- data/lib/puma/rack_patch.rb +4 -1
- data/lib/puma/server.rb +178 -76
- data/lib/puma/thread_pool.rb +51 -0
- data/puma.gemspec +5 -5
- data/test/ab_rs.rb +22 -0
- data/test/test_app_status.rb +69 -0
- data/test/test_cli.rb +91 -5
- data/test/test_http11.rb +1 -18
- data/test/test_persistent.rb +3 -3
- data/test/test_rack_server.rb +6 -0
- data/test/test_thread_pool.rb +24 -0
- metadata +31 -27
- data/.gemtest +0 -0
- data/examples/builder.rb +0 -29
- data/examples/camping/README +0 -3
- data/examples/camping/blog.rb +0 -294
- data/examples/camping/tepee.rb +0 -149
- data/examples/httpd.conf +0 -474
- data/examples/mime.yaml +0 -3
- data/examples/mongrel.conf +0 -9
- data/examples/monitrc +0 -57
- data/examples/random_thrash.rb +0 -19
- data/examples/simpletest.rb +0 -52
- data/examples/webrick_compare.rb +0 -20
- data/lib/puma/gems.rb +0 -20
- data/lib/puma/mime_types.yml +0 -616
- data/lib/puma/utils.rb +0 -44
- data/tasks/gem.rake +0 -24
- data/tasks/java.rake +0 -12
- data/tasks/native.rake +0 -36
- data/tasks/ragel.rake +0 -24
data/Manifest.txt
CHANGED
@@ -7,17 +7,7 @@ README.md
|
|
7
7
|
Rakefile
|
8
8
|
TODO
|
9
9
|
bin/puma
|
10
|
-
|
11
|
-
examples/camping/README
|
12
|
-
examples/camping/blog.rb
|
13
|
-
examples/camping/tepee.rb
|
14
|
-
examples/httpd.conf
|
15
|
-
examples/mime.yaml
|
16
|
-
examples/mongrel.conf
|
17
|
-
examples/monitrc
|
18
|
-
examples/random_thrash.rb
|
19
|
-
examples/simpletest.rb
|
20
|
-
examples/webrick_compare.rb
|
10
|
+
bin/pumactl
|
21
11
|
ext/puma_http11/PumaHttp11Service.java
|
22
12
|
ext/puma_http11/ext_help.h
|
23
13
|
ext/puma_http11/extconf.rb
|
@@ -30,23 +20,21 @@ ext/puma_http11/org/jruby/puma/Http11.java
|
|
30
20
|
ext/puma_http11/org/jruby/puma/Http11Parser.java
|
31
21
|
ext/puma_http11/puma_http11.c
|
32
22
|
lib/puma.rb
|
23
|
+
lib/puma/app/status.rb
|
33
24
|
lib/puma/cli.rb
|
34
25
|
lib/puma/const.rb
|
26
|
+
lib/puma/control_cli.rb
|
35
27
|
lib/puma/events.rb
|
36
|
-
lib/puma/
|
37
|
-
lib/puma/mime_types.yml
|
28
|
+
lib/puma/null_io.rb
|
38
29
|
lib/puma/rack_patch.rb
|
39
30
|
lib/puma/server.rb
|
40
31
|
lib/puma/thread_pool.rb
|
41
|
-
lib/puma/utils.rb
|
42
32
|
lib/rack/handler/puma.rb
|
43
33
|
puma.gemspec
|
44
|
-
|
45
|
-
tasks/java.rake
|
46
|
-
tasks/native.rake
|
47
|
-
tasks/ragel.rake
|
34
|
+
test/ab_rs.rb
|
48
35
|
test/lobster.ru
|
49
36
|
test/mime.yaml
|
37
|
+
test/test_app_status.rb
|
50
38
|
test/test_cli.rb
|
51
39
|
test/test_http10.rb
|
52
40
|
test/test_http11.rb
|
data/Rakefile
CHANGED
@@ -1,12 +1,90 @@
|
|
1
|
-
#
|
2
|
-
# NOTE: Keep this file clean.
|
3
|
-
# Add your customizations inside tasks directory.
|
4
|
-
# Thank You.
|
5
|
-
#
|
6
|
-
|
7
1
|
require 'rubygems'
|
8
2
|
|
3
|
+
require 'hoe'
|
4
|
+
|
9
5
|
IS_JRUBY = defined?(RUBY_ENGINE) ? RUBY_ENGINE == "jruby" : false
|
10
6
|
|
11
|
-
|
12
|
-
|
7
|
+
HOE = Hoe.spec 'puma' do
|
8
|
+
self.rubyforge_name = 'puma'
|
9
|
+
self.readme_file = "README.md"
|
10
|
+
developer 'Evan Phoenix', 'evan@phx.io'
|
11
|
+
|
12
|
+
spec_extras[:extensions] = ["ext/puma_http11/extconf.rb"]
|
13
|
+
spec_extras[:executables] = ['puma', 'pumactl']
|
14
|
+
|
15
|
+
dependency 'rack', '~> 1.2'
|
16
|
+
|
17
|
+
extra_dev_deps << ['rake-compiler', "~> 0.7.0"]
|
18
|
+
|
19
|
+
clean_globs.push('test_*.log', 'log')
|
20
|
+
end
|
21
|
+
|
22
|
+
task :test => [:compile]
|
23
|
+
|
24
|
+
# hoe/test and rake-compiler don't seem to play well together, so disable
|
25
|
+
# hoe/test's .gemtest touch file thingy for now
|
26
|
+
HOE.spec.files -= [".gemtest"]
|
27
|
+
|
28
|
+
file "#{HOE.spec.name}.gemspec" => ['Rakefile'] do |t|
|
29
|
+
puts "Generating #{t.name}"
|
30
|
+
File.open(t.name, 'w') { |f| f.puts HOE.spec.to_ruby }
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Generate or update the standalone gemspec file for the project"
|
34
|
+
task :gemspec => ["#{HOE.spec.name}.gemspec"]
|
35
|
+
|
36
|
+
# the following tasks ease the build of C file from Ragel one
|
37
|
+
|
38
|
+
file 'ext/puma_http11/http11_parser.c' => ['ext/puma_http11/http11_parser.rl'] do |t|
|
39
|
+
begin
|
40
|
+
sh "ragel #{t.prerequisites.last} -C -G2 -o #{t.name}"
|
41
|
+
rescue
|
42
|
+
fail "Could not build wrapper using Ragel (it failed or not installed?)"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
file 'ext/puma_http11/org/jruby/puma/Http11Parser.java' => ['ext/puma_http11/http11_parser.java.rl'] do |t|
|
47
|
+
begin
|
48
|
+
sh "ragel #{t.prerequisites.last} -J -G2 -o #{t.name}"
|
49
|
+
rescue
|
50
|
+
fail "Could not build wrapper using Ragel (it failed or not installed?)"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if IS_JRUBY
|
55
|
+
require 'rake/javaextensiontask'
|
56
|
+
|
57
|
+
# build http11 java extension
|
58
|
+
Rake::JavaExtensionTask.new('puma_http11', HOE.spec)
|
59
|
+
|
60
|
+
task :ragel => 'ext/puma_http11/org/jruby/puma/Http11Parser.java'
|
61
|
+
else
|
62
|
+
# use rake-compiler for building the extension
|
63
|
+
require 'rake/extensiontask'
|
64
|
+
|
65
|
+
# build http11 C extension
|
66
|
+
Rake::ExtensionTask.new('puma_http11', HOE.spec) do |ext|
|
67
|
+
# define target for extension (supporting fat binaries)
|
68
|
+
if RUBY_PLATFORM =~ /mingw|mswin/ then
|
69
|
+
RUBY_VERSION =~ /(\d+\.\d+)/
|
70
|
+
ext.lib_dir = "lib/#{$1}"
|
71
|
+
elsif ENV['CROSS']
|
72
|
+
# define cross-compilation tasks when not on Windows.
|
73
|
+
ext.cross_compile = true
|
74
|
+
ext.cross_platform = ['i386-mswin32', 'i386-mingw32']
|
75
|
+
end
|
76
|
+
|
77
|
+
# cleanup versioned library directory
|
78
|
+
CLEAN.include 'lib/{1.8,1.9}'
|
79
|
+
end
|
80
|
+
|
81
|
+
task :ragel => 'ext/puma_http11/http11_parser.c'
|
82
|
+
end
|
83
|
+
|
84
|
+
task :ext_clean do
|
85
|
+
sh "rm -rf lib/puma_http11.bundle"
|
86
|
+
sh "rm -rf lib/puma_http11.jar"
|
87
|
+
sh "rm -rf lib/puma_http11.so"
|
88
|
+
end
|
89
|
+
|
90
|
+
task :clean => :ext_clean
|
data/bin/puma
CHANGED
data/bin/pumactl
ADDED
data/lib/puma.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Puma
|
2
|
+
module App
|
3
|
+
class Status
|
4
|
+
def initialize(server, cli)
|
5
|
+
@server = server
|
6
|
+
@cli = cli
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
case env['PATH_INFO']
|
11
|
+
when "/stop"
|
12
|
+
@server.stop
|
13
|
+
return [200, {}, ['{ "status": "ok" }']]
|
14
|
+
|
15
|
+
when "/halt"
|
16
|
+
@server.halt
|
17
|
+
return [200, {}, ['{ "status": "ok" }']]
|
18
|
+
|
19
|
+
when "/restart"
|
20
|
+
if @cli and @cli.restart_on_stop!
|
21
|
+
@server.stop
|
22
|
+
return [200, {}, ['{ "status": "ok" }']]
|
23
|
+
else
|
24
|
+
return [200, {}, ['{ "status": "not configured" }']]
|
25
|
+
end
|
26
|
+
|
27
|
+
when "/stats"
|
28
|
+
b = @server.backlog
|
29
|
+
r = @server.running
|
30
|
+
return [200, {}, ["{ \"backlog\": #{b}, \"running\": #{r} }"]]
|
31
|
+
end
|
32
|
+
|
33
|
+
[404, {}, ["Unsupported action"]]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/puma/cli.rb
CHANGED
@@ -7,10 +7,20 @@ require 'puma/const'
|
|
7
7
|
require 'rack/commonlogger'
|
8
8
|
|
9
9
|
module Puma
|
10
|
+
# Handles invoke a Puma::Server in a command line style.
|
11
|
+
#
|
10
12
|
class CLI
|
11
13
|
DefaultTCPHost = "0.0.0.0"
|
12
14
|
DefaultTCPPort = 9292
|
13
15
|
|
16
|
+
IS_JRUBY = defined?(JRUBY_VERSION)
|
17
|
+
|
18
|
+
# Create a new CLI object using +argv+ as the command line
|
19
|
+
# arguments.
|
20
|
+
#
|
21
|
+
# +stdout+ and +stderr+ can be set to IO-like objects which
|
22
|
+
# this object will report status on.
|
23
|
+
#
|
14
24
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
15
25
|
@argv = argv
|
16
26
|
@stdout = stdout
|
@@ -18,18 +28,78 @@ module Puma
|
|
18
28
|
|
19
29
|
@events = Events.new @stdout, @stderr
|
20
30
|
|
31
|
+
@server = nil
|
32
|
+
@status = nil
|
33
|
+
|
34
|
+
@restart = false
|
35
|
+
@temp_status_path = nil
|
36
|
+
|
21
37
|
setup_options
|
38
|
+
|
39
|
+
generate_restart_data
|
40
|
+
end
|
41
|
+
|
42
|
+
def restart_on_stop!
|
43
|
+
if @restart_argv
|
44
|
+
@restart = true
|
45
|
+
return true
|
46
|
+
else
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def generate_restart_data
|
52
|
+
# Use the same trick as unicorn, namely favor PWD because
|
53
|
+
# it will contain an unresolved symlink, useful for when
|
54
|
+
# the pwd is /data/releases/current.
|
55
|
+
if dir = ENV['PWD']
|
56
|
+
s_env = File.stat(dir)
|
57
|
+
s_pwd = File.stat(Dir.pwd)
|
58
|
+
|
59
|
+
if s_env.ino == s_pwd.ino and s_env.dev == s_pwd.dev
|
60
|
+
@restart_dir = dir
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
@restart_dir ||= Dir.pwd
|
65
|
+
|
66
|
+
if defined? Rubinius::OS_ARGV
|
67
|
+
@restart_argv = Rubinius::OS_ARGV
|
68
|
+
else
|
69
|
+
require 'rubygems'
|
70
|
+
|
71
|
+
# if $0 is a file in the current directory, then restart
|
72
|
+
# it the same, otherwise add -S on there because it was
|
73
|
+
# picked up in PATH.
|
74
|
+
#
|
75
|
+
if File.exists?($0)
|
76
|
+
@restart_argv = [Gem.ruby, $0] + ARGV
|
77
|
+
else
|
78
|
+
@restart_argv = [Gem.ruby, "-S", $0] + ARGV
|
79
|
+
end
|
80
|
+
end
|
22
81
|
end
|
23
82
|
|
83
|
+
def restart!
|
84
|
+
Dir.chdir @restart_dir
|
85
|
+
Kernel.exec(*@restart_argv)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Write +str+ to +@stdout+
|
89
|
+
#
|
24
90
|
def log(str)
|
25
91
|
@stdout.puts str
|
26
92
|
end
|
27
93
|
|
94
|
+
# Write +str+ to +@stderr+
|
95
|
+
#
|
28
96
|
def error(str)
|
29
97
|
@stderr.puts "ERROR: #{str}"
|
30
98
|
exit 1
|
31
99
|
end
|
32
100
|
|
101
|
+
# Build the OptionParser object to handle the available options.
|
102
|
+
#
|
33
103
|
def setup_options
|
34
104
|
@options = {
|
35
105
|
:min_threads => 0,
|
@@ -63,6 +133,27 @@ module Puma
|
|
63
133
|
end
|
64
134
|
end
|
65
135
|
|
136
|
+
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
|
137
|
+
@options[:state] = arg
|
138
|
+
end
|
139
|
+
|
140
|
+
o.on "--status [URL]", "The bind url to use for the status server" do |arg|
|
141
|
+
if arg and arg != "@"
|
142
|
+
@options[:status_address] = arg
|
143
|
+
elsif IS_JRUBY
|
144
|
+
raise NotImplementedError, "No default url available on JRuby"
|
145
|
+
else
|
146
|
+
require 'tmpdir'
|
147
|
+
|
148
|
+
t = (Time.now.to_f * 1000).to_i
|
149
|
+
path = "#{Dir.tmpdir}/puma-status-#{t}-#{$$}"
|
150
|
+
|
151
|
+
@temp_status_path = path
|
152
|
+
|
153
|
+
@options[:status_address] = "unix://#{path}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
66
157
|
end
|
67
158
|
|
68
159
|
@parser.banner = "puma <options> <rackup file>"
|
@@ -73,6 +164,9 @@ module Puma
|
|
73
164
|
end
|
74
165
|
end
|
75
166
|
|
167
|
+
# Load the specified rackup file, pull an options from
|
168
|
+
# the rackup file, and set @app.
|
169
|
+
#
|
76
170
|
def load_rackup
|
77
171
|
@app, options = Rack::Builder.parse_file @rackup
|
78
172
|
@options.merge! options
|
@@ -84,6 +178,9 @@ module Puma
|
|
84
178
|
end
|
85
179
|
end
|
86
180
|
|
181
|
+
# If configured, write the pid of the current process out
|
182
|
+
# to a file.
|
183
|
+
#
|
87
184
|
def write_pid
|
88
185
|
if path = @options[:pidfile]
|
89
186
|
File.open(path, "w") do |f|
|
@@ -92,14 +189,34 @@ module Puma
|
|
92
189
|
end
|
93
190
|
end
|
94
191
|
|
192
|
+
def write_state
|
193
|
+
require 'yaml'
|
194
|
+
|
195
|
+
if path = @options[:state]
|
196
|
+
state = { "pid" => Process.pid }
|
197
|
+
|
198
|
+
if url = @options[:status_address]
|
199
|
+
state["status_address"] = url
|
200
|
+
end
|
201
|
+
|
202
|
+
File.open(path, "w") do |f|
|
203
|
+
f.write state.to_yaml
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# :nodoc:
|
95
209
|
def parse_options
|
96
210
|
@parser.parse! @argv
|
97
211
|
end
|
98
212
|
|
213
|
+
# Parse the options, load the rackup, start the server and wait
|
214
|
+
# for it to finish.
|
215
|
+
#
|
99
216
|
def run
|
100
217
|
parse_options
|
101
218
|
|
102
|
-
@rackup =
|
219
|
+
@rackup = @argv.shift || "config.ru"
|
103
220
|
|
104
221
|
unless File.exists?(@rackup)
|
105
222
|
raise "Missing rackup file '#{@rackup}'"
|
@@ -107,8 +224,9 @@ module Puma
|
|
107
224
|
|
108
225
|
load_rackup
|
109
226
|
write_pid
|
227
|
+
write_state
|
110
228
|
|
111
|
-
unless @quiet
|
229
|
+
unless @options[:quiet]
|
112
230
|
@app = Rack::CommonLogger.new(@app, STDOUT)
|
113
231
|
end
|
114
232
|
|
@@ -148,8 +266,33 @@ module Puma
|
|
148
266
|
end
|
149
267
|
end
|
150
268
|
|
151
|
-
|
152
|
-
|
269
|
+
@server = server
|
270
|
+
|
271
|
+
if str = @options[:status_address]
|
272
|
+
require 'puma/app/status'
|
273
|
+
|
274
|
+
uri = URI.parse str
|
275
|
+
|
276
|
+
app = Puma::App::Status.new server, self
|
277
|
+
status = Puma::Server.new app, @events
|
278
|
+
status.min_threads = 0
|
279
|
+
status.max_threads = 1
|
280
|
+
|
281
|
+
case uri.scheme
|
282
|
+
when "tcp"
|
283
|
+
log "* Starting status server on #{str}"
|
284
|
+
status.add_tcp_listener uri.host, uri.port
|
285
|
+
when "unix"
|
286
|
+
log "* Starting status server on #{str}"
|
287
|
+
path = "#{uri.host}#{uri.path}"
|
288
|
+
|
289
|
+
status.add_unix_listener path
|
290
|
+
else
|
291
|
+
error "Invalid status URI: #{str}"
|
292
|
+
end
|
293
|
+
|
294
|
+
status.run
|
295
|
+
@status = status
|
153
296
|
end
|
154
297
|
|
155
298
|
log "Use Ctrl-C to stop"
|
@@ -157,8 +300,21 @@ module Puma
|
|
157
300
|
begin
|
158
301
|
server.run.join
|
159
302
|
rescue Interrupt
|
160
|
-
log " -
|
303
|
+
log " - Gracefully stopping, waiting for requests to finish"
|
304
|
+
server.stop(true)
|
305
|
+
log " - Goodbye!"
|
161
306
|
end
|
307
|
+
|
308
|
+
File.unlink @temp_status_path if @temp_status_path
|
309
|
+
|
310
|
+
if @restart
|
311
|
+
log "* Restarting..."
|
312
|
+
restart!
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def stop
|
317
|
+
@server.stop(true) if @server
|
162
318
|
end
|
163
319
|
end
|
164
320
|
end
|