rainbows 0.91.1 → 0.92.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.document +1 -1
  2. data/.gitignore +1 -0
  3. data/.manifest +13 -4
  4. data/ChangeLog +237 -219
  5. data/DEPLOY +13 -13
  6. data/Documentation/comparison.haml +1 -1
  7. data/GIT-VERSION-FILE +1 -1
  8. data/GIT-VERSION-GEN +1 -1
  9. data/GNUmakefile +18 -7
  10. data/NEWS +29 -0
  11. data/README +5 -4
  12. data/Rakefile +7 -0
  13. data/SIGNALS +5 -1
  14. data/TODO +2 -5
  15. data/config/.gitignore +1 -0
  16. data/config/isolate.rb +25 -0
  17. data/lib/rainbows/base.rb +32 -8
  18. data/lib/rainbows/const.rb +3 -2
  19. data/lib/rainbows/ev_core.rb +42 -2
  20. data/lib/rainbows/event_machine.rb +48 -5
  21. data/lib/rainbows/fiber/base.rb +4 -2
  22. data/lib/rainbows/fiber/rev.rb +1 -1
  23. data/lib/rainbows/http_response.rb +21 -20
  24. data/lib/rainbows/http_server.rb +13 -6
  25. data/lib/rainbows/max_body.rb +82 -0
  26. data/lib/rainbows/rev/deferred_response.rb +10 -11
  27. data/lib/rainbows/revactor.rb +38 -4
  28. data/lib/rainbows/tee_input.rb +17 -0
  29. data/lib/rainbows.rb +26 -2
  30. data/local.mk.sample +13 -23
  31. data/rainbows.gemspec +2 -2
  32. data/t/app_deferred.ru +23 -0
  33. data/t/async_examples/async_app.ru +8 -8
  34. data/t/rack-fiber_pool/app.ru +5 -0
  35. data/t/{t0100-rack-input-hammer.sh → t0100-rack-input-hammer-chunked.sh} +1 -1
  36. data/t/t0100-rack-input-hammer-content-length.sh +50 -0
  37. data/t/t0103-rack-input-limit.sh +60 -0
  38. data/t/t0104-rack-input-limit-tiny.sh +62 -0
  39. data/t/t0105-rack-input-limit-bigger.sh +105 -0
  40. data/t/t0401-em-async-tailer.sh +1 -1
  41. data/t/t0600-rack-fiber_pool.sh +49 -0
  42. data/t/t0700-app-deferred.sh +45 -0
  43. data/t/test-lib.sh +1 -0
  44. metadata +22 -10
  45. data/lib/rainbows/event_machine_defer.rb +0 -59
  46. data/lib/rainbows/revactor/tee_input.rb +0 -52
  47. data/t/simple-http_EventMachineDefer.ru +0 -11
@@ -0,0 +1,105 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+
4
+ t_plan 10 "rack.input client_max_body_size bigger"
5
+
6
+ t_begin "setup and startup" && {
7
+ rtmpfiles curl_out curl_err cmbs_config
8
+ rainbows_setup $model
9
+ sed -e 's/client_max_body_size.*/client_max_body_size 10485760/' \
10
+ < $unicorn_config > $cmbs_config
11
+ rainbows -D sha1-random-size.ru -c $cmbs_config
12
+ rainbows_wait_start
13
+ }
14
+
15
+ t_begin "stops a regular request" && {
16
+ rm -f $ok
17
+ dd if=/dev/zero bs=102485761 count=1 of=$tmp
18
+ curl -vsSf -T $tmp -H Expect: \
19
+ http://$listen/ > $curl_out 2> $curl_err || > $ok
20
+ dbgcat curl_err
21
+ dbgcat curl_out
22
+ test -e $ok
23
+ }
24
+
25
+ t_begin "stops a large chunked request" && {
26
+ rm -f $ok
27
+ dd if=/dev/zero bs=102485761 count=1 | \
28
+ curl -vsSf -T- -H Expect: \
29
+ http://$listen/ > $curl_out 2> $curl_err || > $ok
30
+ dbgcat curl_err
31
+ dbgcat curl_out
32
+ test -e $ok
33
+ }
34
+
35
+ t_begin "small size sha1 chunked ok" && {
36
+ blob_sha1=b376885ac8452b6cbf9ced81b1080bfd570d9b91
37
+ rm -f $ok
38
+ dd if=/dev/zero bs=256 count=1 | \
39
+ curl -vsSf -T- -H Expect: \
40
+ http://$listen/ > $curl_out 2> $curl_err
41
+ dbgcat curl_err
42
+ dbgcat curl_out
43
+ test "$(cat $curl_out)" = $blob_sha1
44
+ }
45
+
46
+ t_begin "small size sha1 content-length ok" && {
47
+ blob_sha1=b376885ac8452b6cbf9ced81b1080bfd570d9b91
48
+ rm -f $ok
49
+ dd if=/dev/zero bs=256 count=1 of=$tmp
50
+ curl -vsSf -T $tmp -H Expect: \
51
+ http://$listen/ > $curl_out 2> $curl_err
52
+ dbgcat curl_err
53
+ dbgcat curl_out
54
+ test "$(cat $curl_out)" = $blob_sha1
55
+ }
56
+
57
+ t_begin "right size sha1 chunked ok" && {
58
+ blob_sha1=8c206a1a87599f532ce68675536f0b1546900d7a
59
+ rm -f $ok
60
+ dd if=/dev/zero bs=10485760 count=1 | \
61
+ curl -vsSf -T- -H Expect: \
62
+ http://$listen/ > $curl_out 2> $curl_err
63
+ dbgcat curl_err
64
+ dbgcat curl_out
65
+ test "$(cat $curl_out)" = $blob_sha1
66
+ }
67
+
68
+ t_begin "right size sha1 content-length ok" && {
69
+ blob_sha1=8c206a1a87599f532ce68675536f0b1546900d7a
70
+ rm -f $ok
71
+ dd if=/dev/zero bs=10485760 count=1 of=$tmp
72
+ curl -vsSf -T $tmp -H Expect: \
73
+ http://$listen/ > $curl_out 2> $curl_err
74
+ dbgcat curl_err
75
+ dbgcat curl_out
76
+ test "$(cat $curl_out)" = $blob_sha1
77
+ }
78
+
79
+ t_begin "default size sha1 chunked ok" && {
80
+ blob_sha1=3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
81
+ rm -f $ok
82
+ dd if=/dev/zero bs=1048576 count=1 | \
83
+ curl -vsSf -T- -H Expect: \
84
+ http://$listen/ > $curl_out 2> $curl_err
85
+ dbgcat curl_err
86
+ dbgcat curl_out
87
+ test "$(cat $curl_out)" = $blob_sha1
88
+ }
89
+
90
+ t_begin "default size sha1 content-length ok" && {
91
+ blob_sha1=3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
92
+ rm -f $ok
93
+ dd if=/dev/zero bs=1048576 count=1 of=$tmp
94
+ curl -vsSf -T $tmp -H Expect: \
95
+ http://$listen/ > $curl_out 2> $curl_err
96
+ dbgcat curl_err
97
+ dbgcat curl_out
98
+ test "$(cat $curl_out)" = $blob_sha1
99
+ }
100
+
101
+ t_begin "shutdown" && {
102
+ kill $rainbows_pid
103
+ }
104
+
105
+ t_done
@@ -55,7 +55,7 @@ t_begin "kill curls and wait for termination" && {
55
55
  }
56
56
 
57
57
  t_begin "termination signal sent" && {
58
- kill $rainbows_pid
58
+ kill -QUIT $rainbows_pid
59
59
  }
60
60
 
61
61
  t_begin "no errors from curl" && {
@@ -0,0 +1,49 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ case $model in
4
+ EventMachine) ;;
5
+ *)
6
+ t_info "skipping $T since it's not compatible with $model"
7
+ exit 0
8
+ ;;
9
+ esac
10
+
11
+ require_check rack/fiber_pool Rack::FiberPool
12
+
13
+ t_plan 7 "basic test with rack-fiber_pool gem"
14
+
15
+ CONFIG_RU=rack-fiber_pool/app.ru
16
+
17
+ t_begin "setup and start" && {
18
+ rainbows_setup
19
+ rtmpfiles curl_err curl_out
20
+
21
+ rainbows -D -c $unicorn_config $CONFIG_RU
22
+ rainbows_wait_start
23
+ }
24
+
25
+ t_begin "send requests off in parallel" && {
26
+ curl --no-buffer -sSf http://$listen/ >> $curl_out 2>> $curl_err &
27
+ curl --no-buffer -sSf http://$listen/ >> $curl_out 2>> $curl_err &
28
+ curl --no-buffer -sSf http://$listen/ >> $curl_out 2>> $curl_err &
29
+ }
30
+
31
+ t_begin "wait for curl terminations" && {
32
+ wait
33
+ }
34
+
35
+ t_begin "termination signal sent" && {
36
+ kill $rainbows_pid
37
+ }
38
+
39
+ t_begin "no errors from curl" && {
40
+ test ! -s $curl_err
41
+ }
42
+
43
+ t_begin "no errors in stderr" && check_stderr
44
+
45
+ t_begin "ensure we hit 3 separate fibers" && {
46
+ test x3 = x"$(sort < $curl_out | uniq | wc -l)"
47
+ }
48
+
49
+ t_done
@@ -0,0 +1,45 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ case $model in
4
+ EventMachine) ;;
5
+ *)
6
+ t_info "skipping $T since it's not compatible with $model"
7
+ exit 0
8
+ ;;
9
+ esac
10
+
11
+ t_plan 5 "basic test for app.deferred? usage"
12
+
13
+ CONFIG_RU=app_deferred.ru
14
+
15
+ t_begin "setup and start" && {
16
+ rainbows_setup
17
+ rtmpfiles deferred_err deferred_out sync_err sync_out
18
+ rainbows -D -c $unicorn_config $CONFIG_RU
19
+ rainbows_wait_start
20
+ }
21
+
22
+ t_begin "synchronous requests run in the same thread" && {
23
+ curl --no-buffer -sSf http://$listen/ >> $sync_out 2>> $sync_err &
24
+ curl --no-buffer -sSf http://$listen/ >> $sync_out 2>> $sync_err &
25
+ curl --no-buffer -sSf http://$listen/ >> $sync_out 2>> $sync_err &
26
+ wait
27
+ test ! -s $sync_err
28
+ test 3 -eq "$(wc -l < $sync_out)"
29
+ test 1 -eq "$(uniq < $sync_out | wc -l)"
30
+ }
31
+
32
+ t_begin "deferred requests run in a different thread" && {
33
+ curl -sSf http://$listen/deferred >> $deferred_out 2>> $deferred_err
34
+ test ! -s $deferred_err
35
+ sync_thread="$(uniq < $sync_out)"
36
+ test x"$(uniq < $deferred_out)" != x"$sync_thread"
37
+ }
38
+
39
+ t_begin "termination signal sent" && {
40
+ kill $rainbows_pid
41
+ }
42
+
43
+ t_begin "no errors in stderr" && check_stderr
44
+
45
+ t_done
data/t/test-lib.sh CHANGED
@@ -113,6 +113,7 @@ EOF
113
113
  # boxes and sometimes sleep 1s in tests
114
114
  kato=5
115
115
  echo 'Rainbows! do'
116
+ echo " client_max_body_size nil"
116
117
  if test $# -ge 1
117
118
  then
118
119
  echo " use :$1"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rainbows
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.91.1
4
+ version: 0.92.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rainbows! hackers
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-04-19 00:00:00 +00:00
12
+ date: 2010-05-04 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -18,12 +18,15 @@ dependencies:
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
20
20
  requirements:
21
- - - ~>
21
+ - - ">="
22
22
  - !ruby/object:Gem::Version
23
23
  version: 0.97.1
24
+ - - <
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0
24
27
  version:
25
28
  description: |-
26
- Rainbows! is an HTTP server for sleepy Rack applications. It is based on
29
+ \Rainbows! is an HTTP server for sleepy Rack applications. It is based on
27
30
  Unicorn, but designed to handle applications that expect long
28
31
  request/response times and/or slow clients. For Rack applications not
29
32
  heavily bound by slow external network dependencies, consider Unicorn
@@ -46,7 +49,6 @@ extra_rdoc_files:
46
49
  - lib/rainbows/error.rb
47
50
  - lib/rainbows/ev_core.rb
48
51
  - lib/rainbows/event_machine.rb
49
- - lib/rainbows/event_machine_defer.rb
50
52
  - lib/rainbows/fiber.rb
51
53
  - lib/rainbows/fiber/base.rb
52
54
  - lib/rainbows/fiber/io.rb
@@ -56,6 +58,7 @@ extra_rdoc_files:
56
58
  - lib/rainbows/fiber_spawn.rb
57
59
  - lib/rainbows/http_response.rb
58
60
  - lib/rainbows/http_server.rb
61
+ - lib/rainbows/max_body.rb
59
62
  - lib/rainbows/never_block.rb
60
63
  - lib/rainbows/never_block/event_machine.rb
61
64
  - lib/rainbows/rev.rb
@@ -69,7 +72,7 @@ extra_rdoc_files:
69
72
  - lib/rainbows/rev_thread_pool.rb
70
73
  - lib/rainbows/rev_thread_spawn.rb
71
74
  - lib/rainbows/revactor.rb
72
- - lib/rainbows/revactor/tee_input.rb
75
+ - lib/rainbows/tee_input.rb
73
76
  - lib/rainbows/thread_pool.rb
74
77
  - lib/rainbows/thread_spawn.rb
75
78
  - LICENSE
@@ -105,6 +108,8 @@ files:
105
108
  - TODO
106
109
  - TUNING
107
110
  - bin/rainbows
111
+ - config/.gitignore
112
+ - config/isolate.rb
108
113
  - lib/rainbows.rb
109
114
  - lib/rainbows/actor_spawn.rb
110
115
  - lib/rainbows/app_pool.rb
@@ -114,7 +119,6 @@ files:
114
119
  - lib/rainbows/error.rb
115
120
  - lib/rainbows/ev_core.rb
116
121
  - lib/rainbows/event_machine.rb
117
- - lib/rainbows/event_machine_defer.rb
118
122
  - lib/rainbows/fiber.rb
119
123
  - lib/rainbows/fiber/base.rb
120
124
  - lib/rainbows/fiber/io.rb
@@ -124,6 +128,7 @@ files:
124
128
  - lib/rainbows/fiber_spawn.rb
125
129
  - lib/rainbows/http_response.rb
126
130
  - lib/rainbows/http_server.rb
131
+ - lib/rainbows/max_body.rb
127
132
  - lib/rainbows/never_block.rb
128
133
  - lib/rainbows/never_block/event_machine.rb
129
134
  - lib/rainbows/rev.rb
@@ -137,7 +142,7 @@ files:
137
142
  - lib/rainbows/rev_thread_pool.rb
138
143
  - lib/rainbows/rev_thread_spawn.rb
139
144
  - lib/rainbows/revactor.rb
140
- - lib/rainbows/revactor/tee_input.rb
145
+ - lib/rainbows/tee_input.rb
141
146
  - lib/rainbows/thread_pool.rb
142
147
  - lib/rainbows/thread_spawn.rb
143
148
  - local.mk.sample
@@ -147,6 +152,7 @@ files:
147
152
  - t/.gitignore
148
153
  - t/GNUmakefile
149
154
  - t/README
155
+ - t/app_deferred.ru
150
156
  - t/async-response-no-autochunk.ru
151
157
  - t/async-response.ru
152
158
  - t/async_examples/README
@@ -166,11 +172,11 @@ files:
166
172
  - t/heartbeat-timeout.ru
167
173
  - t/large-file-response.ru
168
174
  - t/my-tap-lib.sh
175
+ - t/rack-fiber_pool/app.ru
169
176
  - t/sha1-random-size.ru
170
177
  - t/sha1.ru
171
178
  - t/simple-http_Base.ru
172
179
  - t/simple-http_EventMachine.ru
173
- - t/simple-http_EventMachineDefer.ru
174
180
  - t/simple-http_FiberPool.ru
175
181
  - t/simple-http_FiberSpawn.ru
176
182
  - t/simple-http_NeverBlock.ru
@@ -200,15 +206,21 @@ files:
200
206
  - t/t0012-spurious-wakeups-quiet.sh
201
207
  - t/t0013-reload-bad-config.sh
202
208
  - t/t0014-config-conflict.sh
203
- - t/t0100-rack-input-hammer.sh
209
+ - t/t0100-rack-input-hammer-chunked.sh
210
+ - t/t0100-rack-input-hammer-content-length.sh
204
211
  - t/t0101-rack-input-trailer.sh
205
212
  - t/t0102-rack-input-short.sh
213
+ - t/t0103-rack-input-limit.sh
214
+ - t/t0104-rack-input-limit-tiny.sh
215
+ - t/t0105-rack-input-limit-bigger.sh
206
216
  - t/t0200-async-response.sh
207
217
  - t/t0201-async-response-no-autochunk.sh
208
218
  - t/t0300-async_sinatra.sh
209
219
  - t/t0400-em-async-app.sh
210
220
  - t/t0401-em-async-tailer.sh
211
221
  - t/t0500-cramp-streaming.sh
222
+ - t/t0600-rack-fiber_pool.sh
223
+ - t/t0700-app-deferred.sh
212
224
  - t/t9000-rack-app-pool.sh
213
225
  - t/t9000.ru
214
226
  - t/test-lib.sh
@@ -1,59 +0,0 @@
1
- # -*- encoding: binary -*-
2
- # :stopdoc:
3
- # FIXME: fails many tests, experimental
4
- require 'rainbows/event_machine'
5
-
6
- module Rainbows
7
-
8
- # This is currently highly experimental
9
- module EventMachineDefer
10
- include Rainbows::EventMachine
11
-
12
- class Client < Rainbows::EventMachine::Client
13
- undef_method :app_call
14
-
15
- def defer_op
16
- @env[RACK_INPUT] = @input
17
- @env[REMOTE_ADDR] = @remote_addr
18
- @env[ASYNC_CALLBACK] = method(:response_write)
19
- catch(:async) { APP.call(@env.update(RACK_DEFAULTS)) }
20
- rescue => e
21
- handle_error(e)
22
- nil
23
- end
24
-
25
- def defer_callback(response)
26
- # too tricky to support pipelining with :async since the
27
- # second (pipelined) request could be a stuck behind a
28
- # long-running async response
29
- (response.nil? || -1 == response.first) and return @state = :close
30
-
31
- resume
32
-
33
- alive = @hp.keepalive? && G.alive
34
- out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers?
35
- response_write(response, out, alive)
36
- if alive
37
- @env.clear
38
- @hp.reset
39
- @state = :headers
40
- if @hp.headers(@env, @buf)
41
- EM.next_tick(method(:app_call))
42
- else
43
- set_comm_inactivity_timeout(G.kato)
44
- end
45
- else
46
- quit
47
- end
48
- end
49
-
50
- def app_call
51
- pause
52
- set_comm_inactivity_timeout(0)
53
- # defer_callback(defer_op)
54
- EM.defer(method(:defer_op), method(:defer_callback))
55
- end
56
- end
57
-
58
- end
59
- end
@@ -1,52 +0,0 @@
1
- # -*- encoding: binary -*-
2
- require 'rainbows/revactor'
3
-
4
- module Rainbows
5
- module Revactor
6
-
7
- # acts like tee(1) on an input input to provide a input-like stream
8
- # while providing rewindable semantics through a File/StringIO
9
- # backing store. On the first pass, the input is only read on demand
10
- # so your Rack application can use input notification (upload progress
11
- # and like). This should fully conform to the Rack::InputWrapper
12
- # specification on the public API. This class is intended to be a
13
- # strict interpretation of Rack::InputWrapper functionality and will
14
- # not support any deviations from it.
15
- class TeeInput < ::Unicorn::TeeInput
16
-
17
- private
18
-
19
- # tees off a +length+ chunk of data from the input into the IO
20
- # backing store as well as returning it. +dst+ must be specified.
21
- # returns nil if reading from the input returns nil
22
- def tee(length, dst)
23
- unless parser.body_eof?
24
- if parser.filter_body(dst, buf << socket.read).nil?
25
- tmp.write(dst)
26
- diff = dst.size - length
27
- if diff > 0
28
- dst.replace(dst[0,length])
29
- tmp.seek(-diff, IO::SEEK_CUR)
30
- end
31
- return dst
32
- end
33
- end
34
- finalize_input
35
- rescue => e
36
- client_error(e)
37
- end
38
-
39
- def finalize_input
40
- while parser.trailers(req, buf).nil?
41
- # Don't worry about raising ClientShutdown here on EOFError, tee()
42
- # will catch EOFError when app is processing it, otherwise in
43
- # initialize we never get any chance to enter the app so the
44
- # EOFError will just get trapped by Unicorn and not the Rack app
45
- buf << socket.read
46
- end
47
- self.socket = nil
48
- end
49
-
50
- end
51
- end
52
- end
@@ -1,11 +0,0 @@
1
- use Rack::ContentLength
2
- use Rack::ContentType
3
- run lambda { |env|
4
- if env['rack.multithread'] == true &&
5
- EM.reactor_running? &&
6
- env['rainbows.model'] == :EventMachineDefer
7
- [ 200, {}, [ env.inspect << "\n" ] ]
8
- else
9
- raise "incorrect parameters"
10
- end
11
- }