puma 0.9.0 → 0.9.1

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.

@@ -8,6 +8,7 @@ Rakefile
8
8
  TODO
9
9
  bin/puma
10
10
  bin/pumactl
11
+ examples/config.rb
11
12
  ext/puma_http11/PumaHttp11Service.java
12
13
  ext/puma_http11/ext_help.h
13
14
  ext/puma_http11/extconf.rb
@@ -22,9 +23,11 @@ ext/puma_http11/puma_http11.c
22
23
  lib/puma.rb
23
24
  lib/puma/app/status.rb
24
25
  lib/puma/cli.rb
26
+ lib/puma/config.rb
25
27
  lib/puma/const.rb
26
28
  lib/puma/control_cli.rb
27
29
  lib/puma/events.rb
30
+ lib/puma/jruby_restart.rb
28
31
  lib/puma/null_io.rb
29
32
  lib/puma/rack_patch.rb
30
33
  lib/puma/server.rb
@@ -0,0 +1,5 @@
1
+ state_path "puma.state"
2
+ activate_control_app
3
+
4
+ rackup "test/lobster.ru"
5
+ threads 3, 10
@@ -3,6 +3,7 @@ require 'uri'
3
3
 
4
4
  require 'puma/server'
5
5
  require 'puma/const'
6
+ require 'puma/config'
6
7
 
7
8
  require 'rack/commonlogger'
8
9
 
@@ -10,9 +11,7 @@ module Puma
10
11
  # Handles invoke a Puma::Server in a command line style.
11
12
  #
12
13
  class CLI
13
- DefaultTCPHost = "0.0.0.0"
14
- DefaultTCPPort = 9292
15
-
14
+ DefaultRackup = "config.ru"
16
15
  IS_JRUBY = defined?(JRUBY_VERSION)
17
16
 
18
17
  # Create a new CLI object using +argv+ as the command line
@@ -81,8 +80,13 @@ module Puma
81
80
  end
82
81
 
83
82
  def restart!
84
- Dir.chdir @restart_dir
85
- Kernel.exec(*@restart_argv)
83
+ if IS_JRUBY
84
+ require 'puma/jruby_restart'
85
+ JRubyRestart.chdir_exec(@restart_dir, Gem.ruby, *@restart_argv)
86
+ else
87
+ Dir.chdir @restart_dir
88
+ Kernel.exec(*@restart_argv)
89
+ end
86
90
  end
87
91
 
88
92
  # Write +str+ to +@stdout+
@@ -104,14 +108,17 @@ module Puma
104
108
  @options = {
105
109
  :min_threads => 0,
106
110
  :max_threads => 16,
107
- :quiet => false
111
+ :quiet => false,
112
+ :binds => []
108
113
  }
109
114
 
110
- @binds = []
111
-
112
115
  @parser = OptionParser.new do |o|
113
116
  o.on "-b", "--bind URI", "URI to bind to (tcp:// and unix:// only)" do |arg|
114
- @binds << arg
117
+ @options[:binds] << arg
118
+ end
119
+
120
+ o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
121
+ @options[:config_file] = arg
115
122
  end
116
123
 
117
124
  o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
@@ -122,6 +129,19 @@ module Puma
122
129
  @options[:quiet] = true
123
130
  end
124
131
 
132
+ o.on "-S", "--state PATH", "Where to store the state details" do |arg|
133
+ @options[:state] = arg
134
+ end
135
+
136
+ o.on "--control URL", "The bind url to use for the control server",
137
+ "Use 'auto' to use temp unix server" do |arg|
138
+ if arg
139
+ @options[:control_url] = arg
140
+ elsif IS_JRUBY
141
+ raise NotImplementedError, "No default url available on JRuby"
142
+ end
143
+ end
144
+
125
145
  o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
126
146
  min, max = arg.split(":")
127
147
  if max
@@ -133,27 +153,6 @@ module Puma
133
153
  end
134
154
  end
135
155
 
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
-
157
156
  end
158
157
 
159
158
  @parser.banner = "puma <options> <rackup file>"
@@ -168,7 +167,7 @@ module Puma
168
167
  # the rackup file, and set @app.
169
168
  #
170
169
  def load_rackup
171
- @app, options = Rack::Builder.parse_file @rackup
170
+ @app, options = Rack::Builder.parse_file @options[:rackup]
172
171
  @options.merge! options
173
172
 
174
173
  options.each do |key,val|
@@ -195,9 +194,7 @@ module Puma
195
194
  if path = @options[:state]
196
195
  state = { "pid" => Process.pid }
197
196
 
198
- if url = @options[:status_address]
199
- state["status_address"] = url
200
- end
197
+ state["config"] = @config
201
198
 
202
199
  File.open(path, "w") do |f|
203
200
  f.write state.to_yaml
@@ -208,6 +205,18 @@ module Puma
208
205
  # :nodoc:
209
206
  def parse_options
210
207
  @parser.parse! @argv
208
+
209
+ @config = Puma::Configuration.new @options
210
+ @config.load
211
+
212
+ unless @options[:rackup]
213
+ @options[:rackup] = @argv.shift || DefaultRackup
214
+ end
215
+
216
+ if @options[:control_url] == "auto"
217
+ path = @temp_status_path = Configuration.temp_path
218
+ @options[:control_url] = "unix://#{path}"
219
+ end
211
220
  end
212
221
 
213
222
  # Parse the options, load the rackup, start the server and wait
@@ -216,10 +225,10 @@ module Puma
216
225
  def run
217
226
  parse_options
218
227
 
219
- @rackup = @argv.shift || "config.ru"
228
+ rackup = @options[:rackup]
220
229
 
221
- unless File.exists?(@rackup)
222
- raise "Missing rackup file '#{@rackup}'"
230
+ unless File.exists?(rackup)
231
+ raise "Missing rackup file '#{rackup}'"
223
232
  end
224
233
 
225
234
  load_rackup
@@ -230,11 +239,6 @@ module Puma
230
239
  @app = Rack::CommonLogger.new(@app, STDOUT)
231
240
  end
232
241
 
233
- if @binds.empty?
234
- @options[:Host] ||= DefaultTCPHost
235
- @options[:Port] ||= DefaultTCPPort
236
- end
237
-
238
242
  min_t = @options[:min_threads]
239
243
  max_t = @options[:max_threads]
240
244
 
@@ -245,12 +249,7 @@ module Puma
245
249
  log "Puma #{Puma::Const::PUMA_VERSION} starting..."
246
250
  log "* Min threads: #{min_t}, max threads: #{max_t}"
247
251
 
248
- if @options[:Host]
249
- log "* Listening on tcp://#{@options[:Host]}:#{@options[:Port]}"
250
- server.add_tcp_listener @options[:Host], @options[:Port]
251
- end
252
-
253
- @binds.each do |str|
252
+ @options[:binds].each do |str|
254
253
  uri = URI.parse str
255
254
  case uri.scheme
256
255
  when "tcp"
@@ -268,7 +267,7 @@ module Puma
268
267
 
269
268
  @server = server
270
269
 
271
- if str = @options[:status_address]
270
+ if str = @options[:control_url]
272
271
  require 'puma/app/status'
273
272
 
274
273
  uri = URI.parse str
@@ -0,0 +1,98 @@
1
+ module Puma
2
+ class Configuration
3
+ DefaultTCPHost = "0.0.0.0"
4
+ DefaultTCPPort = 9292
5
+
6
+ def initialize(options)
7
+ @options = options
8
+ @options[:binds] ||= []
9
+ end
10
+
11
+ attr_reader :options
12
+
13
+ def load
14
+ if path = @options[:config_file]
15
+ instance_eval File.read(path), path, 1
16
+ end
17
+
18
+ # Rakeup default option support
19
+ if host = @options[:Host]
20
+ port = @options[:Port] || DefaultTCPPort
21
+
22
+ @options[:binds] << "tcp://#{host}:#{port}"
23
+ end
24
+
25
+ if @options[:binds].empty?
26
+ @options[:binds] << "tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"
27
+ end
28
+ end
29
+
30
+ def self.temp_path
31
+ require 'tmpdir'
32
+
33
+ t = (Time.now.to_f * 1000).to_i
34
+ "#{Dir.tmpdir}/puma-status-#{t}-#{$$}"
35
+ end
36
+
37
+ # Use +obj+ or +block+ as the Rack app. This allows a config file to
38
+ # be the app itself.
39
+ #
40
+ def app(obj=nil, &block)
41
+ obj ||= block
42
+
43
+ raise "Provide either a #call'able or a block" unless obj
44
+
45
+ @options[:app] = obj
46
+ end
47
+
48
+ # Start the Puma control rack app on +url+. This app can be communicated
49
+ # with to control the main server.
50
+ #
51
+ def activate_control_app(url="auto")
52
+ @options[:control_url] = url
53
+ end
54
+
55
+ # Bind the server to +url+. tcp:// and unix:// are the only accepted
56
+ # protocols.
57
+ #
58
+ def bind(url)
59
+ @options[:binds] << url
60
+ end
61
+
62
+ # Store the pid of the server in the file at +path+.
63
+ def pidfile(path)
64
+ @options[:pidfile] = path
65
+ end
66
+
67
+ # Disable request logging.
68
+ #
69
+ def quiet
70
+ @options[:quiet] = true
71
+ end
72
+
73
+ # Load +path+ as a rackup file.
74
+ #
75
+ def rackup(path)
76
+ @options[:rackup] = path.to_s
77
+ end
78
+
79
+ # Configure +min+ to be the minimum number of threads to use to answer
80
+ # requests and +max+ the maximum.
81
+ #
82
+ def threads(min, max)
83
+ if min > max
84
+ raise "The minimum number of threads must be less than the max"
85
+ end
86
+
87
+ @options[:min_threads] = min
88
+ @options[:max_threads] = max
89
+ end
90
+
91
+ # Use +path+ as the file to store the server info state. This is
92
+ # used by pumactl to query and control the server.
93
+ #
94
+ def state_path(path)
95
+ @options[:state] = path.to_s
96
+ end
97
+ end
98
+ end
@@ -71,7 +71,7 @@ module Puma
71
71
 
72
72
  PATH_INFO = 'PATH_INFO'.freeze
73
73
 
74
- PUMA_VERSION = VERSION = "0.9.0".freeze
74
+ PUMA_VERSION = VERSION = "0.9.1".freeze
75
75
 
76
76
  PUMA_TMP_BASE = "puma".freeze
77
77
 
@@ -1,6 +1,8 @@
1
1
  require 'optparse'
2
2
 
3
3
  require 'puma/const'
4
+ require 'puma/config'
5
+
4
6
  require 'yaml'
5
7
  require 'uri'
6
8
 
@@ -22,7 +24,7 @@ module Puma
22
24
  end
23
25
 
24
26
  def connect
25
- if str = @state['status_address']
27
+ if str = @config.options[:control_url]
26
28
  uri = URI.parse str
27
29
  case uri.scheme
28
30
  when "tcp"
@@ -44,6 +46,7 @@ module Puma
44
46
  @parser.parse! @argv
45
47
 
46
48
  @state = YAML.load_file(@path)
49
+ @config = @state['config']
47
50
 
48
51
  cmd = @argv.shift
49
52
 
@@ -101,8 +104,8 @@ module Puma
101
104
 
102
105
  def command_stats
103
106
  sock = connect
104
- s << "GET /stats HTTP/1.0\r\n\r\n"
105
- rep = s.read
107
+ sock << "GET /stats HTTP/1.0\r\n\r\n"
108
+ rep = sock.read
106
109
 
107
110
  body = rep.split("\r\n").last
108
111
 
@@ -0,0 +1,22 @@
1
+ require 'ffi'
2
+
3
+ module Puma
4
+ module JRubyRestart
5
+ extend FFI::Library
6
+ ffi_lib 'c'
7
+
8
+ attach_function :execlp, [:string, :varargs], :int
9
+ attach_function :chdir, [:string], :int
10
+
11
+ def self.chdir_exec(dir, cmd, *argv)
12
+ chdir(dir)
13
+ argv.unshift(cmd)
14
+ argv = ([:string] * argv.size).zip(argv).flatten
15
+ argv <<:int
16
+ argv << 0
17
+ execlp(cmd, *argv)
18
+ raise SystemCallError.new(FFI.errno)
19
+ end
20
+ end
21
+ end
22
+
@@ -137,7 +137,9 @@ module Puma
137
137
  @todo << Stop
138
138
  end
139
139
 
140
- @workers.each { |w| w.join }
140
+ # Use this instead of #each so that we don't stop in the middle
141
+ # of each and see a mutated object mid #each
142
+ @workers.first.join until @workers.empty?
141
143
 
142
144
  @spawned = 0
143
145
  @workers = []
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "puma"
5
- s.version = "0.9.0"
5
+ s.version = "0.9.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Evan Phoenix"]
@@ -12,11 +12,11 @@ Gem::Specification.new do |s|
12
12
  s.executables = ["puma", "pumactl"]
13
13
  s.extensions = ["ext/puma_http11/extconf.rb"]
14
14
  s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
15
- s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/app/status.rb", "lib/puma/cli.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/events.rb", "lib/puma/null_io.rb", "lib/puma/rack_patch.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "test/ab_rs.rb", "test/lobster.ru", "test/mime.yaml", "test/test_app_status.rb", "test/test_cli.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_persistent.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb", "test/testhelp.rb", "tools/trickletest.rb"]
15
+ s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "examples/config.rb", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/app/status.rb", "lib/puma/cli.rb", "lib/puma/config.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/events.rb", "lib/puma/jruby_restart.rb", "lib/puma/null_io.rb", "lib/puma/rack_patch.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "test/ab_rs.rb", "test/lobster.ru", "test/mime.yaml", "test/test_app_status.rb", "test/test_cli.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_persistent.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb", "test/testhelp.rb", "tools/trickletest.rb"]
16
16
  s.rdoc_options = ["--main", "README.md"]
17
17
  s.require_paths = ["lib"]
18
18
  s.rubyforge_project = "puma"
19
- s.rubygems_version = "1.8.10"
19
+ s.rubygems_version = "1.8.12"
20
20
  s.summary = "Puma is a small library that provides a very fast and concurrent HTTP 1.1 server for Ruby web applications"
21
21
  s.test_files = ["test/test_app_status.rb", "test/test_cli.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_persistent.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
22
22
 
@@ -28,13 +28,13 @@ class TestCLI < Test::Unit::TestCase
28
28
  end
29
29
 
30
30
  unless defined? JRUBY_VERSION
31
- def test_status
31
+ def test_control
32
32
  url = "unix://#{@tmp_path}"
33
33
 
34
34
  sin = StringIO.new
35
35
  sout = StringIO.new
36
36
 
37
- cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--status", url, "test/lobster.ru"], sin, sout
37
+ cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--control", url, "test/lobster.ru"], sin, sout
38
38
  cli.parse_options
39
39
 
40
40
  t = Thread.new { cli.run }
@@ -51,13 +51,13 @@ class TestCLI < Test::Unit::TestCase
51
51
  t.join
52
52
  end
53
53
 
54
- def test_status_stop
54
+ def test_control_stop
55
55
  url = "unix://#{@tmp_path}"
56
56
 
57
57
  sin = StringIO.new
58
58
  sout = StringIO.new
59
59
 
60
- cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--status", url, "test/lobster.ru"], sin, sout
60
+ cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--control", url, "test/lobster.ru"], sin, sout
61
61
  cli.parse_options
62
62
 
63
63
  t = Thread.new { cli.run }
@@ -73,9 +73,9 @@ class TestCLI < Test::Unit::TestCase
73
73
  t.join
74
74
  end
75
75
 
76
- def test_tmp_status
76
+ def test_tmp_control
77
77
  url = "tcp://127.0.0.1:8232"
78
- cli = Puma::CLI.new ["--state", @tmp_path, "--status"]
78
+ cli = Puma::CLI.new ["--state", @tmp_path, "--control", "auto"]
79
79
  cli.parse_options
80
80
  cli.write_state
81
81
 
@@ -83,7 +83,7 @@ class TestCLI < Test::Unit::TestCase
83
83
 
84
84
  assert_equal Process.pid, data["pid"]
85
85
 
86
- url = data["status_address"]
86
+ url = data["config"].options[:control_url]
87
87
 
88
88
  m = %r!unix://(.*)!.match(url)
89
89
 
@@ -93,13 +93,13 @@ class TestCLI < Test::Unit::TestCase
93
93
 
94
94
  def test_state
95
95
  url = "tcp://127.0.0.1:8232"
96
- cli = Puma::CLI.new ["--state", @tmp_path, "--status", url]
96
+ cli = Puma::CLI.new ["--state", @tmp_path, "--control", url]
97
97
  cli.parse_options
98
98
  cli.write_state
99
99
 
100
100
  data = YAML.load_file(@tmp_path)
101
101
 
102
102
  assert_equal Process.pid, data["pid"]
103
- assert_equal url, data["status_address"]
103
+ assert_equal url, data["config"].options[:control_url]
104
104
  end
105
105
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 57
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 0
10
- version: 0.9.0
9
+ - 1
10
+ version: 0.9.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Evan Phoenix
@@ -103,6 +103,7 @@ files:
103
103
  - TODO
104
104
  - bin/puma
105
105
  - bin/pumactl
106
+ - examples/config.rb
106
107
  - ext/puma_http11/PumaHttp11Service.java
107
108
  - ext/puma_http11/ext_help.h
108
109
  - ext/puma_http11/extconf.rb
@@ -117,9 +118,11 @@ files:
117
118
  - lib/puma.rb
118
119
  - lib/puma/app/status.rb
119
120
  - lib/puma/cli.rb
121
+ - lib/puma/config.rb
120
122
  - lib/puma/const.rb
121
123
  - lib/puma/control_cli.rb
122
124
  - lib/puma/events.rb
125
+ - lib/puma/jruby_restart.rb
123
126
  - lib/puma/null_io.rb
124
127
  - lib/puma/rack_patch.rb
125
128
  - lib/puma/server.rb