rainbows 3.3.0 → 3.4.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.
data/.gitignore CHANGED
@@ -17,3 +17,5 @@ pkg/
17
17
  /GIT-VERSION-FILE
18
18
  /man
19
19
  /LATEST
20
+ tags
21
+ TAGS
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v3.3.0.GIT
4
+ DEF_VER=v3.4.0.GIT
5
5
 
6
6
  LF='
7
7
  '
@@ -29,4 +29,6 @@ class Rainbows::Client < Kgio::Socket
29
29
  end
30
30
  end while true
31
31
  end
32
+
33
+ alias write kgio_write
32
34
  end
@@ -190,7 +190,9 @@ module Rainbows::Configurator
190
190
  # end
191
191
  #
192
192
  # Keep in mind that splice(2) itself is a relatively new system call
193
- # and has been buggy in many older Linux kernels.
193
+ # and has been buggy in many older Linux kernels. If you're proxying
194
+ # the output of sockets to the client, be sure to use "io_splice"
195
+ # 4.1.1 or later to avoid stalling responses.
194
196
  #
195
197
  # Default: IO on Ruby 1.9+, false otherwise
196
198
  def copy_stream(klass)
@@ -9,6 +9,7 @@ class Rainbows::Coolio::Heartbeat < Coolio::TimerWatcher
9
9
  KATO = Rainbows::Coolio::KATO
10
10
  CONN = Rainbows::Coolio::CONN
11
11
  Rainbows.config!(self, :keepalive_timeout)
12
+ Rainbows.at_quit { KATO.each_key { |client| client.timeout? }.clear }
12
13
 
13
14
  def on_timer
14
15
  if (ot = KEEPALIVE_TIMEOUT) >= 0
@@ -22,44 +22,27 @@ require 'sendfile'
22
22
  # === RubyGem Requirements
23
23
  #
24
24
  # * raindrops 0.6.0 or later
25
- # * sleepy_penguin 2.0.0 or later
25
+ # * sleepy_penguin 3.0.1 or later
26
26
  # * sendfile 1.1.0 or later
27
27
  #
28
28
  module Rainbows::Epoll
29
29
  # :stopdoc:
30
30
  include Rainbows::Base
31
- ReRun = []
32
31
  autoload :Server, 'rainbows/epoll/server'
33
32
  autoload :Client, 'rainbows/epoll/client'
34
33
  autoload :ResponsePipe, 'rainbows/epoll/response_pipe'
35
34
  autoload :ResponseChunkPipe, 'rainbows/epoll/response_chunk_pipe'
36
- class << self
37
- attr_writer :nr_clients
38
- end
39
-
40
- def self.loop
41
- begin
42
- EP.wait(nil, 1000) { |_, obj| obj.epoll_run }
43
- while obj = ReRun.shift
44
- obj.epoll_run
45
- end
46
- Rainbows::Epoll::Client.expire
47
- rescue Errno::EINTR
48
- rescue => e
49
- Rainbows::Error.listen_loop(e)
50
- end while Rainbows.tick || @nr_clients.call > 0
51
- end
52
35
 
53
36
  def init_worker_process(worker)
54
37
  super
55
- Rainbows::Epoll.const_set :EP, SleepyPenguin::Epoll.new
56
- Rainbows.at_quit { Rainbows::Epoll::EP.close }
38
+ Rainbows.const_set(:EP, SleepyPenguin::Epoll.new)
57
39
  Rainbows::Client.__send__ :include, Client
40
+ LISTENERS.each { |io| io.extend(Server) }
58
41
  end
59
42
 
60
43
  def worker_loop(worker) # :nodoc:
61
44
  init_worker_process(worker)
62
- Server.run
45
+ Client.loop
63
46
  end
64
47
  # :startdoc:
65
48
  end
@@ -10,8 +10,10 @@ module Rainbows::Epoll::Client
10
10
  OUT = SleepyPenguin::Epoll::OUT | SleepyPenguin::Epoll::ET
11
11
  KATO = {}
12
12
  KATO.compare_by_identity if KATO.respond_to?(:compare_by_identity)
13
+ Rainbows.at_quit { KATO.each_key { |k| k.timeout! }.clear }
13
14
  Rainbows.config!(self, :keepalive_timeout)
14
- EP = Rainbows::Epoll::EP
15
+ EP = Rainbows::EP
16
+ ReRun = []
15
17
  @@last_expire = Time.now
16
18
 
17
19
  def self.expire
@@ -23,6 +25,19 @@ module Rainbows::Epoll::Client
23
25
  @@last_expire = now
24
26
  end
25
27
 
28
+ def self.loop
29
+ begin
30
+ EP.wait(nil, 1000) { |_, obj| obj.epoll_run }
31
+ while obj = ReRun.shift
32
+ obj.epoll_run
33
+ end
34
+ expire
35
+ rescue Errno::EINTR
36
+ rescue => e
37
+ Rainbows::Error.listen_loop(e)
38
+ end while Rainbows.tick || Server.nr > 0
39
+ end
40
+
26
41
  # only call this once
27
42
  def epoll_once
28
43
  @wr_queue = [] # may contain String, ResponsePipe, and StreamFile objects
@@ -100,7 +115,7 @@ module Rainbows::Epoll::Client
100
115
  end
101
116
 
102
117
  def want_more
103
- Rainbows::Epoll::ReRun << self
118
+ ReRun << self
104
119
  end
105
120
 
106
121
  def on_deferred_write_complete
@@ -5,7 +5,7 @@ class Rainbows::Epoll::ResponsePipe
5
5
  attr_reader :io
6
6
  alias to_io io
7
7
  RBUF = Rainbows::EvCore::RBUF
8
- EP = Rainbows::Epoll::EP
8
+ EP = Rainbows::EP
9
9
 
10
10
  def initialize(io, client, body)
11
11
  @io, @client, @body = io, client, body
@@ -2,16 +2,14 @@
2
2
  # :enddoc:
3
3
  module Rainbows::Epoll::Server
4
4
  @@nr = 0
5
- Rainbows::Epoll.nr_clients = lambda { @@nr }
6
5
  IN = SleepyPenguin::Epoll::IN | SleepyPenguin::Epoll::ET
7
6
  MAX = Rainbows.server.worker_connections
8
7
  THRESH = MAX - 1
9
8
  LISTENERS = Rainbows::HttpServer::LISTENERS
10
- EP = Rainbows::Epoll::EP
9
+ EP = Rainbows::EP
11
10
 
12
- def self.run
13
- LISTENERS.each { |sock| EP.add(sock.extend(self), IN) }
14
- Rainbows::Epoll.loop
11
+ def self.nr
12
+ @@nr
15
13
  end
16
14
 
17
15
  # rearms all listeners when there's a free slot
@@ -19,6 +17,10 @@ module Rainbows::Epoll::Server
19
17
  THRESH == (@@nr -= 1) and LISTENERS.each { |sock| EP.set(sock, IN) }
20
18
  end
21
19
 
20
+ def self.extended(sock)
21
+ EP.set(sock, IN)
22
+ end
23
+
22
24
  def epoll_run
23
25
  return EP.delete(self) if @@nr >= MAX
24
26
  while io = kgio_tryaccept
@@ -32,9 +32,7 @@ EM::VERSION >= '0.12.10' or abort 'eventmachine 0.12.10 is required'
32
32
  # all request processing is complete.
33
33
  #
34
34
  # Merb (and other frameworks/apps) supporting +deferred?+ execution as
35
- # documented at http://brainspl.at/articles/2008/04/18/deferred-requests-with-merb-ebb-and-thin
36
- # will also get the ability to conditionally defer request processing
37
- # to a separate thread.
35
+ # documented at Rainbows::EventMachine::TryDefer
38
36
  #
39
37
  # This model does not implement as streaming "rack.input" which allows
40
38
  # the Rack application to process data as it arrives. This means
@@ -74,11 +72,11 @@ module Rainbows::EventMachine
74
72
  conns = EM.instance_variable_get(:@conns) or
75
73
  raise RuntimeError, "EM @conns instance variable not accessible!"
76
74
  Rainbows::EventMachine::Server.const_set(:CUR, conns)
75
+ Rainbows.at_quit do
76
+ EM.next_tick { conns.each_value { |c| client_class === c and c.quit } }
77
+ end
77
78
  EM.add_periodic_timer(1) do
78
- unless Rainbows.tick
79
- conns.each_value { |c| client_class === c and c.quit }
80
- EM.stop if conns.empty? && EM.reactor_running?
81
- end
79
+ EM.stop if ! Rainbows.tick && conns.empty? && EM.reactor_running?
82
80
  end
83
81
  LISTENERS.map! do |s|
84
82
  EM.watch(s, Rainbows::EventMachine::Server) do |c|
@@ -1,27 +1,32 @@
1
1
  # -*- encoding: binary -*-
2
- # :enddoc:
3
2
 
4
3
  # Middleware that will run the app dispatch in a separate thread.
5
4
  # This middleware is automatically loaded by Rainbows! when using
6
5
  # EventMachine and if the app responds to the +deferred?+ method.
7
- class Rainbows::EventMachine::TryDefer < Struct.new(:app)
6
+ #
7
+ # Use EM.threadpool_size in your \Rainbows! config file to control
8
+ # the number of threads used by EventMachine.
9
+ #
10
+ # See http://brainspl.at/articles/2008/04/18/deferred-requests-with-merb-ebb-and-thin
11
+ # for more information.
12
+ class Rainbows::EventMachine::TryDefer
8
13
  # shortcuts
9
- ASYNC_CALLBACK = Rainbows::EvCore::ASYNC_CALLBACK
14
+ ASYNC_CALLBACK = Rainbows::EvCore::ASYNC_CALLBACK # :nodoc:
10
15
 
11
- def initialize(app)
16
+ def initialize(app) # :nodoc:
12
17
  # the entire app becomes multithreaded, even the root (non-deferred)
13
18
  # thread since any thread can share processes with others
14
19
  Rainbows::Const::RACK_DEFAULTS['rack.multithread'] = true
15
- super
20
+ @app = app
16
21
  end
17
22
 
18
- def call(env)
19
- if app.deferred?(env)
20
- EM.defer(proc { catch(:async) { app.call(env) } }, env[ASYNC_CALLBACK])
23
+ def call(env) # :nodoc:
24
+ if @app.deferred?(env)
25
+ EM.defer(proc { catch(:async) { @app.call(env) } }, env[ASYNC_CALLBACK])
21
26
  # all of the async/deferred stuff breaks Rack::Lint :<
22
27
  nil
23
28
  else
24
- app.call(env)
29
+ @app.call(env)
25
30
  end
26
31
  end
27
32
  end
@@ -10,7 +10,7 @@ require 'rainbows/epoll'
10
10
  # === RubyGem Requirements
11
11
  #
12
12
  # * raindrops 0.6.0 or later
13
- # * sleepy_penguin 2.0.0 or later
13
+ # * sleepy_penguin 3.0.1 or later
14
14
  # * sendfile 1.1.0 or later
15
15
  module Rainbows::XEpoll
16
16
  # :stopdoc:
@@ -19,14 +19,13 @@ module Rainbows::XEpoll
19
19
 
20
20
  def init_worker_process(worker)
21
21
  super
22
- Rainbows::Epoll.const_set :EP, SleepyPenguin::Epoll.new
23
- Rainbows.at_quit { Rainbows::Epoll::EP.close }
22
+ Rainbows.const_set(:EP, SleepyPenguin::Epoll.new)
24
23
  Rainbows::Client.__send__ :include, Client
25
24
  end
26
25
 
27
26
  def worker_loop(worker) # :nodoc:
28
27
  init_worker_process(worker)
29
- Client.run
28
+ Client.loop
30
29
  end
31
30
  # :startdoc:
32
31
  end
@@ -3,9 +3,7 @@
3
3
 
4
4
  module Rainbows::XEpoll::Client
5
5
  N = Raindrops.new(1)
6
- Rainbows::Epoll.nr_clients = lambda { N[0] }
7
6
  include Rainbows::Epoll::Client
8
- EP = Rainbows::Epoll::EP
9
7
  ACCEPTORS = Rainbows::HttpServer::LISTENERS.dup
10
8
  extend Rainbows::WorkerYield
11
9
 
@@ -26,8 +24,17 @@ module Rainbows::XEpoll::Client
26
24
  end
27
25
  end
28
26
 
29
- def self.run
30
- Rainbows::Epoll.loop
27
+ def self.loop
28
+ begin
29
+ EP.wait(nil, 1000) { |_, obj| obj.epoll_run }
30
+ while obj = ReRun.shift
31
+ obj.epoll_run
32
+ end
33
+ Rainbows::Epoll::Client.expire
34
+ rescue Errno::EINTR
35
+ rescue => e
36
+ Rainbows::Error.listen_loop(e)
37
+ end while Rainbows.tick || N[0] > 0
31
38
  Rainbows::JoinThreads.acceptors(ACCEPTORS)
32
39
  end
33
40
 
@@ -61,7 +61,7 @@ require "raindrops"
61
61
  # === RubyGem Requirements
62
62
  #
63
63
  # * raindrops 0.6.0 or later
64
- # * sleepy_penguin 2.0.0 or later
64
+ # * sleepy_penguin 3.0.1 or later
65
65
  module Rainbows::XEpollThreadPool
66
66
  extend Rainbows::PoolSize
67
67
 
@@ -37,11 +37,15 @@ module Rainbows::XEpollThreadPool::Client
37
37
 
38
38
  ep = SleepyPenguin::Epoll
39
39
  EP = ep.new
40
- Rainbows.at_quit { EP.close }
41
40
  IN = ep::IN | ep::ET | ep::ONESHOT
42
41
  KATO = {}
43
42
  KATO.compare_by_identity if KATO.respond_to?(:compare_by_identity)
44
43
  LOCK = Mutex.new
44
+ Rainbows.at_quit do
45
+ clients = nil
46
+ LOCK.synchronize { clients = KATO.keys; KATO.clear }
47
+ clients.each { |io| io.closed? or io.close }
48
+ end
45
49
  @@last_expire = Time.now
46
50
 
47
51
  def kato_set
@@ -123,7 +127,7 @@ module Rainbows::XEpollThreadPool::Client
123
127
  def pipeline_ready(hp)
124
128
  # be fair to other clients, let others run first
125
129
  hp.parse and return queue!
126
- kato_set
130
+ epoll_run("")
127
131
  false
128
132
  end
129
133
  end
@@ -39,7 +39,7 @@ require "raindrops"
39
39
  # === RubyGem Requirements
40
40
  #
41
41
  # * raindrops 0.6.0 or later
42
- # * sleepy_penguin 2.0.0 or later
42
+ # * sleepy_penguin 3.0.1 or later
43
43
  module Rainbows::XEpollThreadSpawn
44
44
  # :stopdoc:
45
45
  include Rainbows::Base
@@ -26,11 +26,15 @@ module Rainbows::XEpollThreadSpawn::Client
26
26
 
27
27
  ep = SleepyPenguin::Epoll
28
28
  EP = ep.new
29
- Rainbows.at_quit { EP.close }
30
29
  IN = ep::IN | ep::ET | ep::ONESHOT
31
30
  KATO = {}
32
31
  KATO.compare_by_identity if KATO.respond_to?(:compare_by_identity)
33
32
  LOCK = Mutex.new
33
+ Rainbows.at_quit do
34
+ clients = nil
35
+ LOCK.synchronize { clients = KATO.keys; KATO.clear }
36
+ clients.each { |io| io.closed? or io.close }
37
+ end
34
38
  @@last_expire = Time.now
35
39
 
36
40
  def kato_set
data/pkg.mk CHANGED
@@ -69,7 +69,7 @@ doc:: .document .wrongdoc.yml $(pkg_extra)
69
69
  $(RM) -r doc
70
70
  $(WRONGDOC) all
71
71
  install -m644 COPYING doc/COPYING
72
- install -m644 $(shell grep '^[A-Z]' .document) doc/
72
+ install -m644 $(shell LC_ALL=C grep '^[A-Z]' .document) doc/
73
73
 
74
74
  ifneq ($(VERSION),)
75
75
  pkggem := pkg/$(rfpackage)-$(VERSION).gem
@@ -168,7 +168,7 @@ doc_gz:
168
168
  for i in $(docs); do \
169
169
  gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
170
170
  check-warnings:
171
- @(for i in $$(git ls-files '*.rb'|grep -v '^setup\.rb$$'); \
171
+ @(for i in $$(git ls-files '*.rb'| grep -v '^setup\.rb$$'); \
172
172
  do $(RUBY) -d -W2 -c $$i; done) | grep -v '^Syntax OK$$' || :
173
173
 
174
174
  .PHONY: all .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
@@ -9,6 +9,9 @@ map "/rss" do
9
9
  [ 200, {}, [ ($1.to_i * 1024).to_s ] ]
10
10
  }
11
11
  end
12
+ map "/pid" do
13
+ run lambda { |env| [ 200, {}, [ "#{Process.pid}\n" ] ] }
14
+ end
12
15
  map "/" do
13
16
  run Rack::File.new(Dir.pwd)
14
17
  end
@@ -0,0 +1,59 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ case $model in
4
+ Coolio|CoolioThreadSpawn|CoolioThreadPool|EventMachine) ;;
5
+ Epoll|XEpoll|XEpollThreadPool|XEpollThreadSpawn) ;;
6
+ *)
7
+ t_info "$0 not supported for $model"
8
+ exit 0
9
+ ;;
10
+ esac
11
+
12
+ t_plan 7 "keepalive clients disconnected on SIGQUIT for $model"
13
+
14
+ t_begin "setup and start" && {
15
+ rainbows_setup $model 50 30
16
+ rainbows -E none -D env.ru -c $unicorn_config
17
+ rainbows_wait_start
18
+ }
19
+
20
+ t_begin "start a keepalive request" && {
21
+ (
22
+ cat < $fifo > $tmp &
23
+ printf 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'
24
+ wait
25
+ ) | socat - TCP4:$listen > $fifo &
26
+ }
27
+
28
+ t_begin "wait for response" && {
29
+ while ! tail -1 < $tmp | grep '}$' >/dev/null
30
+ do
31
+ sleep 1
32
+ done
33
+ }
34
+
35
+ t_begin "stop Rainbows! gracefully" && {
36
+ t0=$(date +%s)
37
+ kill -QUIT $rainbows_pid
38
+ }
39
+
40
+ t_begin "keepalive client disconnected quickly" && {
41
+ wait
42
+ diff=$(( $(date +%s) - $t0 ))
43
+ test $diff -le 2 || die "client diff=$diff > 2"
44
+ }
45
+
46
+ t_begin "wait for termination" && {
47
+ while kill -0 $rainbows_pid
48
+ do
49
+ sleep 1
50
+ done
51
+ diff=$(( $(date +%s) - $t0 ))
52
+ test $diff -le 4 || die "server diff=$diff > 4"
53
+ }
54
+
55
+ t_begin "check stderr" && {
56
+ check_stderr
57
+ }
58
+
59
+ t_done
@@ -0,0 +1,120 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ STRACE=$(which strace 2>/dev/null || :)
4
+ if ! test -x "$STRACE"
5
+ then
6
+ t_info "strace not found, skipping $T"
7
+ exit 0
8
+ fi
9
+ if test x"$(uname -s)" != xLinux
10
+ then
11
+ t_info "Linux is the only supported OS for $T"
12
+ exit 0
13
+ fi
14
+
15
+ # these buffer internally in external libraries, so we can't detect when
16
+ # to use TCP_CORK
17
+ skip_models EventMachine NeverBlock
18
+ skip_models Coolio CoolioThreadPool CoolioThreadSpawn
19
+ skip_models Revactor Rev RevThreadPool RevThreadSpawn
20
+
21
+ # not sure why, but we don't have time to care about Ruby 1.8 too much
22
+ case $RUBY_VERSION in
23
+ 1.8.*) skip_models WriterThreadSpawn WriterThreadPool ;;
24
+ esac
25
+
26
+ t_plan 13 "Kgio autopush tests"
27
+
28
+ start_strace () {
29
+ # dbgcat strace_out
30
+ > $strace_out
31
+ sleep 1
32
+ strace -p $worker_pid -e '!futex' -f -o $strace_out &
33
+ strace_pid=$!
34
+ while ! test -s $strace_out; do sleep 1; done
35
+ }
36
+
37
+ check_TCP_CORK () {
38
+ nr=0
39
+ while test 2 -gt $(grep TCP_CORK $strace_out | wc -l)
40
+ do
41
+ nr=$(( $nr + 1 ))
42
+ if test $nr -gt 30
43
+ then
44
+ dbgcat strace_out
45
+ die "waited too long ($nr seconds) for TCP_CORK"
46
+ fi
47
+ sleep 1
48
+ done
49
+
50
+ test 2 -eq $(grep TCP_CORK $strace_out | wc -l)
51
+ fgrep 'SOL_TCP, TCP_CORK, [0], 4) = 0' $strace_out
52
+ fgrep 'SOL_TCP, TCP_CORK, [1], 4) = 0' $strace_out
53
+ }
54
+
55
+ t_begin "setup and start" && {
56
+ rainbows_setup $model 1 1
57
+ rtmpfiles strace_out
58
+ ed -s $unicorn_config <<EOF
59
+ ,s/^listen.*/listen "$listen", :tcp_nodelay => true, :tcp_nopush => true/
60
+ w
61
+ EOF
62
+ rainbows -D large-file-response.ru -c $unicorn_config -E none
63
+ rainbows_wait_start
64
+ }
65
+
66
+ t_begin "read worker pid" && {
67
+ worker_pid=$(curl -sSf http://$listen/pid)
68
+ kill -0 $worker_pid
69
+ }
70
+
71
+ t_begin "start strace on worker" && start_strace
72
+
73
+ t_begin "reading RSS uncorks" && {
74
+ curl -sSf http://$listen/rss >/dev/null
75
+ }
76
+
77
+ t_begin "restart strace on worker" && {
78
+ kill $strace_pid
79
+ wait
80
+ start_strace
81
+ }
82
+
83
+ t_begin "reading static file uncorks" && {
84
+ curl -sSf http://$listen/random_blob >/dev/null
85
+ check_TCP_CORK
86
+ }
87
+
88
+ t_begin "stop strace on worker" && {
89
+ kill $strace_pid
90
+ wait
91
+ }
92
+
93
+ t_begin "enable sendfile" && {
94
+ echo >> $unicorn_config 'require "sendfile"'
95
+ kill -HUP $rainbows_pid
96
+ test xSTART = x"$(cat $fifo)"
97
+ }
98
+
99
+ t_begin "reread worker pid" && {
100
+ worker_pid=$(curl -sSf http://$listen/pid)
101
+ kill -0 $worker_pid
102
+ }
103
+
104
+ t_begin "restart strace on the worker" && start_strace
105
+
106
+ t_begin "HTTP/1.x GET on static file with sendfile uncorks" && {
107
+ curl -sSf http://$listen/random_blob >/dev/null
108
+ check_TCP_CORK
109
+ }
110
+
111
+ t_begin "killing succeeds" && {
112
+ kill $strace_pid
113
+ wait
114
+ # dbgcat strace_out
115
+ kill $rainbows_pid
116
+ }
117
+
118
+ t_begin "check stderr" && check_stderr
119
+
120
+ t_done
@@ -38,10 +38,10 @@ Isolate.now!(opts) do
38
38
  end
39
39
 
40
40
  if RUBY_PLATFORM =~ /linux/
41
- gem 'sleepy_penguin', '2.0.0'
41
+ gem 'sleepy_penguin', '3.0.1'
42
42
 
43
43
  # is 2.6.32 new enough?
44
- gem 'io_splice', '4.1.0' if `uname -r`.strip > '2.6.32'
44
+ gem 'io_splice', '4.1.1' if `uname -r`.strip > '2.6.32'
45
45
  end
46
46
  end
47
47
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rainbows
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 3
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 3.3.0
10
+ version: 3.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Rainbows! hackers
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-16 00:00:00 Z
18
+ date: 2011-05-21 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rack
@@ -458,6 +458,8 @@ files:
458
458
  - t/t0040-keepalive_requests-setting.sh
459
459
  - t/t0041-optional-pool-size.sh
460
460
  - t/t0042-client_header_buffer_size.sh
461
+ - t/t0043-quit-keepalive-disconnect.sh
462
+ - t/t0044-autopush.sh
461
463
  - t/t0050-response-body-close-has-env.sh
462
464
  - t/t0100-rack-input-hammer-chunked.sh
463
465
  - t/t0100-rack-input-hammer-content-length.sh