puma 0.8.2-java → 0.9.0-java

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.

@@ -1,7 +1,16 @@
1
1
  require 'thread'
2
2
 
3
3
  module Puma
4
+ # A simple thread pool management object.
5
+ #
4
6
  class ThreadPool
7
+
8
+ # Maintain a minimum of +min+ and maximum of +max+ threads
9
+ # in the pool.
10
+ #
11
+ # The block passed is the work that will be performed in each
12
+ # thread.
13
+ #
5
14
  def initialize(min, max, &blk)
6
15
  @todo = Queue.new
7
16
  @mutex = Mutex.new
@@ -15,11 +24,15 @@ module Puma
15
24
 
16
25
  @workers = []
17
26
 
27
+ @auto_trim = nil
28
+
18
29
  min.times { spawn_thread }
19
30
  end
20
31
 
21
32
  attr_reader :spawned
22
33
 
34
+ # How many objects have yet to be processed by the pool?
35
+ #
23
36
  def backlog
24
37
  @todo.size
25
38
  end
@@ -27,6 +40,7 @@ module Puma
27
40
  Stop = Object.new
28
41
  Trim = Object.new
29
42
 
43
+ # :nodoc:
30
44
  def spawn_thread
31
45
  @mutex.synchronize do
32
46
  @spawned += 1
@@ -64,6 +78,7 @@ module Puma
64
78
  th
65
79
  end
66
80
 
81
+ # Add +work+ to the todo list for a Thread to pickup and process.
67
82
  def <<(work)
68
83
  if @todo.num_waiting == 0 and @spawned < @max
69
84
  spawn_thread
@@ -72,6 +87,9 @@ module Puma
72
87
  @todo << work
73
88
  end
74
89
 
90
+ # If too many threads are in the pool, tell one to finish go ahead
91
+ # and exit.
92
+ #
75
93
  def trim
76
94
  @mutex.synchronize do
77
95
  if @spawned - @trim_requested > @min
@@ -81,7 +99,40 @@ module Puma
81
99
  end
82
100
  end
83
101
 
102
+ class AutoTrim
103
+ def initialize(pool, timeout)
104
+ @pool = pool
105
+ @timeout = timeout
106
+ @running = false
107
+ end
108
+
109
+ def start!
110
+ @running = true
111
+
112
+ @thread = Thread.new do
113
+ while @running
114
+ @pool.trim
115
+ sleep @timeout
116
+ end
117
+ end
118
+ end
119
+
120
+ def stop
121
+ @running = false
122
+ @thread.wakeup
123
+ end
124
+ end
125
+
126
+ def auto_trim!(timeout=5)
127
+ @auto_trim = AutoTrim.new(self, timeout)
128
+ @auto_trim.start!
129
+ end
130
+
131
+ # Tell all threads in the pool to exit and wait for them to finish.
132
+ #
84
133
  def shutdown
134
+ @auto_trim.stop if @auto_trim
135
+
85
136
  @spawned.times do
86
137
  @todo << Stop
87
138
  end
Binary file
@@ -2,23 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "puma"
5
- s.version = "0.8.2"
5
+ s.version = "0.9.0"
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"]
9
- s.date = "2011-11-22"
9
+ s.date = "2011-12-06"
10
10
  s.description = "Puma is a small library that provides a very fast and concurrent HTTP 1.1 server for Ruby web applications. It is designed for running rack apps only.\n\nWhat makes Puma so fast is the careful use of an Ragel extension to provide fast, accurate HTTP 1.1 protocol parsing. This makes the server scream without too many portability issues."
11
11
  s.email = ["evan@phx.io"]
12
- s.executables = ["puma"]
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", "examples/builder.rb", "examples/camping/README", "examples/camping/blog.rb", "examples/camping/tepee.rb", "examples/httpd.conf", "examples/mime.yaml", "examples/mongrel.conf", "examples/monitrc", "examples/random_thrash.rb", "examples/simpletest.rb", "examples/webrick_compare.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/cli.rb", "lib/puma/const.rb", "lib/puma/events.rb", "lib/puma/gems.rb", "lib/puma/mime_types.yml", "lib/puma/rack_patch.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/puma/utils.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "tasks/gem.rake", "tasks/java.rake", "tasks/native.rake", "tasks/ragel.rake", "test/lobster.ru", "test/mime.yaml", "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", ".gemtest"]
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"]
16
16
  s.rdoc_options = ["--main", "README.md"]
17
17
  s.require_paths = ["lib"]
18
18
  s.rubyforge_project = "puma"
19
19
  s.rubygems_version = "1.8.10"
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
- s.test_files = ["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"]
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
 
23
23
  if s.respond_to? :specification_version then
24
24
  s.specification_version = 3
@@ -0,0 +1,22 @@
1
+ url = ARGV.shift
2
+ count = (ARGV.shift || 1000).to_i
3
+
4
+ STDOUT.sync = true
5
+
6
+ 1.upto(5) do |i|
7
+ print "#{i}: "
8
+ str = `ab -n #{count} -c #{i} #{url} 2>/dev/null`
9
+
10
+ rs = /Requests per second:\s+([\d.]+)\s/.match(str)
11
+ puts rs[1]
12
+ end
13
+
14
+ puts "Keep Alive:"
15
+
16
+ 1.upto(5) do |i|
17
+ print "#{i}: "
18
+ str = `ab -n #{count} -k -c #{i} #{url} 2>/dev/null`
19
+
20
+ rs = /Requests per second:\s+([\d.]+)\s/.match(str)
21
+ puts rs[1]
22
+ end
@@ -0,0 +1,69 @@
1
+ require 'test/unit'
2
+ require 'puma/app/status'
3
+
4
+ class TestAppStatus < Test::Unit::TestCase
5
+ class FakeServer
6
+ def initialize
7
+ @status = :running
8
+ @backlog = 0
9
+ @running = 0
10
+ end
11
+
12
+ attr_reader :status
13
+ attr_accessor :backlog, :running
14
+
15
+ def stop
16
+ @status = :stop
17
+ end
18
+
19
+ def halt
20
+ @status = :halt
21
+ end
22
+ end
23
+
24
+ def setup
25
+ @server = FakeServer.new
26
+ @app = Puma::App::Status.new(@server, @server)
27
+ end
28
+
29
+ def test_unsupported
30
+ env = { 'PATH_INFO' => "/not-real" }
31
+
32
+ status, header, body = @app.call env
33
+
34
+ assert_equal 404, status
35
+ end
36
+
37
+ def test_stop
38
+ env = { 'PATH_INFO' => "/stop" }
39
+
40
+ status, header, body = @app.call env
41
+
42
+ assert_equal :stop, @server.status
43
+ assert_equal 200, status
44
+ assert_equal ['{ "status": "ok" }'], body
45
+ end
46
+
47
+ def test_halt
48
+ env = { 'PATH_INFO' => "/halt" }
49
+
50
+ status, header, body = @app.call env
51
+
52
+ assert_equal :halt, @server.status
53
+ assert_equal 200, status
54
+ assert_equal ['{ "status": "ok" }'], body
55
+ end
56
+
57
+ def test_stats
58
+ env = { 'PATH_INFO' => "/stats" }
59
+
60
+ @server.backlog = 1
61
+ @server.running = 9
62
+
63
+ status, header, body = @app.call env
64
+
65
+ assert_equal 200, status
66
+ assert_equal ['{ "backlog": 1, "running": 9 }'], body
67
+ end
68
+
69
+ end
@@ -4,16 +4,102 @@ require 'tempfile'
4
4
 
5
5
  class TestCLI < Test::Unit::TestCase
6
6
  def setup
7
- @pid_file = Tempfile.new("puma-test")
8
- @pid_path = @pid_file.path
9
- @pid_file.close!
7
+ @tmp_file = Tempfile.new("puma-test")
8
+ @tmp_path = @tmp_file.path
9
+ @tmp_file.close!
10
+
11
+ @tmp_path2 = "#{@tmp_path}2"
12
+
13
+ File.unlink @tmp_path if File.exist? @tmp_path
14
+ File.unlink @tmp_path2 if File.exist? @tmp_path2
15
+ end
16
+
17
+ def teardown
18
+ File.unlink @tmp_path if File.exist? @tmp_path
19
+ File.unlink @tmp_path2 if File.exist? @tmp_path2
10
20
  end
11
21
 
12
22
  def test_pid_file
13
- cli = Puma::CLI.new ["--pidfile", @pid_path]
23
+ cli = Puma::CLI.new ["--pidfile", @tmp_path]
14
24
  cli.parse_options
15
25
  cli.write_pid
16
26
 
17
- assert_equal File.read(@pid_path).strip.to_i, Process.pid
27
+ assert_equal File.read(@tmp_path).strip.to_i, Process.pid
28
+ end
29
+
30
+ unless defined? JRUBY_VERSION
31
+ def test_status
32
+ url = "unix://#{@tmp_path}"
33
+
34
+ sin = StringIO.new
35
+ sout = StringIO.new
36
+
37
+ cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--status", url, "test/lobster.ru"], sin, sout
38
+ cli.parse_options
39
+
40
+ t = Thread.new { cli.run }
41
+
42
+ sleep 1
43
+
44
+ s = UNIXSocket.new @tmp_path
45
+ s << "GET /stats HTTP/1.0\r\n\r\n"
46
+ body = s.read
47
+
48
+ assert_equal '{ "backlog": 0, "running": 0 }', body.split("\r\n").last
49
+
50
+ cli.stop
51
+ t.join
52
+ end
53
+
54
+ def test_status_stop
55
+ url = "unix://#{@tmp_path}"
56
+
57
+ sin = StringIO.new
58
+ sout = StringIO.new
59
+
60
+ cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--status", url, "test/lobster.ru"], sin, sout
61
+ cli.parse_options
62
+
63
+ t = Thread.new { cli.run }
64
+
65
+ sleep 1
66
+
67
+ s = UNIXSocket.new @tmp_path
68
+ s << "GET /stop HTTP/1.0\r\n\r\n"
69
+ body = s.read
70
+
71
+ assert_equal '{ "status": "ok" }', body.split("\r\n").last
72
+
73
+ t.join
74
+ end
75
+
76
+ def test_tmp_status
77
+ url = "tcp://127.0.0.1:8232"
78
+ cli = Puma::CLI.new ["--state", @tmp_path, "--status"]
79
+ cli.parse_options
80
+ cli.write_state
81
+
82
+ data = YAML.load_file(@tmp_path)
83
+
84
+ assert_equal Process.pid, data["pid"]
85
+
86
+ url = data["status_address"]
87
+
88
+ m = %r!unix://(.*)!.match(url)
89
+
90
+ assert m, "'#{url}' is not a URL"
91
+ end
92
+ end
93
+
94
+ def test_state
95
+ url = "tcp://127.0.0.1:8232"
96
+ cli = Puma::CLI.new ["--state", @tmp_path, "--status", url]
97
+ cli.parse_options
98
+ cli.write_state
99
+
100
+ data = YAML.load_file(@tmp_path)
101
+
102
+ assert_equal Process.pid, data["pid"]
103
+ assert_equal url, data["status_address"]
18
104
  end
19
105
  end
@@ -6,7 +6,7 @@ require 'test/testhelp'
6
6
  include Puma
7
7
 
8
8
  class Http11ParserTest < Test::Unit::TestCase
9
-
9
+
10
10
  def test_parse_simple
11
11
  parser = HttpParser.new
12
12
  req = {}
@@ -130,22 +130,5 @@ class Http11ParserTest < Test::Unit::TestCase
130
130
  end
131
131
 
132
132
  end
133
-
134
-
135
-
136
- def test_query_parse
137
- res = Utils.query_parse("zed=1&frank=#{Utils.escape('&&& ')}")
138
- assert res["zed"], "didn't get the request right"
139
- assert res["frank"], "no frank"
140
- assert_equal "1", res["zed"], "wrong result"
141
- assert_equal "&&& ", Utils.unescape(res["frank"]), "wrong result"
142
-
143
- res = Utils.query_parse("zed=1&zed=2&zed=3&frank=11;zed=45")
144
- assert res["zed"], "didn't get the request right"
145
- assert res["frank"], "no frank"
146
- assert_equal 4,res["zed"].length, "wrong number for zed"
147
- assert_equal "11",res["frank"], "wrong number for frank"
148
- end
149
-
150
133
  end
151
134
 
@@ -123,7 +123,7 @@ class TestPersistent < Test::Unit::TestCase
123
123
  @client << @keep_request
124
124
  sz = @body[0].size.to_s
125
125
 
126
- assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
126
+ assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: Keep-Alive\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
127
127
  assert_equal "Hello", @client.read(5)
128
128
  end
129
129
 
@@ -197,8 +197,8 @@ class TestPersistent < Test::Unit::TestCase
197
197
  assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
198
198
  assert_equal "Hello", @client.read(5)
199
199
 
200
- assert_equal "", @inputs[0].string
201
- assert_equal "", @inputs[1].string
200
+ assert_kind_of Puma::NullIO, @inputs[0]
201
+ assert_kind_of Puma::NullIO, @inputs[1]
202
202
 
203
203
  end
204
204
 
@@ -99,4 +99,28 @@ class TestThreadPool < Test::Unit::TestCase
99
99
 
100
100
  assert_equal 1, pool.spawned
101
101
  end
102
+
103
+ def test_autotrim
104
+ finish = false
105
+ pool = new_pool(1, 2) { Thread.pass until finish }
106
+
107
+ pool << 1
108
+ pool << 2
109
+
110
+ assert_equal 2, pool.spawned
111
+
112
+ finish = true
113
+
114
+ pause
115
+
116
+ assert_equal 2, pool.spawned
117
+
118
+ pool.auto_trim! 1
119
+
120
+ sleep 1
121
+
122
+ pause
123
+
124
+ assert_equal 1, pool.spawned
125
+ end
102
126
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.8.2
5
+ version: 0.9.0
6
6
  platform: java
7
7
  authors:
8
8
  - Evan Phoenix
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-11-28 00:00:00 -08:00
13
+ date: 2011-12-05 00:00:00 -08:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -54,6 +54,7 @@ email:
54
54
  - evan@phx.io
55
55
  executables:
56
56
  - puma
57
+ - pumactl
57
58
  extensions: []
58
59
 
59
60
  extra_rdoc_files:
@@ -69,17 +70,7 @@ files:
69
70
  - Rakefile
70
71
  - TODO
71
72
  - bin/puma
72
- - examples/builder.rb
73
- - examples/camping/README
74
- - examples/camping/blog.rb
75
- - examples/camping/tepee.rb
76
- - examples/httpd.conf
77
- - examples/mime.yaml
78
- - examples/mongrel.conf
79
- - examples/monitrc
80
- - examples/random_thrash.rb
81
- - examples/simpletest.rb
82
- - examples/webrick_compare.rb
73
+ - bin/pumactl
83
74
  - ext/puma_http11/PumaHttp11Service.java
84
75
  - ext/puma_http11/ext_help.h
85
76
  - ext/puma_http11/extconf.rb
@@ -92,23 +83,21 @@ files:
92
83
  - ext/puma_http11/org/jruby/puma/Http11Parser.java
93
84
  - ext/puma_http11/puma_http11.c
94
85
  - lib/puma.rb
86
+ - lib/puma/app/status.rb
95
87
  - lib/puma/cli.rb
96
88
  - lib/puma/const.rb
89
+ - lib/puma/control_cli.rb
97
90
  - lib/puma/events.rb
98
- - lib/puma/gems.rb
99
- - lib/puma/mime_types.yml
91
+ - lib/puma/null_io.rb
100
92
  - lib/puma/rack_patch.rb
101
93
  - lib/puma/server.rb
102
94
  - lib/puma/thread_pool.rb
103
- - lib/puma/utils.rb
104
95
  - lib/rack/handler/puma.rb
105
96
  - puma.gemspec
106
- - tasks/gem.rake
107
- - tasks/java.rake
108
- - tasks/native.rake
109
- - tasks/ragel.rake
97
+ - test/ab_rs.rb
110
98
  - test/lobster.ru
111
99
  - test/mime.yaml
100
+ - test/test_app_status.rb
112
101
  - test/test_cli.rb
113
102
  - test/test_http10.rb
114
103
  - test/test_http11.rb
@@ -120,7 +109,6 @@ files:
120
109
  - test/test_ws.rb
121
110
  - test/testhelp.rb
122
111
  - tools/trickletest.rb
123
- - .gemtest
124
112
  - lib/puma_http11.jar
125
113
  has_rdoc: true
126
114
  homepage:
@@ -152,6 +140,7 @@ signing_key:
152
140
  specification_version: 3
153
141
  summary: Puma is a small library that provides a very fast and concurrent HTTP 1.1 server for Ruby web applications
154
142
  test_files:
143
+ - test/test_app_status.rb
155
144
  - test/test_cli.rb
156
145
  - test/test_http10.rb
157
146
  - test/test_http11.rb