diff options
Diffstat (limited to 't/async_examples/async_app.ru')
-rw-r--r-- | t/async_examples/async_app.ru | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/t/async_examples/async_app.ru b/t/async_examples/async_app.ru new file mode 100644 index 0000000..328effb --- /dev/null +++ b/t/async_examples/async_app.ru @@ -0,0 +1,126 @@ +#!/usr/bin/env rackup -s thin +# +# async_app.ru +# raggi/thin +# +# A second demo app for async rack + thin app processing! +# Now using http status code 100 instead. +# +# Created by James Tucker on 2008-06-17. +# Copyright 2008 James Tucker <raggi@rubyforge.org>. +# +#-- +# Benchmark Results: +# +# raggi@mbk:~$ ab -c 100 -n 500 http://127.0.0.1:3000/ +# This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0 +# Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ +# Copyright 2006 The Apache Software Foundation, http://www.apache.org/ +# +# Benchmarking 127.0.0.1 (be patient) +# Completed 100 requests +# Completed 200 requests +# Completed 300 requests +# Completed 400 requests +# Finished 500 requests +# +# +# Server Software: thin +# Server Hostname: 127.0.0.1 +# Server Port: 3000 +# +# Document Path: / +# Document Length: 12 bytes +# +# Concurrency Level: 100 +# Time taken for tests: 5.263089 seconds +# Complete requests: 500 +# Failed requests: 0 +# Write errors: 0 +# Total transferred: 47000 bytes +# HTML transferred: 6000 bytes +# Requests per second: 95.00 [#/sec] (mean) +# Time per request: 1052.618 [ms] (mean) +# Time per request: 10.526 [ms] (mean, across all concurrent requests) +# Transfer rate: 8.55 [Kbytes/sec] received +# +# Connection Times (ms) +# min mean[+/-sd] median max +# Connect: 0 3 2.2 3 8 +# Processing: 1042 1046 3.1 1046 1053 +# Waiting: 1037 1042 3.6 1041 1050 +# Total: 1045 1049 3.1 1049 1057 +# +# Percentage of the requests served within a certain time (ms) +# 50% 1049 +# 66% 1051 +# 75% 1053 +# 80% 1053 +# 90% 1054 +# 95% 1054 +# 98% 1056 +# 99% 1057 +# 100% 1057 (longest request) + +class DeferrableBody + include EventMachine::Deferrable + + def call(body) + body.each do |chunk| + @body_callback.call(chunk) + end + end + + def each &blk + @body_callback = blk + end + +end + +class AsyncApp + + # This is a template async response. N.B. Can't use string for body on 1.9 + AsyncResponse = [-1, {}, []].freeze + + def call(env) + + body = DeferrableBody.new + + # Get the headers out there asap, let the client know we're alive... + EventMachine::next_tick { env['async.callback'].call [200, {'Content-Type' => 'text/plain'}, body] } + + # Semi-emulate a long db request, instead of a timer, in reality we'd be + # waiting for the response data. Whilst this happens, other connections + # can be serviced. + # This could be any callback based thing though, a deferrable waiting on + # IO data, a db request, an http request, an smtp send, whatever. + EventMachine::add_timer(1) { + body.call ["Woah, async!\n"] + + EventMachine::next_tick { + # This could actually happen any time, you could spawn off to new + # threads, pause as a good looking lady walks by, whatever. + # Just shows off how we can defer chunks of data in the body, you can + # even call this many times. + body.call ["Cheers then!"] + body.succeed + } + } + + # throw :async # Still works for supporting non-async frameworks... + + AsyncResponse # May end up in Rack :-) + end + +end + +# The additions to env for async.connection and async.callback absolutely +# destroy the speed of the request if Lint is doing it's checks on env. +# It is also important to note that an async response will not pass through +# any further middleware, as the async response notification has been passed +# right up to the webserver, and the callback goes directly there too. +# Middleware could possibly catch :async, and also provide a different +# async.connection and async.callback. + +# use Rack::Lint +run AsyncApp.new |