rainbows 0.6.0 → 0.7.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 (55) hide show
  1. data/.document +1 -0
  2. data/Documentation/GNUmakefile +4 -1
  3. data/Documentation/comparison.css +6 -0
  4. data/Documentation/comparison.haml +297 -0
  5. data/GIT-VERSION-GEN +1 -1
  6. data/GNUmakefile +24 -17
  7. data/README +32 -28
  8. data/Summary +7 -0
  9. data/TODO +4 -6
  10. data/bin/rainbows +2 -2
  11. data/lib/rainbows.rb +33 -3
  12. data/lib/rainbows/actor_spawn.rb +29 -0
  13. data/lib/rainbows/app_pool.rb +17 -6
  14. data/lib/rainbows/base.rb +10 -13
  15. data/lib/rainbows/const.rb +1 -1
  16. data/lib/rainbows/dev_fd_response.rb +6 -0
  17. data/lib/rainbows/error.rb +34 -0
  18. data/lib/rainbows/ev_core.rb +3 -12
  19. data/lib/rainbows/event_machine.rb +7 -9
  20. data/lib/rainbows/fiber.rb +15 -0
  21. data/lib/rainbows/fiber/base.rb +112 -0
  22. data/lib/rainbows/fiber/io.rb +65 -0
  23. data/lib/rainbows/fiber/queue.rb +35 -0
  24. data/lib/rainbows/fiber_pool.rb +44 -0
  25. data/lib/rainbows/fiber_spawn.rb +34 -0
  26. data/lib/rainbows/http_server.rb +14 -1
  27. data/lib/rainbows/never_block.rb +69 -0
  28. data/lib/rainbows/rev.rb +7 -0
  29. data/lib/rainbows/rev/client.rb +9 -3
  30. data/lib/rainbows/rev/core.rb +2 -5
  31. data/lib/rainbows/rev/heartbeat.rb +5 -1
  32. data/lib/rainbows/rev_thread_spawn.rb +62 -60
  33. data/lib/rainbows/revactor.rb +22 -23
  34. data/lib/rainbows/thread_pool.rb +28 -26
  35. data/lib/rainbows/thread_spawn.rb +33 -33
  36. data/local.mk.sample +9 -7
  37. data/rainbows.gemspec +8 -2
  38. data/t/GNUmakefile +14 -7
  39. data/t/fork-sleep.ru +10 -0
  40. data/t/simple-http_FiberPool.ru +9 -0
  41. data/t/simple-http_FiberSpawn.ru +9 -0
  42. data/t/simple-http_NeverBlock.ru +11 -0
  43. data/t/sleep.ru +2 -0
  44. data/t/t0000-simple-http.sh +12 -1
  45. data/t/t0001-unix-http.sh +12 -1
  46. data/t/t0009-broken-app.sh +56 -0
  47. data/t/t0009.ru +13 -0
  48. data/t/t0010-keepalive-timeout-effective.sh +42 -0
  49. data/t/t0011-close-on-exec-set.sh +54 -0
  50. data/t/t0300-async_sinatra.sh +1 -1
  51. data/t/t9000-rack-app-pool.sh +1 -1
  52. data/t/t9000.ru +8 -5
  53. data/t/test-lib.sh +14 -4
  54. metadata +33 -5
  55. data/lib/rainbows/ev_thread_core.rb +0 -80
data/.document CHANGED
@@ -10,3 +10,4 @@ SIGNALS
10
10
  TODO
11
11
  TUNING
12
12
  vs_Unicorn
13
+ Summary
@@ -26,5 +26,8 @@ install-man: man
26
26
  %.1.html: %.1.txt
27
27
  $(pandoc_html) < $< > $@+ && mv $@+ $@
28
28
 
29
+ comparison.html: comparison.haml
30
+ haml -t ugly < $< > $@+ && mv $@+ $@
31
+
29
32
  clean::
30
- $(RM) $(man1) $(html1)
33
+ $(RM) $(man1) $(html1) comparison.html
@@ -0,0 +1,6 @@
1
+ /* help to make this look nice would be greatly appreciated */
2
+ .comparison {
3
+ margin: 1em;
4
+ border: 1px solid;
5
+ width: 100%;
6
+ }
@@ -0,0 +1,297 @@
1
+ %h2 core features and compatibility
2
+ %br
3
+ %table.comp
4
+ %tr.comp_header
5
+ %th.mod module
6
+ %th.tee rack.input streaming
7
+ %th.r18 Ruby 1.8
8
+ %th.r19 Ruby 1.9
9
+ %th.rbx Rubinius
10
+ %th.slow slow clients
11
+ %tr.comp_base
12
+ %td.mod Unicorn/Base
13
+ %td.tee Yes
14
+ %td.r18 Yes
15
+ %td.r19 Yes
16
+ %td.rbx Yes
17
+ %td.slow No
18
+ %tr.comp_row
19
+ %td.mod Revactor
20
+ %td.tee Yes
21
+ %td.r18 No
22
+ %td.r19 Yes
23
+ %td.rbx No
24
+ %td.slow Yes
25
+ %tr.comp_row
26
+ %td.mod ThreadPool
27
+ %td.tee Yes
28
+ %td.r18 Yes
29
+ %td.r19 Yes
30
+ %td.rbx Yes
31
+ %td.slow OK
32
+ %tr.comp_row
33
+ %td.mod Rev
34
+ %td.tee No
35
+ %td.r18 Yes
36
+ %td.r19 Yes
37
+ %td.rbx No
38
+ %td.slow Yes
39
+ %tr.comp_row
40
+ %td.mod ThreadSpawn
41
+ %td.tee Yes
42
+ %td.r18 Yes
43
+ %td.r19 Yes
44
+ %td.rbx Yes
45
+ %td.slow OK
46
+ %tr.comp_row
47
+ %td.mod EventMachine
48
+ %td.tee No
49
+ %td.r18 Yes
50
+ %td.r19 Yes
51
+ %td.rbx No
52
+ %td.slow Yes
53
+ %tr.comp_row
54
+ %td.mod RevThreadSpawn
55
+ %td.tee No
56
+ %td.r18 Slow*
57
+ %td.r19 Yes
58
+ %td.rbx No
59
+ %td.slow Yes
60
+ %tr.comp_row
61
+ %td.mod FiberSpawn
62
+ %td.tee Yes
63
+ %td.r18 No
64
+ %td.r19 Yes
65
+ %td.rbx No
66
+ %td.slow Yes
67
+ %tr.comp_row
68
+ %td.mod FiberPool
69
+ %td.tee Yes
70
+ %td.r18 No
71
+ %td.r19 Yes
72
+ %td.rbx No
73
+ %td.slow Yes
74
+ %tr.comp_base
75
+ %td.mod ActorSpawn
76
+ %td.tee Yes
77
+ %td.r18 Not yet
78
+ %td.r19 No
79
+ %td.rbx Yes
80
+ %td.slow Yes
81
+ %tr.comp_base
82
+ %td.mod NeverBlock
83
+ %td.tee No
84
+ %td.r18 Yes
85
+ %td.r19 Yes
86
+ %td.rbx No
87
+ %td.slow Yes
88
+ %ul
89
+ %li
90
+ RevThreadSpawn + 1.8 performance is being improved, follow
91
+ the
92
+ %a(href="http://rubyforge.org/mailman/listinfo/rev-talk")
93
+ rev-talk mailing list
94
+ for details.
95
+ %li
96
+ waiting on Rubinius for better signal handling
97
+ %li
98
+ rack.input streaming is what makes
99
+ %a(href="http://upr.bogomips.org/") upload progress,
100
+ BOSH, and Web Sockets possible
101
+ %li
102
+ rack.input streaming is NOT compatible with current versions of nginx
103
+ or any proxy that fully buffers request bodies before proxying.
104
+ Keep in mind request body buffering in nginx is a good thing in all
105
+ other cases where rack.input streaming is not needed.
106
+
107
+ %h2 application requirements
108
+ %br
109
+ %table.comp
110
+ %tr.comp_header
111
+ %th.mod module
112
+ %th.slowio slow I/O (backend, not client)
113
+ %th.thr thread safety
114
+ %th.reent single thread reentrant
115
+ %tr.comp_base
116
+ %td.mod Unicorn/Base
117
+ %td.slowio avoid
118
+ %td.thr No
119
+ %td.reent No
120
+ %tr.comp_row
121
+ %td.mod Revactor
122
+ %td.slowio
123
+ %a(href="http://rev.rubyforge.org/")Rev,
124
+ %a(href="http://revactor.org/")Revactor,
125
+ %b
126
+ not
127
+ %a(href="Rainbows/Fiber/IO.html")Fiber::IO
128
+ %td.thr No
129
+ %td.reent Yes
130
+ %tr.comp_row
131
+ %td.mod ThreadPool
132
+ %td.slowio thread-safe Ruby
133
+ %td.thr Yes
134
+ %td.reent No
135
+ %tr.comp_row
136
+ %td.mod Rev
137
+ %td.slowio
138
+ %a(href="http://rev.rubyforge.org/") Rev
139
+ %td.thr No
140
+ %td.reent No
141
+ %tr.comp_row
142
+ %td.mod ThreadSpawn
143
+ %td.slowio thread-safe Ruby
144
+ %td.thr Yes
145
+ %td.reent No
146
+ %tr.comp_row
147
+ %td.mod EventMachine
148
+ %td.slowio
149
+ %a(href="http://rubyeventmachine.com") EventMachine
150
+ %td.thr No
151
+ %td.reent No
152
+ %tr.comp_row
153
+ %td.mod RevThreadSpawn
154
+ %td.slowio
155
+ thread-safe Ruby,
156
+ %a(href="http://rev.rubyforge.org/") Rev
157
+ %td.thr Yes
158
+ %td.reent No
159
+ %tr.comp_row
160
+ %td.mod FiberSpawn
161
+ %td.slowio
162
+ %a(href="Rainbows/Fiber/IO.html") Rainbows::Fiber::IO
163
+ %td.thr No
164
+ %td.reent Yes
165
+ %tr.comp_row
166
+ %td.mod FiberPool
167
+ %td.slowio
168
+ %a(href="Rainbows/Fiber/IO.html") Rainbows::Fiber::IO
169
+ %td.thr No
170
+ %td.reent Yes
171
+ %tr.comp_base
172
+ %td.mod ActorSpawn
173
+ %td.slowio thread-safe Ruby
174
+ %td.thr Yes
175
+ %td.reent Yes
176
+ %tr.comp_base
177
+ %td.mod NeverBlock
178
+ %td.slowio
179
+ %a(href="http://www.espace.com.eg/neverblock") NeverBlock,
180
+ %a(href="http://rubyeventmachine.com") EventMachine
181
+ %td.thr No
182
+ %td.reent Yes
183
+
184
+ %ul
185
+ %li
186
+ Requirements for single thread reentrancy are loose in that there is
187
+ no risk of race conditions and potentially mutually exclusive to
188
+ thread-safety. In the case where a Fiber yields while holding a
189
+ resource and another Fiber attempting to acquire it may raise
190
+ an error or worse, deadlock the entire process.
191
+ %li
192
+ Slow I/O means anything that can block/stall on sockets including
193
+ 3rd-party APIs (OpenID providers included) or slow database queries.
194
+ Properly run Memcached (within the same LAN) is fast and not a blocker.
195
+ Slow I/O on POSIX filesystems only includes a few operations, namely
196
+ on UNIX domain sockets and named pipes. Nearly all other operations
197
+ on POSIX filesystems can be considered "fast", or at least
198
+ uninterruptible.
199
+
200
+ %h2 middlewares and frameworks
201
+ %br
202
+
203
+ %table.comp
204
+ %tr.comp_header
205
+ %th.mod model
206
+ %th.devfd
207
+ %a(href="Rainbows/DevFdResponse.html") DevFdResponse
208
+ %th.app_pool
209
+ %a(href="Rainbows/AppPool.html") AppPool
210
+ %th.lock
211
+ %a(href="http://rack.rubyforge.org/doc/Rack/Lock.html") Rack::Lock
212
+ %th.async async
213
+ %tr.comp_row
214
+ %td.mod Unicorn/Base
215
+ %td.devfd no-op
216
+ %td.app_pool no-op
217
+ %td.lock no-op
218
+ %td.async lots of RAM :P
219
+ %tr.comp_row
220
+ %td.mod Revactor
221
+ %td.devfd no-op
222
+ %td.app_pool Yes
223
+ %td.lock No!
224
+ %td.async Revactor itself
225
+ %tr.comp_row
226
+ %td.mod ThreadPool
227
+ %td.devfd no-op
228
+ %td.app_pool Yes
229
+ %td.lock Yes
230
+ %td.async standard Ruby
231
+ %tr.comp_row
232
+ %td.mod Rev
233
+ %td.devfd Yes
234
+ %td.app_pool no-op
235
+ %td.lock no-op
236
+ %td.async DevFdResponse
237
+ %tr.comp_row
238
+ %td.mod ThreadSpawn
239
+ %td.devfd no-op
240
+ %td.app_pool Yes
241
+ %td.lock Yes
242
+ %td.async standard Ruby
243
+ %tr.comp_row
244
+ %td.mod EventMachine
245
+ %td.devfd Yes
246
+ %td.app_pool no-op
247
+ %td.lock no-op
248
+ %td.async async_sinatra
249
+ %tr.comp_row
250
+ %td.mod RevThreadSpawn
251
+ %td.devfd Yes
252
+ %td.app_pool Yes
253
+ %td.lock Dumb
254
+ %td.async standard Ruby
255
+ %tr.comp_row
256
+ %td.mod FiberSpawn
257
+ %td.devfd Yes
258
+ %td.app_pool Yes
259
+ %td.lock No!
260
+ %td.async Rainbows::Fiber{::IO,.sleep}
261
+ %tr.comp_row
262
+ %td.mod FiberPool
263
+ %td.devfd Yes
264
+ %td.app_pool Yes
265
+ %td.lock No!
266
+ %td.async Rainbows::Fiber{::IO,.sleep}
267
+ %tr.comp_row
268
+ %td.mod ActorSpawn
269
+ %td.devfd no-op
270
+ %td.app_pool Yes
271
+ %td.lock Yes
272
+ %td.async standard Ruby
273
+ %tr.comp_row
274
+ %td.mod NeverBlock
275
+ %td.devfd Yes
276
+ %td.app_pool Yes*
277
+ %td.lock Yes*
278
+ %td.async NeverBlock, async_sinatra
279
+
280
+ %ul
281
+ %li
282
+ "No!" means it's fundamentally incompatible, use an
283
+ %a(href="Rainbows/AppPool.html") AppPool
284
+ %b :size
285
+ of one instead.
286
+ %li
287
+ NeverBlock also supports a :pool_size option which is one less
288
+ layer of complexity than using AppPool.
289
+ %li
290
+ NeverBlock can neuter the Mutex class so Rack::Lock effectively
291
+ becomes a no-op with:
292
+ %br
293
+ %code require "never_block/frameworks/rails"
294
+ (before Rails is loaded)
295
+ %li
296
+ Everything that's DevFdResponse-compatible can use it for passing
297
+ async responses through
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.6.0.GIT
4
+ DEF_VER=v0.7.0.GIT
5
5
 
6
6
  LF='
7
7
  '
data/GNUmakefile CHANGED
@@ -1,19 +1,13 @@
1
- # use GNU Make to run tests in parallel, and without depending on Rubygems
1
+ # use GNU Make to run tests in parallel, and without depending on RubyGems
2
2
  all::
3
3
  RUBY = ruby
4
- rake = rake
4
+ RAKE = rake
5
5
  GIT_URL = git://git.bogomips.org/rainbows.git
6
6
 
7
7
  GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
8
8
  @./GIT-VERSION-GEN
9
9
  -include GIT-VERSION-FILE
10
10
  -include local.mk
11
- ifdef ruby
12
- ifeq ($(RUBY),ruby)
13
- $(warning ruby variable is deprecated, use RUBY instead)
14
- RUBY = $(ruby)
15
- endif
16
- endif
17
11
  ifeq ($(DLEXT),) # "so" for Linux
18
12
  DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts Config::CONFIG["DLEXT"]')
19
13
  endif
@@ -61,13 +55,16 @@ manifest: $(pkg_extra) man
61
55
  $(RM) $@+
62
56
 
63
57
  NEWS: GIT-VERSION-FILE
64
- $(rake) -s news_rdoc > $@+
58
+ $(RAKE) -s news_rdoc > $@+
65
59
  mv $@+ $@
66
60
 
67
- SINCE = 0.5.0
68
- ChangeLog: log_range = $(shell test -n "$(SINCE)" && echo v$(SINCE)..)
61
+ SINCE = 0.6.0
62
+ ChangeLog: LOG_VERSION = \
63
+ $(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
64
+ echo $(GIT_VERSION) || git describe)
65
+ ChangeLog: log_range = v$(SINCE)..$(LOG_VERSION)
69
66
  ChangeLog: GIT-VERSION-FILE
70
- @echo "ChangeLog from $(GIT_URL) ($(SINCE)..$(GIT_VERSION))" > $@+
67
+ @echo "ChangeLog from $(GIT_URL) ($(log_range))" > $@+
71
68
  @echo >> $@+
72
69
  git log $(log_range) | sed -e 's/^/ /' >> $@+
73
70
  mv $@+ $@
@@ -80,6 +77,7 @@ atom = <link rel="alternate" title="Atom feed" href="$(1)" \
80
77
  # using rdoc 2.4.1+
81
78
  doc: .document NEWS ChangeLog
82
79
  for i in $(man1_bins); do > $$i; done
80
+ find bin lib -type f -name '*.rbc' -exec rm -f '{}' ';'
83
81
  rdoc -Na -t "$(shell sed -ne '1s/^= //p' README)"
84
82
  install -m644 COPYING doc/COPYING
85
83
  install -m644 $(shell grep '^[A-Z]' .document) doc/
@@ -94,8 +92,13 @@ doc: .document NEWS ChangeLog
94
92
  $(RUBY) -i -p -e \
95
93
  '$$_.gsub!("</title>",%q{\&$(call atom,$(news_atom))})' \
96
94
  doc/NEWS.html doc/README.html
97
- $(rake) -s news_atom > doc/NEWS.atom.xml
95
+ $(RAKE) -s news_atom > doc/NEWS.atom.xml
98
96
  cd doc && ln README.html tmp && mv tmp index.html
97
+ $(MAKE) -C Documentation comparison.html
98
+ $(RUBY) -i -p -e \
99
+ '$$_.gsub!(/INCLUDE/){File.read("Documentation/comparison.html")}' \
100
+ doc/Summary.html
101
+ cat Documentation/comparison.css >> doc/rdoc.css
99
102
  $(RM) $(man1_bins)
100
103
 
101
104
  ifneq ($(VERSION),)
@@ -109,10 +112,10 @@ release_changes := release_changes-$(VERSION)
109
112
  release-notes: $(release_notes)
110
113
  release-changes: $(release_changes)
111
114
  $(release_changes):
112
- $(rake) -s release_changes > $@+
115
+ $(RAKE) -s release_changes > $@+
113
116
  $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
114
117
  $(release_notes):
115
- GIT_URL=$(GIT_URL) $(rake) -s release_notes > $@+
118
+ GIT_URL=$(GIT_URL) $(RAKE) -s release_notes > $@+
116
119
  $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
117
120
 
118
121
  # ensures we're actually on the tagged $(VERSION), only used for release
@@ -150,10 +153,14 @@ $(pkgtgz): manifest fix-perms
150
153
  package: $(pkgtgz) $(pkggem)
151
154
 
152
155
  release: verify package $(release_notes) $(release_changes)
156
+ # make tgz release on RubyForge
153
157
  rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
154
158
  $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
155
- rubyforge add_file \
156
- $(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
159
+ # push gem to Gemcutter
160
+ gem push $(pkggem)
161
+ # in case of gem downloads from RubyForge releases page
162
+ -rubyforge add_file \
163
+ $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
157
164
  else
158
165
  gem install-gem: GIT-VERSION-FILE
159
166
  $(MAKE) $@ VERSION=$(GIT_VERSION)
data/README CHANGED
@@ -1,6 +1,6 @@
1
1
  = Rainbows! Unicorn for sleepy apps and slow clients
2
2
 
3
- Rainbows! is a HTTP server for sleepy Rack applications. It is based on
3
+ Rainbows! is an HTTP server for sleepy Rack applications. It is based on
4
4
  Unicorn, but designed to handle applications that expect long
5
5
  request/response times and/or slow clients. For Rack applications not
6
6
  heavily bound by slow external network dependencies, consider Unicorn
@@ -13,24 +13,23 @@ suck; differently.
13
13
 
14
14
  For network concurrency, models we currently support are:
15
15
 
16
- * {:Revactor}[link:Rainbows/Revactor.html]
17
- * {:ThreadPool}[link:Rainbows/ThreadPool.html]
18
- * {:Rev}[link:Rainbows/Rev.html]*
19
- * {:ThreadSpawn}[link:Rainbows/ThreadSpawn.html]
20
- * {:EventMachine}[link:Rainbows/EventMachine.html]
16
+ * {Revactor}[link:Rainbows/Revactor.html]
17
+ * {ThreadPool}[link:Rainbows/ThreadPool.html]
18
+ * {Rev}[link:Rainbows/Rev.html]
19
+ * {ThreadSpawn}[link:Rainbows/ThreadSpawn.html]
20
+ * {EventMachine}[link:Rainbows/EventMachine.html]
21
+ * {RevThreadSpawn}[link:Rainbows/RevThreadSpawn.html]
22
+ * {FiberSpawn}[link:Rainbows/FiberSpawn.html]
23
+ * {FiberPool}[link:Rainbows/FiberPool.html]
24
+ * {NeverBlock}[link:Rainbows/NeverBlock.html]
21
25
 
22
- We have {more on the way}[link:TODO.html] for handling network concurrency.
23
- Additionally, we also use multiple processes (managed by Unicorn) for
24
- CPU/memory/disk concurrency.
26
+ We have {many more on the way}[link:TODO.html] for handling network
27
+ concurrency. Additionally, we also use multiple processes (managed by
28
+ Unicorn) for robustness and CPU/memory/disk concurrency.
25
29
 
26
- \* our \Rev concurrency model is only recommended for slow clients, not
27
- sleepy apps. Additionally it does not support streaming "rack.input" to
28
- the application.
29
-
30
- For application concurrency, we have the Rainbows::AppPool Rack
31
- middleware that allows us to limit application concurrency independently
32
- of network concurrency. Rack::Lock as distributed by Rack may also be
33
- used to limit application concurrency to one (per-worker).
30
+ We also provide Rainbows::AppPool Rack middleware for some network
31
+ concurrency models for limiting application concurrency independently of
32
+ network concurrency.
34
33
 
35
34
  == Features
36
35
 
@@ -38,8 +37,8 @@ used to limit application concurrency to one (per-worker).
38
37
  modern Ruby HTTP applications.
39
38
 
40
39
  * Built on {Unicorn}[http://unicorn.bogomips.org/], inheriting its
41
- process/socket management features
42
- such as transparent upgrades and Ruby configuration DSL.
40
+ process/socket management features such as transparent upgrades and
41
+ Ruby configuration DSL.
43
42
 
44
43
  * As with Unicorn, it is able to stream large request bodies off the
45
44
  socket to the application while the client is still uploading. Since
@@ -47,13 +46,16 @@ used to limit application concurrency to one (per-worker).
47
46
  it is with Unicorn.
48
47
 
49
48
  * Combines heavyweight concurrency (worker processes) with lightweight
50
- concurrency (Actors or Threads), allowing CPU/memory/disk to be scaled
51
- independently of client connections. Alternative concurrency models
49
+ concurrency (Events/Fibers/Actors/Threads), allowing CPU/memory/disk to
50
+ be scaled independently of client connections. More concurrency models
52
51
  (listed in the TODO) will be supported as we find time for them.
53
52
 
53
+ * We give you {lots of options}[link:Summary.html] with more
54
+ {on the way}[link:TODO.html].
55
+
54
56
  == Applications
55
57
 
56
- \Rainbows is for the odd things Unicorn sucks at:
58
+ \Rainbows is mainly designed for the odd things Unicorn sucks at:
57
59
 
58
60
  * 3rd-party APIs (to services outside your control/LAN)
59
61
  * OpenID consumers (to providers outside your control/LAN)
@@ -63,10 +65,12 @@ used to limit application concurrency to one (per-worker).
63
65
  * BOSH (with slow clients)
64
66
  * HTTP server push
65
67
  * Long polling
66
- * Reverse Ajax
68
+ * Reverse AJAX
69
+ * HTML 5 Web Sockets
70
+ * real-time upload processing
67
71
 
68
- \Rainbows may also be used to service slow clients even with fast
69
- applications using the \Rev concurrency model.
72
+ \Rainbows can also be used to service slow clients directly even with
73
+ fast applications.
70
74
 
71
75
  == License
72
76
 
@@ -86,7 +90,7 @@ and run setup.rb after unpacking it:
86
90
 
87
91
  http://rubyforge.org/frs/?group_id=8977
88
92
 
89
- You may also install it via Rubygems on Rubyforge:
93
+ You may also install it via RubyGems on Gemcutter:
90
94
 
91
95
  gem install rainbows
92
96
 
@@ -125,13 +129,13 @@ You can get the latest source via git from the following locations
125
129
  (these versions may not be stable):
126
130
 
127
131
  git://git.bogomips.org/rainbows.git
128
- git://rubyforge.org/rainbows.git (mirror)
132
+ git://repo.or.cz/rainbows.git (mirror)
129
133
 
130
134
  You may browse the code from the web and download the latest snapshot
131
135
  tarballs here:
132
136
 
133
137
  * http://git.bogomips.org/cgit/rainbows.git (cgit)
134
- * http://rainbows.rubyforge.org/git?p=rainbows.git (gitweb)
138
+ * http://repo.or.cz/w/rainbows.git (gitweb)
135
139
 
136
140
  Inline patches (from "git format-patch") to the mailing list are
137
141
  preferred because they allow code review and comments in the reply to