Permalink
Browse files

Implement optional threading support.

  • Loading branch information...
1 parent 2141c98 commit ca5dffdaa8326be2958d678082814bacc0f335ce @macournoyer committed Aug 5, 2012
View
@@ -63,6 +63,18 @@ def use_kqueue(value)
set :use_kqueue, value, TrueClass, FalseClass
end
+ # {include:Thin::Server#threaded}
+ # @see Thin::Server#threaded
+ def threaded(value)
+ set :threaded, value, TrueClass, FalseClass
+ end
+
+ # {include:Thin::Server#thread_pool_size}
+ # @see Thin::Server#thread_pool_size
+ def thread_pool_size(value)
+ set :thread_pool_size, value, Integer
+ end
+
# {include:Thin::Server#before_fork}
# @see Thin::Server#before_fork
def before_fork(&block)
View
@@ -9,6 +9,7 @@ module Protocols
# * Asynchronous responses, via the <tt>env['async.callback']</tt> or <tt>throw :async</tt>.
# * Keep-alive.
# * File streaming.
+ # * Calling the Rack app from pooled threads.
class Http < EM::Connection
# Http class has to be defined before requiring those.
require "thin/protocols/http/request"
@@ -51,6 +52,8 @@ def on_message_begin
end
def on_headers_complete(headers)
+ @request.multithread = server.threaded?
+ @request.multiprocess = server.prefork?
@request.remote_address = socket_address
@request.http_version = "HTTP/%d.%d" % @parser.http_version
@request.method = @parser.http_method
@@ -75,8 +78,12 @@ def on_message_complete
# Starts the processing of the current request in <tt>@request</tt>.
def process
- if response = call_app
- process_response(response)
+ if server.threaded?
+ EM.defer(method(:call_app), method(:process_response))
+ else
+ if response = call_app
+ process_response(response)
+ end
end
end
@@ -125,6 +132,9 @@ def process_response(response)
handle_error
end
+
+ # == Support methods
+
# Send the HTTP response back to the client.
def send_response(response=@response)
@response = response
@@ -70,8 +70,6 @@ def initialize
RACK_VERSION => VERSION::RACK,
RACK_ERRORS => $stderr,
- RACK_MULTITHREAD => false,
- RACK_MULTIPROCESS => true,
RACK_RUN_ONCE => false
}
@keep_alive = false
@@ -129,6 +127,14 @@ def keep_alive=(bool)
@keep_alive = bool
end
+ def multithread=(bool)
+ @env[RACK_MULTITHREAD] = bool
+ end
+
+ def multiprocess=(bool)
+ @env[RACK_MULTIPROCESS] = bool
+ end
+
# Returns +true+ if the client expect the connection to be kept alive.
def keep_alive?
@keep_alive
View
@@ -74,6 +74,14 @@ class Server
# Default: 1024
attr_accessor :worker_connections
+ # Set to +true+ to call +app+ in a thread.
+ # Default: false
+ attr_accessor :threaded
+
+ # Size of the pool of threads used to call the +app+.
+ # Default: 20
+ attr_accessor :thread_pool_size
+
# Workers are killed if they don't check-in under +timeout+ seconds.
# Default: 30
attr_accessor :timeout
@@ -117,6 +125,8 @@ def initialize(&app_loader)
@pid_path = "./thin.pid"
@log_path = nil
@worker_connections = 1024
+ @threaded = false
+ @thread_pool_size = 20
if System.supports_fork?
# One worker per processor
@@ -164,6 +174,7 @@ def start(daemonize=false)
EM.epoll = @use_epoll unless @use_epoll.nil?
EM.kqueue = @use_kqueue unless @use_kqueue.nil?
@worker_connections = EM.set_descriptor_table_size(@worker_connections)
+ EM.threadpool_size = @thread_pool_size
# Preload the app in the master process.
@app = @app_loader.call if @preload_app
@@ -202,6 +213,10 @@ def stop
def prefork?
@worker_processes > 0
end
+
+ def threaded?
+ @threaded
+ end
# Procline of the process when the server is running.
def to_s
@@ -52,6 +52,8 @@ def test_defaults_server_name_and_port
end
def test_validate_through_rack_lint
+ @request.multithread = false
+ @request.multiprocess = false
@request.method = "GET"
@request.path = "/info"
@request.fragment = "hello"
View
@@ -12,11 +12,15 @@ def setup
@connection.stubs(:socket_address).returns("127.0.0.1")
end
+ #### Server methods
def app
proc do |env|
[200, {"Content-Type" => "text/plain"}, ["ok"]]
end
end
+ def threaded?; false end
+ def prefork?; false end
+ ####
def teardown
@connection.unbind
View
@@ -10,7 +10,7 @@ x Keep-alive
- Use Logger
- Rotate logs on USR1 signal
- Zero downtime restart on USR2 signal
-- Threading
+x Threading
- Rails streaming
- Change user:group after bind
- Wait for app ready before binding: support https://devcenter.heroku.com/articles/labs-preboot/

0 comments on commit ca5dffd

Please sign in to comment.