Date | Commit message (Collapse) |
|
The major feature of this release is the new DeferredResponse
middleware for the Rev-based concurrency model. It should be
transparently compatible with non-Rev models, as well. As a
pleasant side effect, this change also allows large files to be
streamed to the client with Rev as the socket becomes writable
instead of slurping the entire file into an IO::Buffer first.
Bugfixes to graceful shutdowns support for all concurrency
models. The Rev-based model also gets a working heartbeat
mechanism (oops!) and fixed HTTP/1.1 pipelining support.
Eric Wong (37):
app_pool: note it being currently broken with Revactor
Revactor tests can sleep more easily
tests: sleep.ru handles "Expect: 100-continue"
Fix graceful shutdown handling of Thread* models harder
DRY setting of rack.multithread
test-lib: dbgcat adds headers with key name
use timeout correctly to join threads on SIGQUIT
Rev: simplification to error handling
tests: sleep.ru slurps rack.input stream
refactor graceful shutdowns again, harder
tests: introduce require_for_model function
tests: add unbuffered tee(1)-like helper
tests: rack.input trailer tests for all models
tests: fix issues with non-portable shell constructs
tests: fix random_blob dependency
tests: factor out a common parser error "library"
tests: DRY setting of the "model" environment var
tests: DRY Ruby requires based on model
test-lib: quiet down pipefail error message
tests: DRY require tests for Rev/Revactor
rev: handle fully-buffered, pipelined requests
rev: avoid stack overflow through pipelining
tests: common basic HTTP tests for all models
tests: rack.input hammer concurrency testing
tests: for log reopening for all concurrency models
http_response: filter out X-Rainbows-* headers
rev: fix heartbeat timeouts
revactor: switch to a 1 second heartbeat
rev: async response bodies with DevFdResponse middleware
tests: more reliable error checking
tests: DWIM FIFO creation
tests: predictable and simpler tempfile management
rev: AsyncResponse => DeferredResponse API cleanup
rev: update documentation for this model
TUNING: update documentation notes
TODO: update with new items
local.mk.sample: sync with BDFL's version
|
|
|
|
The "async" moniker wasn't appropriate since this API also
handles static files without slurping, so "deferred" is a more
appropriate term (even if I have trouble speling words with
double conssonants in them).
The DeferredResponse.write method now emulates the
HttpResponse.write method for consistency.
|
|
This new middleware should be a no-op for non-Rev concurrency
models (or by explicitly setting env['rainbows.autochunk'] to
false).
Setting env['rainbows.autochunk'] to true (the default when Rev
is used) allows (e)poll-able IO objects (sockets, pipes) to be
sent asynchronously after app.call(env) returns.
This also has a fortunate side effect of introducing a code path
which allows large, static files to be sent without slurping
them into a Rev IO::Buffer, too. This new change works even
without the DevFdResponse middleware, so you won't have to
reconfigure your app.
This lets us epoll on response bodies that come in from a pipe
or even a socket and send them either straight through or with
chunked encoding.
|
|
Like everybody else... Closing the listener sockets doesn't seem
to wakeup the actors reliably and since it's easier to use a 1
second heartbeat than correct signal/messaging for all the rest
of the other clients, we'll just do that instead of relying on
one-off signal handlers.
|
|
Oops, looks like they were never implemented at all.
|
|
We'll be using some custom headers to craft responses
|
|
Handling HTTP pipelining through recursion is not good since
several hundred kilobytes worth of GET/HEAD requests can be a
LOT of GET/HEAD requests...
|
|
This leaves us vulnerable to stack overflows through excessive
pipelining. The next patch will fix things hopefully.
|
|
We use the "G" global constant from the Rev model everywhere
to simplify things a little.
Test cases are more consistent now, too.
|
|
on_write_complete has no chance of being called
there so remove the unnecessary ensure statement
|
|
Subtraction is a difficult concept for some folks (like
myself) to grasp and implement.
|
|
It's more fool-proof this way and prevents us from using
idiotic/non-obvious concurrency model names.
|
|
I need better tests for graceful shutdown...
|
|
Revactor does not use threads and blocking on a stock Queue
class does not work. Eventually this should be made to work
with the Actor model, but until then, we'll at least document
it...
|
|
This release adds preliminary Rev support for network
concurrency under Ruby 1.8 and Ruby 1.9. There are caveats to
this model and reading the RDoc for Rainbows::Rev is
recommended.
Rainbows::AppPool Rack middleware is now available to limit
application concurrency on a per-process basis independently of
network concurrency. See the RDoc for this class for further
details.
Per-client timeouts have been removed, see
http://mid.gmane.org/20091013062602.GA13128@dcvr.yhbt.net
for the reasoning.
Rack environment changes:
* "rack.multithread" is now only true for models with "Thread"
in their name. Enabling thread-safe (but not reentrant) code
may actually be harmful for Revactor.
* "rainbows.model" is now exposed so the application can easily
figure out which network concurrency model is in use.
Bugfixes include better shutdown and error handling for all
existing models, OpenBSD compatibility for the per-process
heartbeat (same as found in unicorn v0.93.3).
Eric Wong (53):
add SIGNALS doc to RDoc
SIGNALS: add Rainbows!-specific notes
doc: better "Rainbows!" RDoc examples and linkage
tests: generate random_blob once for all tests
tests: move trash files to their own trash/ directory
t0000: basic test includes keepalive + pipelining
tests: simplify temporary file management
tests: add dbgcat() utility method
fchmod heartbeat flips between 0/1
tests: add revactor pipelining/keepalive test
thread_spawn: trap EAGAIN on accept_nonblock
thread_spawn: more robust loop
thread_spawn: non-blocking accept() shouldn't EINTR
tests: enable pipefail shell option if possible
README for test suite
tests: TEST_OPTS => SH_TEST_OPTS
tests: update TRACER examples in makefile
tests: create a bad exit code by default
thread_spawn: clean up nuking of timed-out threads
factor out common listen loop error handling
graceful exit on trap TypeError from IO.select
expand and share init_worker_process
revactor: break on EBADF in the accepting actors
revactor: cleanups and remove redundancy
No need to be halving timeout, already done for us
revactor: graceful death of keepalive clients
revactor: continue fchmod beat in graceful exit
cleanup thread models, threads no longer time out
revactor: fix graceful shutdown timeouts
Fix graceful shutdowns for threaded models
SIGINT/SIGTERM shuts down instantly in workers
tests: check for common exceptions with "Error"
DEPLOY: update with notes on DoS potential
tests: add reopen logs test for revactor
vs Unicorn: use diagrams for concurrency models
vs Unicorn: fix wording to be consistent with diagrams
vs Unicorn: fix copy+paste errors and grammar fail
README: alter reply conventions for the mailing list
preliminary Rev support
local.mk.sample: use ksh93 as default $(SHELL)
rack.multithread is only true for Thread* models
Rev: general module documentation + caveats
Rev: fix error handling for parser errors
t3003: set executable bit
documentation updates (mostly on network models)
rack: expose "rainbows.model" in Rack environment
tests: enforce rack.multithread and rainbows.model
README: update URLs
README: update with Rev model caveats
Add Rainbows::AppPool Rack middleware
t4003: chmod +x
local.mk.sample: use rev 0.3.1 instead
README: link to AppPool and extra note about Rev model
|
|
|
|
This allows applications to determine which concurrency model
they're running under and possibly make adjustments accordingly.
The standard "rack.multithread" isn't enough for some
applications to determine what to do, especially when reentrancy
is required/recommended.
|
|
|
|
We should try to send 400s back to the client if possible.
|
|
|
|
Enabling thread-safe or thread-aware code paths in applications
may even be dangerous in some cases and cause deadlocks in code
that otherwise does not expect threads. This is especially true
of the Revactor case where being a "drop-in" replacement for IO
routines is dangerous if a mutex is held while an Actor performs
a "blocking" I/O operation.
Basically start to assume that anybody writing an app using
Rev or Revactor already takes Rev/Revactor concurrency into
account and won't need the rack.multithread flag set to do
special things.
|
|
There is no TeeInput (streaming request body) support, yet,
as that does not seem fun nor easy to do (or even possible
without using Threads or Fibers or something to save/restore
the stack...)
|
|
Just like in Unicorn...
|
|
They were completely broken in the refactoring :x
|
|
|
|
The process-based heartbeat continues, but we no longer time
threads out just because a client is idle for any reason (for
now).
|
|
Avoid overloading the "alive" variable here and wakeup less
frequently as well to do the fchmod.
|
|
We'll finish processing the current request and
set the "Connection: close" header if possible.
|
|
In Unicorn by HttpServer#init_worker_process
|
|
|
|
Once our listeners get closed, we're as good as
dead so we should exit to avoid spinning.
|
|
This can be common across everything
|
|
Avoid potential race conditions with signal handlers, this makes
exits cleaner since the LISTENERS array will get map!-ed to nils
in the :QUIT signal handler.
|
|
It'll be easier to maintain a common language for logging
and debugging.
|
|
We log thread destruction times now and also make a best-effort
to avoid race conditions on threads that just finished.
|
|
Something is probably wrong with the OS if it does,
so make sure it gets logged and hopefully reported.
|
|
Bad stuff happens, even in our own code because sometimes
we don't know what we're doing. So log it so we'll know to
fix it and let life go on...
|
|
EAGAIN is common on accept_nonblock with multiple processes
sharing the same listen descriptors.
oops :x
|
|
This is for compatibility with OpenBSD as reported
by Jeremy Evans for Unicorn.
|
|
Fixed Ruby 1.8 support (and all 1.9 systems without Revactor).
Process-wide timeout handling for the ThreadSpawn concurrency
model should now work properly. Small cleanups everywhere.
Eric Wong (16):
Rakefile: add publish_news target
Fix NEWS generation on single-paragraph tag messages
README: move RDoc links down to fix gem description
README: add install instructions
summary: s/slow apps/sleepy apps/g
Avoid naming names in LICENSE/README files
rainbows/base: cleanup constant include
tests: quiet down bin installation
Add top-level "test" target for make
local.mk.sample: sync to my current version
tests: allow "make V=2" to set TEST_OPTS += -x
cleanup temporary file usage in tests
local.mk.sample: fix revactor dependency
Thread* models: cleanup timeout management
thread_spawn: fix timeout leading to worker death
less error-prone timeouts for Thread models
|
|
Avoid calling chmod on "false" leading to NoMethodError
and rely entirely on LISTENERS.first being valid.
|
|
|
|
Ensure we reset the per-thread time Thread.current[:t] with each
connection so we don't timeout long-lived connections.
|
|
This was breaking badly under 1.8 since Revactor couldn't be
included (the constant is listed once it is declared as an
autoload).
|
|
Not using the Unicorn version number with this
since it's not remotely close to Unicorn in stability.
|
|
|
|
Various concurrency models work and scale differently, pick
counts that make a reasonable amount of sense...
|
|
This is somewhat like the original model found in Mongrel,
except we refuse to accept() connections unless we have slots
available. Even though we support multiple listen sockets, we
only accept() synchronously to simplify processing and to avoid
having to synchronize ThreadGroup management.
|
|
It's usually a bad sign if we have unhandled exceptions in
the listener loops, so we'll exit just in case.
|