puma 2.5.1 → 2.6.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/History.txt +13 -0
- data/README.md +1 -0
- data/ext/puma_http11/http11_parser.h +1 -0
- data/ext/puma_http11/io_buffer.c +1 -0
- data/ext/puma_http11/mini_ssl.c +1 -0
- data/lib/puma/capistrano.rb +18 -11
- data/lib/puma/cluster.rb +16 -5
- data/lib/puma/const.rb +2 -2
- data/lib/puma/events.rb +22 -0
- data/lib/puma/server.rb +16 -0
- data/lib/puma/single.rb +1 -1
- data/test/test_puma_server.rb +23 -0
- metadata +2 -2
data/History.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
=== 2.6.0 / 2013-09-13
|
2
|
+
|
3
|
+
* 2 minor features:
|
4
|
+
* Add support for event hooks
|
5
|
+
** Add a hook for state transitions
|
6
|
+
* Add phased restart to capistrano recipe.
|
7
|
+
|
8
|
+
* 4 bug fixes:
|
9
|
+
* Convince workers to stop by SIGKILL after timeout
|
10
|
+
* Define RSTRING_NOT_MODIFIED for Rubinius performance
|
11
|
+
* Handle BrokenPipe, StandardError and IOError in fat_wrote and break out
|
12
|
+
* Return success status to the invoking environment
|
13
|
+
|
1
14
|
=== 2.5.1 / 2013-08-13
|
2
15
|
|
3
16
|
* 2 bug fixes:
|
data/README.md
CHANGED
data/ext/puma_http11/io_buffer.c
CHANGED
data/ext/puma_http11/mini_ssl.c
CHANGED
data/lib/puma/capistrano.rb
CHANGED
@@ -8,34 +8,41 @@ Capistrano::Configuration.instance.load do
|
|
8
8
|
# v2 but is fixed in v3.
|
9
9
|
shared_children.push('tmp/sockets')
|
10
10
|
|
11
|
-
_cset(:puma_cmd)
|
11
|
+
_cset(:puma_cmd) { "#{fetch(:bundle_cmd, 'bundle')} exec puma" }
|
12
12
|
_cset(:pumactl_cmd) { "#{fetch(:bundle_cmd, 'bundle')} exec pumactl" }
|
13
|
-
_cset(:
|
13
|
+
_cset(:puma_env) { fetch(:rack_env, fetch(:rails_env, 'production')) }
|
14
|
+
_cset(:puma_state) { "#{shared_path}/sockets/puma.state" }
|
14
15
|
_cset(:puma_socket) { "unix://#{shared_path}/sockets/puma.sock" }
|
15
|
-
_cset(:puma_role)
|
16
|
+
_cset(:puma_role) { :app }
|
16
17
|
|
17
18
|
namespace :puma do
|
18
19
|
desc 'Start puma'
|
19
|
-
task :start, :roles => lambda {
|
20
|
-
run "cd #{current_path} && #{
|
20
|
+
task :start, :roles => lambda { puma_role }, :on_no_matching_servers => :continue do
|
21
|
+
run "cd #{current_path} && #{puma_cmd} #{start_options}", :pty => false
|
21
22
|
end
|
22
23
|
|
23
24
|
desc 'Stop puma'
|
24
|
-
task :stop, :roles => lambda {
|
25
|
-
run "cd #{current_path} && #{
|
25
|
+
task :stop, :roles => lambda { puma_role }, :on_no_matching_servers => :continue do
|
26
|
+
run "cd #{current_path} && #{pumactl_cmd} -S #{state_path} stop"
|
26
27
|
end
|
27
28
|
|
28
29
|
desc 'Restart puma'
|
29
|
-
task :restart, :roles => lambda {
|
30
|
-
run "cd #{current_path} && #{
|
30
|
+
task :restart, :roles => lambda { puma_role }, :on_no_matching_servers => :continue do
|
31
|
+
run "cd #{current_path} && #{pumactl_cmd} -S #{state_path} restart"
|
31
32
|
end
|
33
|
+
|
34
|
+
desc 'Restart puma (phased restart)'
|
35
|
+
task :phased_restart, :roles => lambda { puma_role }, :on_no_matching_servers => :continue do
|
36
|
+
run "cd #{current_path} && #{pumactl_cmd} -S #{state_path} phased-restart"
|
37
|
+
end
|
38
|
+
|
32
39
|
end
|
33
40
|
|
34
41
|
def start_options
|
35
42
|
if config_file
|
36
43
|
"-q -d -e #{puma_env} -C #{config_file}"
|
37
44
|
else
|
38
|
-
"-q -d -e #{puma_env} -b '#{
|
45
|
+
"-q -d -e #{puma_env} -b '#{puma_socket}' -S #{state_path} --control 'unix://#{shared_path}/sockets/pumactl.sock'"
|
39
46
|
end
|
40
47
|
end
|
41
48
|
|
@@ -52,7 +59,7 @@ Capistrano::Configuration.instance.load do
|
|
52
59
|
end
|
53
60
|
|
54
61
|
def state_path
|
55
|
-
(config_file ? configuration.options[:state] : nil) ||
|
62
|
+
(config_file ? configuration.options[:state] : nil) || puma_state
|
56
63
|
end
|
57
64
|
|
58
65
|
def configuration
|
data/lib/puma/cluster.rb
CHANGED
@@ -33,9 +33,10 @@ module Puma
|
|
33
33
|
@pid = pid
|
34
34
|
@phase = phase
|
35
35
|
@stage = :started
|
36
|
+
@signal = "TERM"
|
36
37
|
end
|
37
38
|
|
38
|
-
attr_reader :pid, :phase
|
39
|
+
attr_reader :pid, :phase, :signal
|
39
40
|
|
40
41
|
def booted?
|
41
42
|
@stage == :booted
|
@@ -47,7 +48,13 @@ module Puma
|
|
47
48
|
|
48
49
|
def term
|
49
50
|
begin
|
50
|
-
|
51
|
+
if @first_term_sent && (Time.new - @first_term_sent) > 30
|
52
|
+
@signal = "KILL"
|
53
|
+
else
|
54
|
+
@first_term_sent ||= Time.new
|
55
|
+
end
|
56
|
+
|
57
|
+
Process.kill @signal, @pid
|
51
58
|
rescue Errno::ESRCH
|
52
59
|
end
|
53
60
|
end
|
@@ -85,7 +92,7 @@ module Puma
|
|
85
92
|
|
86
93
|
spawn_workers
|
87
94
|
|
88
|
-
if
|
95
|
+
if all_workers_booted?
|
89
96
|
# If we're running at proper capacity, check to see if
|
90
97
|
# we need to phase any workers out (which will restart
|
91
98
|
# in the right phase).
|
@@ -93,9 +100,13 @@ module Puma
|
|
93
100
|
w = @workers.find { |x| x.phase != @phase }
|
94
101
|
|
95
102
|
if w
|
96
|
-
@phased_state
|
97
|
-
|
103
|
+
if @phased_state == :idle
|
104
|
+
@phased_state = :waiting
|
105
|
+
log "- Stopping #{w.pid} for phased upgrade..."
|
106
|
+
end
|
107
|
+
|
98
108
|
w.term
|
109
|
+
log "- #{w.signal} sent to #{w.pid}..."
|
99
110
|
end
|
100
111
|
end
|
101
112
|
end
|
data/lib/puma/const.rb
CHANGED
data/lib/puma/events.rb
CHANGED
@@ -23,10 +23,32 @@ module Puma
|
|
23
23
|
@debug = ENV.key? 'PUMA_DEBUG'
|
24
24
|
|
25
25
|
@on_booted = []
|
26
|
+
|
27
|
+
@hooks = Hash.new { |h,k| h[k] = [] }
|
26
28
|
end
|
27
29
|
|
28
30
|
attr_reader :stdout, :stderr
|
29
31
|
|
32
|
+
# Fire callbacks for the named hook
|
33
|
+
#
|
34
|
+
def fire(hook, *args)
|
35
|
+
@hooks[hook].each { |t| t.call(*args) }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Register a callbock for a given hook
|
39
|
+
#
|
40
|
+
def register(hook, obj=nil, &blk)
|
41
|
+
if obj and blk
|
42
|
+
raise "Specify either an object or a block, not both"
|
43
|
+
end
|
44
|
+
|
45
|
+
h = obj || blk
|
46
|
+
|
47
|
+
@hooks[hook] << h
|
48
|
+
|
49
|
+
h
|
50
|
+
end
|
51
|
+
|
30
52
|
# Write +str+ to +@stdout+
|
31
53
|
#
|
32
54
|
def log(str)
|
data/lib/puma/server.rb
CHANGED
@@ -156,6 +156,8 @@ module Puma
|
|
156
156
|
client.close unless env['detach']
|
157
157
|
end
|
158
158
|
|
159
|
+
@events.fire :state, :running
|
160
|
+
|
159
161
|
if background
|
160
162
|
@thread = Thread.new { handle_servers_lopez_mode }
|
161
163
|
return @thread
|
@@ -194,6 +196,8 @@ module Puma
|
|
194
196
|
end
|
195
197
|
end
|
196
198
|
|
199
|
+
@events.fire :state, @status
|
200
|
+
|
197
201
|
graceful_shutdown if @status == :stop || @status == :restart
|
198
202
|
|
199
203
|
rescue Exception => e
|
@@ -207,6 +211,8 @@ module Puma
|
|
207
211
|
@binder.close
|
208
212
|
end
|
209
213
|
end
|
214
|
+
|
215
|
+
@events.fire :state, :done
|
210
216
|
end
|
211
217
|
# Runs the server.
|
212
218
|
#
|
@@ -217,6 +223,8 @@ module Puma
|
|
217
223
|
def run(background=true)
|
218
224
|
BasicSocket.do_not_reverse_lookup = true
|
219
225
|
|
226
|
+
@events.fire :state, :booting
|
227
|
+
|
220
228
|
@status = :run
|
221
229
|
|
222
230
|
if @mode == :tcp
|
@@ -255,6 +263,8 @@ module Puma
|
|
255
263
|
@thread_pool.auto_trim!(@auto_trim_time)
|
256
264
|
end
|
257
265
|
|
266
|
+
@events.fire :state, :running
|
267
|
+
|
258
268
|
if background
|
259
269
|
@thread = Thread.new { handle_servers }
|
260
270
|
return @thread
|
@@ -293,6 +303,8 @@ module Puma
|
|
293
303
|
end
|
294
304
|
end
|
295
305
|
|
306
|
+
@events.fire :state, @status
|
307
|
+
|
296
308
|
graceful_shutdown if @status == :stop || @status == :restart
|
297
309
|
@reactor.clear! if @status == :restart
|
298
310
|
|
@@ -308,6 +320,8 @@ module Puma
|
|
308
320
|
@binder.close
|
309
321
|
end
|
310
322
|
end
|
323
|
+
|
324
|
+
@events.fire :state, :done
|
311
325
|
end
|
312
326
|
|
313
327
|
# :nodoc:
|
@@ -763,6 +777,8 @@ module Puma
|
|
763
777
|
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
|
764
778
|
IO.select(nil, [io], nil, 1)
|
765
779
|
retry
|
780
|
+
rescue Errno::EPIPE, SystemCallError, IOError
|
781
|
+
return false
|
766
782
|
end
|
767
783
|
|
768
784
|
return if n == str.bytesize
|
data/lib/puma/single.rb
CHANGED
data/test/test_puma_server.rb
CHANGED
@@ -266,4 +266,27 @@ class TestPumaServer < Test::Unit::TestCase
|
|
266
266
|
|
267
267
|
assert_equal "HTTP/1.0 200 OK\r\nContent-Type: application/pdf\r\nContent-Length: 4242\r\n\r\n", data
|
268
268
|
end
|
269
|
+
|
270
|
+
def test_status_hook_fires_when_server_changes_states
|
271
|
+
|
272
|
+
states = []
|
273
|
+
|
274
|
+
@events.register(:state) { |s| states << s }
|
275
|
+
|
276
|
+
@server.app = proc { |env| [200, {}, [""]] }
|
277
|
+
|
278
|
+
@server.add_tcp_listener @host, @port
|
279
|
+
@server.run
|
280
|
+
|
281
|
+
sock = TCPSocket.new @host, @port
|
282
|
+
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
283
|
+
|
284
|
+
sock.read
|
285
|
+
|
286
|
+
assert_equal [:booting, :running], states
|
287
|
+
|
288
|
+
@server.stop(true)
|
289
|
+
|
290
|
+
assert_equal [:booting, :running, :stop, :done], states
|
291
|
+
end
|
269
292
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|