rainbows 0.1.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/FAQ ADDED
@@ -0,0 +1,50 @@
1
+ = Frequently Asked Questions about \Rainbows!
2
+
3
+ === Why is \Rainbows! a separate project from Unicorn?
4
+
5
+ \Rainbows is for the odd, corner-case requests that Unicorn is poorly
6
+ suited for. More scalable concurrency models introduce additional
7
+ complexity that Unicorn users and developers are uncomfortable with for
8
+ the common cases.
9
+
10
+
11
+ === What complexity? Threads/events/actors are easy to work with!
12
+
13
+ Good for you. Some of us depend on libraries incompatible with those
14
+ models, or are just too lazy to deal with them for the majority of
15
+ requests we service.
16
+
17
+
18
+ === Isn't "rainbows" a branch of Unicorn?
19
+
20
+ That functionality is now in the Revactor model of \Rainbows!
21
+
22
+
23
+ === What happened to the "gossamer" branch of Unicorn?
24
+
25
+ It became the ThreadPool model of \Rainbows!
26
+
27
+
28
+ === Which concurrency model should I use?
29
+
30
+ It depends on your application, libraries, Ruby stack and use cases.
31
+ That's why we support as many concurrency model as we can. Each model
32
+ has their own strengths and weaknesses in terms of maturity,
33
+ ease-of-debugging, compatibility, performance, and memory usage.
34
+
35
+
36
+ === Should I put \Rainbows! behind nginx to serve slow clients?
37
+
38
+ It is optional. You can still use nginx to route certain requests to
39
+ Unicorn and others to \Rainbows! nginx will always outperform
40
+ \Rainbows! in both pure reverse proxy applications and for serving
41
+ static files, but \Rainbows! is for hosting applications that are more
42
+ easily-implemented in Ruby than C.
43
+
44
+
45
+ === Should I use \Rainbows! to serve static files?
46
+
47
+ It depends on the size and amount of static files you're serving. If
48
+ you're serving a lot of static files (especially large ones), then by
49
+ all means use nginx. If not, then \Rainbows! is likely a "good enough"
50
+ solution even if nginx will always outperform it in raw throughput.
data/GIT-VERSION-GEN ADDED
@@ -0,0 +1,41 @@
1
+ #!/bin/sh
2
+
3
+ GVF=GIT-VERSION-FILE
4
+ DEF_VER=v0.1.0
5
+ # DEF_VER=v0.1.0.GIT
6
+
7
+ LF='
8
+ '
9
+
10
+ # First see if there is a version file (included in release tarballs),
11
+ # then try git-describe, then default.
12
+ if test -f version
13
+ then
14
+ VN=$(cat version) || VN="$DEF_VER"
15
+ elif test -d .git -o -f .git &&
16
+ VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
17
+ case "$VN" in
18
+ *$LF*) (exit 1) ;;
19
+ v[0-9]*)
20
+ git update-index -q --refresh
21
+ test -z "$(git diff-index --name-only HEAD --)" ||
22
+ VN="$VN-dirty" ;;
23
+ esac
24
+ then
25
+ VN=$(echo "$VN" | sed -e 's/-/./g');
26
+ else
27
+ VN="$DEF_VER"
28
+ fi
29
+
30
+ VN=$(expr "$VN" : v*'\(.*\)')
31
+
32
+ if test -r $GVF
33
+ then
34
+ VC=$(sed -e 's/^GIT_VERSION = //' <$GVF)
35
+ else
36
+ VC=unset
37
+ fi
38
+ test "$VN" = "$VC" || {
39
+ echo >&2 "GIT_VERSION = $VN"
40
+ echo "GIT_VERSION = $VN" >$GVF
41
+ }
data/GNUmakefile ADDED
@@ -0,0 +1,156 @@
1
+ # use GNU Make to run tests in parallel, and without depending on Rubygems
2
+ all::
3
+ ruby = ruby
4
+ rake = rake
5
+ GIT_URL = git://git.bogomips.org/rainbows.git
6
+
7
+ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
8
+ @./GIT-VERSION-GEN
9
+ -include GIT-VERSION-FILE
10
+ -include local.mk
11
+ ifeq ($(DLEXT),) # "so" for Linux
12
+ DLEXT := $(shell $(ruby) -rrbconfig -e 'puts Config::CONFIG["DLEXT"]')
13
+ endif
14
+ ifeq ($(RUBY_VERSION),)
15
+ RUBY_VERSION := $(shell $(ruby) -e 'puts RUBY_VERSION')
16
+ endif
17
+
18
+ base_bins := rainbows
19
+ bins := $(addprefix bin/, $(base_bins))
20
+ man1_bins := $(addsuffix .1, $(base_bins))
21
+ man1_paths := $(addprefix man/man1/, $(man1_bins))
22
+
23
+ install: $(bins)
24
+ $(prep_setup_rb)
25
+ $(RM) -r .install-tmp
26
+ mkdir .install-tmp
27
+ cp -p bin/* .install-tmp
28
+ $(ruby) setup.rb all
29
+ $(RM) $^
30
+ mv .install-tmp/* bin/
31
+ $(RM) -r .install-tmp
32
+ $(prep_setup_rb)
33
+
34
+ setup_rb_files := .config InstalledFiles
35
+ prep_setup_rb := @-$(RM) $(setup_rb_files);$(MAKE) -C $(ext) clean
36
+
37
+ clean:
38
+ -$(MAKE) -C $(ext) clean
39
+ -$(MAKE) -C Documentation clean
40
+ $(RM) $(setup_rb_files) $(t_log)
41
+
42
+ man:
43
+ $(MAKE) -C Documentation install-man
44
+
45
+ pkg_extra := GIT-VERSION-FILE NEWS ChangeLog
46
+ manifest: $(pkg_extra) man
47
+ $(RM) .manifest
48
+ $(MAKE) .manifest
49
+
50
+ .manifest:
51
+ (git ls-files && \
52
+ for i in $@ $(pkg_extra) $(man1_paths); \
53
+ do echo $$i; done) | LC_ALL=C sort > $@+
54
+ cmp $@+ $@ || mv $@+ $@
55
+ $(RM) $@+
56
+
57
+ NEWS: GIT-VERSION-FILE
58
+ $(rake) -s news_rdoc > $@+
59
+ mv $@+ $@
60
+
61
+ SINCE =
62
+ ChangeLog: log_range = $(shell test -n "$(SINCE)" && echo v$(SINCE)..)
63
+ ChangeLog: GIT-VERSION-FILE
64
+ @echo "ChangeLog from $(GIT_URL) ($(SINCE)..$(GIT_VERSION))" > $@+
65
+ @echo >> $@+
66
+ git log $(log_range) | sed -e 's/^/ /' >> $@+
67
+ mv $@+ $@
68
+
69
+ news_atom := http://rainbows.rubyforge.org/NEWS.atom.xml
70
+ cgit_atom := http://git.bogomips.org/cgit/rainbows.git/atom/?h=master
71
+ atom = <link rel="alternate" title="Atom feed" href="$(1)" \
72
+ type="application/atom+xml"/>
73
+
74
+ # using rdoc 2.4.1+
75
+ doc: .document NEWS ChangeLog
76
+ for i in $(man1_bins); do > $$i; done
77
+ rdoc -Na -t "$(shell sed -ne '1s/^= //p' README)"
78
+ install -m644 COPYING doc/COPYING
79
+ install -m644 $(shell grep '^[A-Z]' .document) doc/
80
+ $(MAKE) -C Documentation install-html install-man
81
+ install -m644 $(man1_paths) doc/
82
+ cd doc && for i in $(base_bins); do \
83
+ sed -e '/"documentation">/r man1/'$$i'.1.html' \
84
+ < $${i}_1.html > tmp && mv tmp $${i}_1.html; done
85
+ $(ruby) -i -p -e \
86
+ '$$_.gsub!("</title>",%q{\&$(call atom,$(cgit_atom))})' \
87
+ doc/ChangeLog.html
88
+ $(ruby) -i -p -e \
89
+ '$$_.gsub!("</title>",%q{\&$(call atom,$(news_atom))})' \
90
+ doc/NEWS.html doc/README.html
91
+ $(rake) -s news_atom > doc/NEWS.atom.xml
92
+ cd doc && ln README.html tmp && mv tmp index.html
93
+ $(RM) $(man1_bins)
94
+
95
+ ifneq ($(VERSION),)
96
+ rfproject := rainbows
97
+ rfpackage := rainbows
98
+ pkggem := pkg/$(rfpackage)-$(VERSION).gem
99
+ pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
100
+ release_notes := release_notes-$(VERSION)
101
+ release_changes := release_changes-$(VERSION)
102
+
103
+ release-notes: $(release_notes)
104
+ release-changes: $(release_changes)
105
+ $(release_changes):
106
+ $(rake) -s release_changes > $@+
107
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
108
+ $(release_notes):
109
+ GIT_URL=$(GIT_URL) $(rake) -s release_notes > $@+
110
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
111
+
112
+ # ensures we're actually on the tagged $(VERSION), only used for release
113
+ verify:
114
+ test x"$(shell umask)" = x0022
115
+ git rev-parse --verify refs/tags/v$(VERSION)^{}
116
+ git diff-index --quiet HEAD^0
117
+ test `git rev-parse --verify HEAD^0` = \
118
+ `git rev-parse --verify refs/tags/v$(VERSION)^{}`
119
+
120
+ fix-perms:
121
+ -git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
122
+ -git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
123
+
124
+ gem: $(pkggem)
125
+
126
+ install-gem: $(pkggem)
127
+ gem install $(CURDIR)/$<
128
+
129
+ $(pkggem): manifest fix-perms
130
+ gem build $(rfpackage).gemspec
131
+ mkdir -p pkg
132
+ mv $(@F) $@
133
+
134
+ $(pkgtgz): distdir = $(basename $@)
135
+ $(pkgtgz): HEAD = v$(VERSION)
136
+ $(pkgtgz): manifest fix-perms
137
+ @test -n "$(distdir)"
138
+ $(RM) -r $(distdir)
139
+ mkdir -p $(distdir)
140
+ tar c `cat .manifest` | (cd $(distdir) && tar x)
141
+ cd pkg && tar c $(basename $(@F)) | gzip -9 > $(@F)+
142
+ mv $@+ $@
143
+
144
+ package: $(pkgtgz) $(pkggem)
145
+
146
+ release: verify package $(release_notes) $(release_changes)
147
+ rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
148
+ $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
149
+ rubyforge add_file \
150
+ $(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
151
+ else
152
+ gem install-gem: GIT-VERSION-FILE
153
+ $(MAKE) $@ VERSION=$(GIT_VERSION)
154
+ endif
155
+
156
+ .PHONY: .FORCE-GIT-VERSION-FILE doc manifest man
data/LICENSE ADDED
@@ -0,0 +1,55 @@
1
+ \Rainbows! is copyrighted free software by Eric Wong
2
+ (mailto:normalperson@yhbt.net) and contributors. You can redistribute it
3
+ and/or modify it under either the terms of the
4
+ {GPL2}[http://www.gnu.org/licenses/gpl-2.0.txt] (see link:COPYING) or
5
+ the conditions below:
6
+
7
+ 1. You may make and give away verbatim copies of the source form of the
8
+ software without restriction, provided that you duplicate all of the
9
+ original copyright notices and associated disclaimers.
10
+
11
+ 2. You may modify your copy of the software in any way, provided that
12
+ you do at least ONE of the following:
13
+
14
+ a) place your modifications in the Public Domain or otherwise make them
15
+ Freely Available, such as by posting said modifications to Usenet or an
16
+ equivalent medium, or by allowing the author to include your
17
+ modifications in the software.
18
+
19
+ b) use the modified software only within your corporation or
20
+ organization.
21
+
22
+ c) rename any non-standard executables so the names do not conflict with
23
+ standard executables, which must also be provided.
24
+
25
+ d) make other distribution arrangements with the author.
26
+
27
+ 3. You may distribute the software in object code or executable
28
+ form, provided that you do at least ONE of the following:
29
+
30
+ a) distribute the executables and library files of the software,
31
+ together with instructions (in the manual page or equivalent) on where
32
+ to get the original distribution.
33
+
34
+ b) accompany the distribution with the machine-readable source of the
35
+ software.
36
+
37
+ c) give non-standard executables non-standard names, with
38
+ instructions on where to get the original software distribution.
39
+
40
+ d) make other distribution arrangements with the author.
41
+
42
+ 4. You may modify and include the part of the software into any other
43
+ software (possibly commercial). But some files in the distribution
44
+ are not written by the author, so that they are not under this terms.
45
+
46
+ 5. The scripts and library files supplied as input to or produced as
47
+ output from the software do not automatically fall under the
48
+ copyright of the software, but belong to whomever generated them,
49
+ and may be sold commercially, and may be aggregated with this
50
+ software.
51
+
52
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
53
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
54
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55
+ PURPOSE.
data/README ADDED
@@ -0,0 +1,122 @@
1
+ = Rainbows! Unicorn for slow apps and slow clients
2
+
3
+ \Rainbows! is a HTTP server for {Rack}[http://rack.rubyforge.org/]
4
+ applications. It is based on {Unicorn}[http://unicorn.bogomips.org/],
5
+ but designed to handle applications that expect long request/response
6
+ times and/or slow clients. For Rack applications not heavily bound by
7
+ slow external dependencies, consider Unicorn instead as it simpler and
8
+ easier to debug.
9
+
10
+ == \Rainbows! is about Diversity
11
+
12
+ We aim to support as many concurrency models as we can because they all
13
+ suck; differently.
14
+
15
+ For network concurrency, models we currently support are:
16
+
17
+ * {:ThreadSpawn}[link:Rainbows/ThreadSpawn.html]
18
+ * {:ThreadPool}[link:Rainbows/ThreadPool.html]
19
+ * {:Revactor}[link:Rainbows/Revactor.html]
20
+
21
+ We have {more on the way}[link:TODO.html] for handling network concurrency.
22
+ Additionally, we also use multiple processes (managed by Unicorn) for
23
+ CPU/memory/disk concurrency.
24
+
25
+ == Features
26
+
27
+ * Designed for Rack, the standard for modern Ruby HTTP applications.
28
+
29
+ * Built on Unicorn, inheriting its process/socket management features
30
+ such as transparent upgrades and Ruby configuration DSL.
31
+
32
+ * As with Unicorn, it is able to stream large request bodies off the
33
+ socket to the application while the client is still uploading. Since
34
+ \Rainbows! can handle slow clients, this feature is more useful than
35
+ it is with Unicorn.
36
+
37
+ * Combines heavyweight concurrency (worker processes) with lightweight
38
+ concurrency (Actors or Threads), allowing CPU/memory/disk to be scaled
39
+ independently of client connections. Alternative concurrency models
40
+ (listed in the TODO) will be supported as we find time for them.
41
+
42
+ == Applications
43
+
44
+ \Rainbows is for the odd things Unicorn sucks at:
45
+
46
+ * 3rd-party APIs (to services outside your control/LAN)
47
+ * OpenID consumers (to providers outside your control/LAN)
48
+ * Reverse proxy implementations with editing/censoring
49
+ (to upstreams outside your control/LAN)
50
+ * Comet
51
+ * BOSH (with slow clients)
52
+ * HTTP server push
53
+ * Long polling
54
+ * Reverse Ajax
55
+
56
+ == License
57
+
58
+ \Rainbows! is copyright 2009 Eric Wong and contributors. It is based on
59
+ Mongrel and Unicorn and carries the same license.
60
+
61
+ Mongrel is copyright 2007 Zed A. Shaw and contributors. It is licensed
62
+ under the Ruby license and the GPL2. See the included LICENSE file for
63
+ details.
64
+
65
+ \Rainbows! is 100% Free Software.
66
+
67
+ == Usage
68
+
69
+ === for Rack applications
70
+
71
+ In APP_ROOT (where config.ru is located), run:
72
+
73
+ rainbows
74
+
75
+ \Rainbows! will bind to all interfaces on TCP port 8080 by default.
76
+
77
+ === Configuration File(s)
78
+
79
+ \Rainbows! will look for the config.ru file used by rackup in APP_ROOT.
80
+
81
+ For deployments, it can use a config file for Unicorn and
82
+ \Rainbows!-specific options specified by the +--config-file/-c+
83
+ command-line switch. \Rainbows! accepts all options found in
84
+ {Unicorn::Configurator}[http://unicorn.bogomips.org/Unicorn/Configurator.html]
85
+ as well as the "\Rainbows!" block, so you can have the following in your
86
+ config file:
87
+
88
+ Rainbows! do
89
+ use :Revactor
90
+ worker_connections 128
91
+ end
92
+
93
+ == Development
94
+
95
+ * git: git://git.bogomips.org/rainbows.git
96
+ * cgit: http://git.bogomips.org/cgit/rainbows.git
97
+
98
+ Inline patches (from "git format-patch") to the mailing list are
99
+ preferred because they allow code review and comments in the reply to
100
+ the patch.
101
+
102
+ We will adhere to mostly the same conventions for patch submissions as
103
+ git itself. See the Documentation/SubmittingPatches document
104
+ distributed with git on on patch submission guidelines to follow. Just
105
+ don't email the git mailing list or maintainer with \Rainbows! patches.
106
+
107
+ == Disclaimer
108
+
109
+ There is NO WARRANTY whatsoever if anything goes wrong, but let us know
110
+ and we'll try our best to fix it.
111
+
112
+ == Contact
113
+
114
+ All feedback (bug reports, user/development dicussion, patches, pull
115
+ requests) go to the mailing list/newsgroup. Patches must be sent inline
116
+ (git format-patch -M + git send-email). No subscription is necessary
117
+ to post on the mailing list. No top posting. Address replies +To:+ (or
118
+ +Cc:+) the original sender and +Cc:+ the mailing list.
119
+
120
+ * email: mailto:rainbows-talk@rubyforge.org
121
+ * archives: http://rubyforge.org/pipermail/rainbows-talk
122
+ * subscribe: http://rubyforge.org/mailman/listinfo/rainbows-talk
data/Rakefile ADDED
@@ -0,0 +1,103 @@
1
+ # -*- encoding: binary -*-
2
+
3
+ # most tasks are in the GNUmakefile which offers better parallelism
4
+
5
+ def tags
6
+ timefmt = '%Y-%m-%dT%H:%M:%SZ'
7
+ @tags ||= `git tag -l`.split(/\n/).map do |tag|
8
+ if %r{\Av[\d\.]+\z} =~ tag
9
+ header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
10
+ header = header.split(/\n/)
11
+ tagger = header.grep(/\Atagger /).first
12
+ body ||= "initial"
13
+ {
14
+ :time => Time.at(tagger.split(/ /)[-2].to_i).utc.strftime(timefmt),
15
+ :tagger_name => %r{^tagger ([^<]+)}.match(tagger)[1],
16
+ :tagger_email => %r{<([^>]+)>}.match(tagger)[1],
17
+ :id => `git rev-parse refs/tags/#{tag}`.chomp!,
18
+ :tag => tag,
19
+ :subject => subject,
20
+ :body => body,
21
+ }
22
+ end
23
+ end.compact.sort { |a,b| b[:time] <=> a[:time] }
24
+ end
25
+
26
+ cgit_url = "http://git.bogomips.org/cgit/rainbows.git"
27
+
28
+ desc 'prints news as an Atom feed'
29
+ task :news_atom do
30
+ require 'nokogiri'
31
+ new_tags = tags[0,10]
32
+ puts(Nokogiri::XML::Builder.new do
33
+ feed :xmlns => "http://www.w3.org/2005/Atom" do
34
+ id! "http://rainbows.rubyforge.org/NEWS.atom.xml"
35
+ title "Rainbows! news"
36
+ subtitle "Unicorn for slow apps and slow clients"
37
+ link! :rel => 'alternate', :type => 'text/html',
38
+ :href => 'http://rainbows.rubyforge.org/NEWS.html'
39
+ updated(new_tags.empty? ? "1970-01-01T00:00:00Z" : new_tags.first[:time])
40
+ new_tags.each do |tag|
41
+ entry do
42
+ title tag[:subject]
43
+ updated tag[:time]
44
+ published tag[:time]
45
+ author {
46
+ name tag[:tagger_name]
47
+ email tag[:tagger_email]
48
+ }
49
+ url = "#{cgit_url}/tag/?id=#{tag[:tag]}"
50
+ link! :rel => "alternate", :type => "text/html", :href =>url
51
+ id! url
52
+ content(:type => 'text') { tag[:body] }
53
+ end
54
+ end
55
+ end
56
+ end.to_xml)
57
+ end
58
+
59
+ desc 'prints RDoc-formatted news'
60
+ task :news_rdoc do
61
+ tags.each do |tag|
62
+ time = tag[:time].tr!('T', ' ').gsub!(/:\d\dZ/, ' UTC')
63
+ puts "=== #{tag[:tag].sub(/^v/, '')} / #{time}"
64
+ puts ""
65
+
66
+ body = tag[:body]
67
+ puts tag[:body].gsub(/^/sm, " ").gsub!(/[ \t]+$/sm, "")
68
+ puts ""
69
+ end
70
+ end
71
+
72
+ desc "print release changelog for Rubyforge"
73
+ task :release_changes do
74
+ version = ENV['VERSION'] or abort "VERSION= needed"
75
+ version = "v#{version}"
76
+ vtags = tags.map { |tag| tag[:tag] =~ /\Av/ and tag[:tag] }.sort
77
+ prev = vtags[vtags.index(version) - 1]
78
+ if prev
79
+ system('git', 'diff', '--stat', prev, version) or abort $?
80
+ puts ""
81
+ system('git', 'log', "#{prev}..#{version}") or abort $?
82
+ else
83
+ system('git', 'log', version) or abort $?
84
+ end
85
+ end
86
+
87
+ desc "print release notes for Rubyforge"
88
+ task :release_notes do
89
+ require 'rubygems'
90
+
91
+ git_url = ENV['GIT_URL'] || 'git://git.bogomips.org/rainbows.git'
92
+
93
+ spec = Gem::Specification.load('rainbows.gemspec')
94
+ puts spec.description.strip
95
+ puts ""
96
+ puts "* #{spec.homepage}"
97
+ puts "* #{spec.email}"
98
+ puts "* #{git_url}"
99
+
100
+ _, _, body = `git cat-file tag v#{spec.version}`.split(/\n\n/, 3)
101
+ print "\nChanges:\n\n"
102
+ puts body
103
+ end