rainbows 0.91.1 → 0.92.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 (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
- }