rainbows 0.94.0 → 0.95.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. data/.document +1 -0
  2. data/.manifest +18 -0
  3. data/ChangeLog +394 -226
  4. data/GIT-VERSION-FILE +1 -1
  5. data/GIT-VERSION-GEN +1 -1
  6. data/GNUmakefile +6 -4
  7. data/NEWS +18 -0
  8. data/README +13 -5
  9. data/Static_Files +71 -0
  10. data/TODO +12 -0
  11. data/Test_Suite +1 -1
  12. data/bin/rainbows +1 -4
  13. data/lib/rainbows/actor_spawn.rb +1 -1
  14. data/lib/rainbows/app_pool.rb +1 -1
  15. data/lib/rainbows/base.rb +79 -89
  16. data/lib/rainbows/byte_slice.rb +17 -0
  17. data/lib/rainbows/configurator.rb +46 -0
  18. data/lib/rainbows/const.rb +2 -2
  19. data/lib/rainbows/dev_fd_response.rb +52 -44
  20. data/lib/rainbows/error.rb +1 -0
  21. data/lib/rainbows/ev_core.rb +3 -2
  22. data/lib/rainbows/event_machine.rb +26 -24
  23. data/lib/rainbows/fiber/base.rb +30 -40
  24. data/lib/rainbows/fiber/body.rb +34 -0
  25. data/lib/rainbows/fiber/io.rb +28 -8
  26. data/lib/rainbows/fiber/queue.rb +1 -0
  27. data/lib/rainbows/fiber/rev.rb +4 -2
  28. data/lib/rainbows/fiber.rb +1 -0
  29. data/lib/rainbows/fiber_pool.rb +2 -2
  30. data/lib/rainbows/fiber_spawn.rb +2 -2
  31. data/lib/rainbows/http_response.rb +20 -31
  32. data/lib/rainbows/http_server.rb +3 -4
  33. data/lib/rainbows/max_body.rb +1 -0
  34. data/lib/rainbows/never_block/event_machine.rb +2 -0
  35. data/lib/rainbows/never_block.rb +5 -4
  36. data/lib/rainbows/queue_pool.rb +1 -0
  37. data/lib/rainbows/response/body.rb +119 -0
  38. data/lib/rainbows/response.rb +43 -0
  39. data/lib/rainbows/rev/client.rb +79 -9
  40. data/lib/rainbows/rev/core.rb +4 -0
  41. data/lib/rainbows/rev/deferred_response.rb +1 -44
  42. data/lib/rainbows/rev/heartbeat.rb +1 -0
  43. data/lib/rainbows/rev/master.rb +1 -0
  44. data/lib/rainbows/rev/sendfile.rb +26 -0
  45. data/lib/rainbows/rev/thread.rb +2 -1
  46. data/lib/rainbows/rev.rb +2 -0
  47. data/lib/rainbows/rev_fiber_spawn.rb +3 -1
  48. data/lib/rainbows/rev_thread_pool.rb +7 -5
  49. data/lib/rainbows/rev_thread_spawn.rb +2 -2
  50. data/lib/rainbows/revactor.rb +146 -146
  51. data/lib/rainbows/sendfile.rb +10 -21
  52. data/lib/rainbows/server_token.rb +39 -0
  53. data/lib/rainbows/stream_file.rb +14 -0
  54. data/lib/rainbows/tee_input.rb +1 -0
  55. data/lib/rainbows/thread_pool.rb +12 -7
  56. data/lib/rainbows/thread_spawn.rb +2 -3
  57. data/lib/rainbows/writer_thread_pool.rb +13 -7
  58. data/lib/rainbows/writer_thread_spawn.rb +12 -9
  59. data/lib/rainbows.rb +16 -45
  60. data/rainbows.gemspec +8 -8
  61. data/t/.gitignore +1 -1
  62. data/t/GNUmakefile +26 -16
  63. data/t/README +1 -1
  64. data/t/async-response-no-autochunk.ru +0 -1
  65. data/t/async-response.ru +0 -1
  66. data/t/cramp/rainsocket.ru +26 -0
  67. data/t/fork-sleep.ru +0 -1
  68. data/t/my-tap-lib.sh +3 -2
  69. data/t/simple-http_ActorSpawn.ru +9 -0
  70. data/t/t0009-broken-app.sh +1 -1
  71. data/t/t0009.ru +0 -1
  72. data/t/t0011-close-on-exec-set.sh +1 -1
  73. data/t/t0015-working_directory.sh +56 -0
  74. data/t/t0016-onenine-encoding-is-tricky.sh +28 -0
  75. data/t/t0016.rb +15 -0
  76. data/t/t0020-large-sendfile-response.sh +141 -0
  77. data/t/t0300-async_sinatra.sh +0 -6
  78. data/t/t0501-cramp-rainsocket.sh +38 -0
  79. data/t/t9001-sendfile-to-path.sh +5 -4
  80. data/t/t9002-server-token.sh +37 -0
  81. data/t/t9002.ru +4 -0
  82. data/t/test-lib.sh +1 -1
  83. data/t/test_isolate.rb +14 -11
  84. metadata +87 -18
@@ -48,8 +48,9 @@ module Rainbows
48
48
 
49
49
  include Base
50
50
 
51
- class Client < EM::Connection
51
+ class Client < EM::Connection # :nodoc: all
52
52
  include Rainbows::EvCore
53
+ include Rainbows::Response
53
54
  G = Rainbows::G
54
55
 
55
56
  def initialize(io)
@@ -70,7 +71,7 @@ module Rainbows
70
71
  begin
71
72
  @env[RACK_INPUT] = @input
72
73
  @env[REMOTE_ADDR] = @remote_addr
73
- @env[ASYNC_CALLBACK] = method(:response_write)
74
+ @env[ASYNC_CALLBACK] = method(:em_write_response)
74
75
 
75
76
  # we're not sure if anybody uses this, but Thin sets it, too
76
77
  @env[ASYNC_CLOSE] = EM::DefaultDeferrable.new
@@ -80,11 +81,11 @@ module Rainbows
80
81
  # too tricky to support pipelining with :async since the
81
82
  # second (pipelined) request could be a stuck behind a
82
83
  # long-running async response
83
- (response.nil? || -1 == response.first) and return @state = :close
84
+ (response.nil? || -1 == response[0]) and return @state = :close
84
85
 
85
86
  alive = @hp.keepalive? && G.alive
86
87
  out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers?
87
- response_write(response, out, alive)
88
+ em_write_response(response, out, alive)
88
89
 
89
90
  if alive
90
91
  @env.clear
@@ -98,32 +99,29 @@ module Rainbows
98
99
  end while true
99
100
  end
100
101
 
101
- def response_write(response, out = [ CONN_CLOSE ], alive = false)
102
- @body = body = response.last
102
+ def em_write_response(response, out = [ CONN_CLOSE ], alive = false)
103
+ @body = body = response[2]
103
104
  if body.respond_to?(:errback) && body.respond_to?(:callback)
104
105
  body.callback { quit }
105
106
  body.errback { quit }
106
- HttpResponse.write(self, response, out)
107
+ write_header(self, response, out)
108
+ write_body_each(self, body)
107
109
  return
108
110
  elsif ! body.respond_to?(:to_path)
109
- HttpResponse.write(self, response, out)
111
+ write_response(self, response, out)
110
112
  quit unless alive
111
113
  return
112
114
  end
113
115
 
114
116
  headers = Rack::Utils::HeaderHash.new(response[1])
115
- path = body.to_path
116
- io = body.to_io if body.respond_to?(:to_io)
117
- io ||= IO.new($1.to_i) if path =~ %r{\A/dev/fd/(\d+)\z}
118
- io ||= File.open(path, 'rb') # could be a named pipe
119
-
117
+ io = body_to_io(body)
120
118
  st = io.stat
119
+
121
120
  if st.file?
122
121
  headers.delete('Transfer-Encoding')
123
122
  headers['Content-Length'] ||= st.size.to_s
124
- response = [ response.first, headers.to_hash, [] ]
125
- HttpResponse.write(self, response, out)
126
- stream = stream_file_data(path)
123
+ write_header(self, [ response[0], headers ], out)
124
+ stream = stream_file_data(body.to_path)
127
125
  stream.callback { quit } unless alive
128
126
  elsif st.socket? || st.pipe?
129
127
  do_chunk = !!(headers['Transfer-Encoding'] =~ %r{\Achunked\z}i)
@@ -133,15 +131,14 @@ module Rainbows
133
131
  else
134
132
  out[0] = CONN_CLOSE
135
133
  end
136
- response = [ response.first, headers.to_hash, [] ]
137
- HttpResponse.write(self, response, out)
134
+ write_header(self, [ response[0], headers ], out)
138
135
  if do_chunk
139
136
  EM.watch(io, ResponseChunkPipe, self).notify_readable = true
140
137
  else
141
138
  EM.enable_proxy(EM.attach(io, ResponsePipe, self), self, 16384)
142
139
  end
143
140
  else
144
- HttpResponse.write(self, response, out)
141
+ write_response(self, response, out)
145
142
  end
146
143
  end
147
144
 
@@ -152,7 +149,7 @@ module Rainbows
152
149
  end
153
150
  end
154
151
 
155
- module ResponsePipe
152
+ module ResponsePipe # :nodoc: all
156
153
  def initialize(client)
157
154
  @client = client
158
155
  end
@@ -163,7 +160,7 @@ module Rainbows
163
160
  end
164
161
  end
165
162
 
166
- module ResponseChunkPipe
163
+ module ResponseChunkPipe # :nodoc: all
167
164
  include ResponsePipe
168
165
 
169
166
  def unbind
@@ -190,7 +187,7 @@ module Rainbows
190
187
  end
191
188
  end
192
189
 
193
- module Server
190
+ module Server # :nodoc: all
194
191
 
195
192
  def close
196
193
  detach
@@ -208,7 +205,7 @@ module Rainbows
208
205
  # Middleware that will run the app dispatch in a separate thread.
209
206
  # This middleware is automatically loaded by Rainbows! when using
210
207
  # EventMachine and if the app responds to the +deferred?+ method.
211
- class TryDefer < Struct.new(:app)
208
+ class TryDefer < Struct.new(:app) # :nodoc: all
212
209
 
213
210
  def initialize(app)
214
211
  # the entire app becomes multithreaded, even the root (non-deferred)
@@ -229,10 +226,15 @@ module Rainbows
229
226
  end
230
227
  end
231
228
 
229
+ def init_worker_process(worker) # :nodoc:
230
+ Rainbows::Response.setup(Rainbows::EventMachine::Client)
231
+ super
232
+ end
233
+
232
234
  # runs inside each forked worker, this sits around and waits
233
235
  # for connections and doesn't die until the parent dies (or is
234
236
  # given a INT, QUIT, or TERM signal)
235
- def worker_loop(worker)
237
+ def worker_loop(worker) # :nodoc:
236
238
  init_worker_process(worker)
237
239
  G.server.app.respond_to?(:deferred?) and
238
240
  G.server.app = TryDefer[G.server.app]
@@ -1,14 +1,15 @@
1
1
  # -*- encoding: binary -*-
2
+ # :enddoc:
2
3
  require 'rainbows/fiber/io'
3
4
 
4
5
  module Rainbows
5
6
  module Fiber
6
7
 
7
- # blocked readers (key: Rainbows::Fiber::IO object, value is irrelevant)
8
- RD = {}.compare_by_identity
8
+ # blocked readers (key: fileno, value: Rainbows::Fiber::IO object)
9
+ RD = []
9
10
 
10
- # blocked writers (key: Rainbows::Fiber::IO object, value is irrelevant)
11
- WR = {}.compare_by_identity
11
+ # blocked writers (key: fileno, value: Rainbows::Fiber::IO object)
12
+ WR = []
12
13
 
13
14
  # sleeping fibers go here (key: Fiber object, value: wakeup time)
14
15
  ZZ = {}.compare_by_identity
@@ -35,9 +36,10 @@ module Rainbows
35
36
  def schedule(&block)
36
37
  ret = begin
37
38
  G.tick
38
- RD.keys.each { |c| c.f.resume } # attempt to time out idle clients
39
+ RD.compact.each { |c| c.f.resume } # attempt to time out idle clients
39
40
  t = schedule_sleepers
40
- Kernel.select(RD.keys.concat(LISTENERS), WR.keys, nil, t) or return
41
+ Kernel.select(RD.compact.concat(LISTENERS),
42
+ WR.compact, nil, t) or return
41
43
  rescue Errno::EINTR
42
44
  retry
43
45
  rescue Errno::EBADF, TypeError
@@ -46,10 +48,10 @@ module Rainbows
46
48
  end or return
47
49
 
48
50
  # active writers first, then _all_ readers for keepalive timeout
49
- ret[1].concat(RD.keys).each { |c| c.f.resume }
51
+ ret[1].concat(RD.compact).each { |c| c.f.resume }
50
52
 
51
53
  # accept is an expensive syscall, filter out listeners we don't want
52
- (ret.first & LISTENERS).each(&block)
54
+ (ret[0] & LISTENERS).each(&block)
53
55
  end
54
56
 
55
57
  # wakes up any sleepers that need to be woken and
@@ -61,54 +63,42 @@ module Rainbows
61
63
  ZZ.delete_if { |fib, time|
62
64
  if now >= time
63
65
  fibs << fib
64
- now = Time.now
65
66
  else
66
67
  max = time
67
68
  false
68
69
  end
69
70
  }
70
71
  fibs.each { |fib| fib.resume }
72
+ now = Time.now
71
73
  max.nil? || max > (now + 1) ? 1 : max - now
72
74
  end
73
75
 
74
- def process_client(client)
75
- G.cur += 1
76
+ def wait_headers_readable(client)
76
77
  io = client.to_io
77
- buf = client.read_timeout or return
78
- hp = HttpParser.new
79
- env = {}
80
- alive = true
81
- remote_addr = Rainbows.addr(io)
82
-
83
- begin # loop
84
- while ! hp.headers(env, buf)
85
- buf << (client.read_timeout or return)
86
- end
87
-
88
- env[CLIENT_IO] = client
89
- env[RACK_INPUT] = 0 == hp.content_length ?
90
- HttpRequest::NULL_IO : TeeInput.new(client, env, hp, buf)
91
- env[REMOTE_ADDR] = remote_addr
92
- response = APP.call(env.update(RACK_DEFAULTS))
93
-
94
- if 100 == response.first.to_i
95
- client.write(EXPECT_100_RESPONSE)
96
- env.delete(HTTP_EXPECT)
97
- response = APP.call(env)
98
- end
78
+ expire = nil
79
+ begin
80
+ return io.recv_nonblock(1, Socket::MSG_PEEK)
81
+ rescue Errno::EAGAIN
82
+ return if expire && expire < Time.now
83
+ expire ||= Time.now + G.kato
84
+ client.wait_readable
85
+ retry
86
+ end
87
+ end
99
88
 
100
- alive = hp.keepalive? && G.alive
101
- out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if hp.headers?
102
- HttpResponse.write(client, response, out)
103
- end while alive and hp.reset.nil? and env.clear
104
- rescue => e
105
- Error.write(io, e)
89
+ def process_client(client)
90
+ G.cur += 1
91
+ super(client) # see Rainbows::Base
106
92
  ensure
107
93
  G.cur -= 1
108
94
  ZZ.delete(client.f)
109
- client.close
110
95
  end
111
96
 
97
+ def self.setup(klass, app)
98
+ require 'rainbows/fiber/body'
99
+ klass.__send__(:include, Rainbows::Fiber::Body)
100
+ self.const_set(:APP, app)
101
+ end
112
102
  end
113
103
  end
114
104
  end
@@ -0,0 +1,34 @@
1
+ # -*- encoding: binary -*-
2
+ # :enddoc:
3
+ # non-portable body handling for Fiber-based concurrency goes here
4
+ # this module is required and included in worker processes only
5
+ # this is meant to be included _after_ Rainbows::Response::Body
6
+ module Rainbows::Fiber::Body # :nodoc:
7
+
8
+ # TODO non-blocking splice(2) under Linux
9
+ ALIASES = {
10
+ :write_body_stream => :write_body_each
11
+ }
12
+
13
+ # the sendfile 1.0.0+ gem includes IO#sendfile_nonblock
14
+ if ::IO.method_defined?(:sendfile_nonblock)
15
+ def write_body_file(client, body)
16
+ sock, off = client.to_io, 0
17
+ begin
18
+ off += sock.sendfile_nonblock(body, off, 0x10000)
19
+ rescue Errno::EAGAIN
20
+ client.wait_writable
21
+ rescue EOFError
22
+ break
23
+ end while true
24
+ end
25
+ else
26
+ ALIASES[:write_body] = :write_body_each
27
+ end
28
+
29
+ def self.included(klass)
30
+ ALIASES.each do |new_method, orig_method|
31
+ klass.__send__(:alias_method, new_method, orig_method)
32
+ end
33
+ end
34
+ end
@@ -7,6 +7,20 @@ module Rainbows
7
7
  # interface that yields away from the current Fiber whenever
8
8
  # the underlying IO object cannot read or write
9
9
  class IO < Struct.new(:to_io, :f)
10
+ include Rainbows::ByteSlice
11
+
12
+ # :stopdoc:
13
+ LOCALHOST = Unicorn::HttpRequest::LOCALHOST
14
+
15
+ # needed to write errors with
16
+ def write_nonblock(buf)
17
+ to_io.write_nonblock(buf)
18
+ end
19
+
20
+ # enough for Rainbows.addr
21
+ def peeraddr
22
+ to_io.respond_to?(:peeraddr) ? to_io.peeraddr : [ LOCALHOST ]
23
+ end
10
24
 
11
25
  # for wrapping output response bodies
12
26
  def each(&block)
@@ -19,27 +33,33 @@ module Rainbows
19
33
  end
20
34
 
21
35
  def close
22
- RD.delete(self)
23
- WR.delete(self)
36
+ fileno = to_io.fileno
37
+ RD[fileno] = WR[fileno] = nil
24
38
  to_io.close unless to_io.closed?
25
39
  end
26
40
 
41
+ def closed?
42
+ to_io.closed?
43
+ end
44
+
27
45
  def wait_readable
28
- RD[self] = false
46
+ fileno = to_io.fileno
47
+ RD[fileno] = self
29
48
  ::Fiber.yield
30
- RD.delete(self)
49
+ RD[fileno] = nil
31
50
  end
32
51
 
33
52
  def wait_writable
34
- WR[self] = false
53
+ fileno = to_io.fileno
54
+ WR[fileno] = self
35
55
  ::Fiber.yield
36
- WR.delete(self)
56
+ WR[fileno] = nil
37
57
  end
38
58
 
39
59
  def write(buf)
40
60
  begin
41
- (w = to_io.write_nonblock(buf)) == buf.size and return
42
- buf = buf[w..-1]
61
+ (w = to_io.write_nonblock(buf)) == buf.bytesize and return
62
+ buf = byte_slice(buf, w..-1)
43
63
  rescue Errno::EAGAIN
44
64
  wait_writable
45
65
  retry
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: binary -*-
2
+ # :enddoc:
2
3
  module Rainbows
3
4
  module Fiber
4
5
 
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: binary -*-
2
+ # :enddoc:
2
3
  require 'rev'
3
4
  require 'rainbows/fiber'
4
5
  require 'rainbows/fiber/io'
@@ -52,6 +53,7 @@ module Rainbows::Fiber
52
53
  include Unicorn
53
54
  include Rainbows
54
55
  include Rainbows::Const
56
+ include Rainbows::Response
55
57
  FIO = Rainbows::Fiber::IO
56
58
 
57
59
  def to_io
@@ -91,7 +93,7 @@ module Rainbows::Fiber
91
93
  env[REMOTE_ADDR] = remote_addr
92
94
  response = APP.call(env.update(RACK_DEFAULTS))
93
95
 
94
- if 100 == response.first.to_i
96
+ if 100 == response[0].to_i
95
97
  client.write(EXPECT_100_RESPONSE)
96
98
  env.delete(HTTP_EXPECT)
97
99
  response = APP.call(env)
@@ -99,7 +101,7 @@ module Rainbows::Fiber
99
101
 
100
102
  alive = hp.keepalive? && G.alive
101
103
  out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if hp.headers?
102
- HttpResponse.write(client, response, out)
104
+ write_response(client, response, out)
103
105
  end while alive and hp.reset.nil? and env.clear
104
106
  rescue => e
105
107
  Error.write(io, e)
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: binary -*-
2
+ # :enddoc:
2
3
  begin
3
4
  require 'fiber'
4
5
  rescue LoadError
@@ -16,7 +16,7 @@ module Rainbows
16
16
  module FiberPool
17
17
  include Fiber::Base
18
18
 
19
- def worker_loop(worker)
19
+ def worker_loop(worker) # :nodoc:
20
20
  init_worker_process(worker)
21
21
  pool = []
22
22
  worker_connections.times {
@@ -24,7 +24,7 @@ module Rainbows
24
24
  process_client(::Fiber.yield) while pool << ::Fiber.current
25
25
  }.resume # resume to hit ::Fiber.yield so it waits on a client
26
26
  }
27
- Fiber::Base.const_set(:APP, app)
27
+ Fiber::Base.setup(self.class, app)
28
28
 
29
29
  begin
30
30
  schedule do |l|
@@ -13,9 +13,9 @@ module Rainbows
13
13
  module FiberSpawn
14
14
  include Fiber::Base
15
15
 
16
- def worker_loop(worker)
16
+ def worker_loop(worker) # :nodoc:
17
17
  init_worker_process(worker)
18
- Fiber::Base.const_set(:APP, app)
18
+ Fiber::Base.setup(self.class, app)
19
19
  limit = worker_connections
20
20
  fio = Rainbows::Fiber::IO
21
21
 
@@ -1,38 +1,27 @@
1
1
  # -*- encoding: binary -*-
2
- require 'time'
3
-
4
- module Rainbows
5
-
6
- class HttpResponse < ::Unicorn::HttpResponse
7
-
8
- def self.header_string(status, headers, out)
9
- status = CODES[status.to_i] || status
2
+ # :enddoc:
3
+ # deprecated, use Rainbows::Response instead
4
+ # Cramp 0.11 relies on this, and is only activated by Cramp
5
+ if defined?(Cramp) && defined?(Rainbows::EventMachine::Client)
6
+ class Rainbows::HttpResponse
7
+ class << self
8
+ include Rainbows::Response
9
+ alias write write_response
10
+ end
11
+ end
10
12
 
11
- headers.each do |key, value|
12
- next if %r{\AX-Rainbows-}i =~ key
13
- next if SKIP.include?(key.downcase)
14
- if value =~ /\n/
15
- # avoiding blank, key-only cookies with /\n+/
16
- out.concat(value.split(/\n+/).map! { |v| "#{key}: #{v}\r\n" })
17
- else
18
- out << "#{key}: #{value}\r\n"
19
- end
13
+ module Rainbows::EventMachine::CrampSocket
14
+ def write_header(_, response, out)
15
+ if websocket?
16
+ write web_socket_upgrade_data
17
+ web_socket_handshake!
18
+ out = nil # disable response headers
20
19
  end
21
-
22
- "HTTP/1.1 #{status}\r\n" \
23
- "Date: #{Time.now.httpdate}\r\n" \
24
- "Status: #{status}\r\n" \
25
- "#{out.join('')}\r\n"
20
+ super(self, response, out)
26
21
  end
22
+ end
27
23
 
28
- def self.write(socket, rack_response, out = [])
29
- status, headers, body = rack_response
30
- out.instance_of?(Array) and
31
- socket.write(header_string(status, headers, out))
32
-
33
- body.each { |chunk| socket.write(chunk) }
34
- ensure
35
- body.respond_to?(:close) and body.close
36
- end
24
+ class Rainbows::EventMachine::Client
25
+ include Rainbows::EventMachine::CrampSocket
37
26
  end
38
27
  end
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: binary -*-
2
+ # :enddoc:
2
3
  module Rainbows
3
4
 
4
5
  class HttpServer < ::Unicorn::HttpServer
@@ -33,10 +34,8 @@ module Rainbows
33
34
  # connection we accept without wasting cycles. That added to the
34
35
  # fact that we let clients keep idle connections open for long
35
36
  # periods of time means we have to chmod at a fixed interval.
36
- alias_method :set_timeout, :timeout=
37
- undef_method :timeout=
38
37
  def timeout=(nr)
39
- set_timeout(nr + 1)
38
+ super(nr + 1)
40
39
  end
41
40
  #:startdoc:
42
41
 
@@ -70,7 +69,7 @@ module Rainbows
70
69
 
71
70
  def worker_connections(*args)
72
71
  return @worker_connections if args.empty?
73
- nr = args.first
72
+ nr = args[0]
74
73
  (Integer === nr && nr > 0) or
75
74
  raise ArgumentError, "worker_connections must be a positive Integer"
76
75
  @worker_connections = nr
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: binary -*-
2
+ # :enddoc:
2
3
  module Rainbows
3
4
 
4
5
  # middleware used to enforce client_max_body_size for TeeInput users,
@@ -1,3 +1,5 @@
1
+ # -*- encoding: binary -*-
2
+ # :enddoc:
1
3
  module Rainbows
2
4
  module NeverBlock
3
5
  class Client < Rainbows::EventMachine::Client
@@ -18,13 +18,14 @@ module Rainbows
18
18
  #
19
19
  module NeverBlock
20
20
 
21
+ # :stopdoc:
21
22
  DEFAULTS = {
22
23
  :pool_size => 20, # same default size used by NB
23
24
  :backend => :EventMachine, # NeverBlock doesn't support Rev yet
24
25
  }
25
26
 
26
27
  # same pool size NB core itself uses
27
- def self.setup
28
+ def self.setup # :nodoc:
28
29
  DEFAULTS.each { |k,v| O[k] ||= v }
29
30
  Integer === O[:pool_size] && O[:pool_size] > 0 or
30
31
  raise ArgumentError, "pool_size must a be an Integer > 0"
@@ -34,7 +35,7 @@ module Rainbows
34
35
  G.server.extend(Core)
35
36
  end
36
37
 
37
- module Core
38
+ module Core # :nodoc: all
38
39
  def self.setup
39
40
  self.const_set(:POOL, ::NB::Pool::FiberPool.new(O[:pool_size]))
40
41
  base = O[:backend].to_s.gsub!(/([a-z])([A-Z])/, '\1_\2').downcase!
@@ -57,9 +58,7 @@ module Rainbows
57
58
  end
58
59
  end
59
60
  end
60
- end
61
61
 
62
- module Core
63
62
  def init_worker_process(worker)
64
63
  super
65
64
  Core.setup
@@ -67,5 +66,7 @@ module Rainbows
67
66
  end
68
67
  end
69
68
 
69
+ # :startdoc:
70
+
70
71
  end
71
72
  end
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: binary -*-
2
+ # :enddoc:
2
3
  require 'thread'
3
4
 
4
5
  module Rainbows