Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are rails controllers multithreaded? Thread.exclusive in controllers

Are Rails controllers multithreaded?

If so, can I protect a certain piece of code (which fires only once every ten minutes) from being run from multiple threads by simply doing

require 'thread'
Thread.exclusive do
     # stuff here
end

on do I need to somehow synchronize on a monitor?

like image 573
Dan Rosenstark Avatar asked Sep 07 '09 11:09

Dan Rosenstark


People also ask

Is rails single threaded?

Rails as a framework is thread-safe. So, the answer is yes! The second link that you posted here names many of the Rails servers that don't do well with multi-threading. He later mentions that nginx is the way to go (it is definitely the most popular one and highly recommended).

Is Ruby single threaded or multi-threaded?

The Ruby Interpreter is single threaded, which is to say that several of its methods are not thread safe.

Is Ruby multi-threaded?

Ruby makes it easy to write multi-threaded programs with the Thread class. Ruby threads are a lightweight and efficient way to achieve concurrency in your code.

Can rails handle concurrent requests?

1 Automatic ConcurrencyRails automatically allows various operations to be performed at the same time. When using a threaded web server, such as the default Puma, multiple HTTP requests will be served simultaneously, with each request provided its own controller instance.


2 Answers

Running rake middleware on a basic rails app gives the following:

use Rack::Lock
use ActionController::Failsafe
use ActionController::Reloader
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActiveRecord::SessionStore, #<Proc:0x017fb394@(eval):8>
use ActionController::RewindableInput
use ActionController::ParamsParser
use Rack::MethodOverride
use Rack::Head
run ActionController::Dispatcher.new

The first item on the rack stack is Rack::Lock. This puts a lock around each request, so only one request is handled at a time. As such a standard rails app is single threaded. You can however spawn new threads within a request that would make your app multi threaded, most people never encounter this.

If you are having issues…

require 'thread'
Thread.exclusive do
     # stuff here
end

… would ensure that stuff inside the block is never run in parallel with any other code. Creating a shared Mutext between all threads (in a class variable or something, but this could be wiped when reloaded in dev mode, so be careful), and locking on it as Rack::Lock#call does is to be preferred if you just want to ensure no two instances of the same code is executed at the same time.

Also, for the record, each request creates and dereferences one controller in each request cycle. No two requests should see the same instance, although they may see the same class.

Setting config.threadsafe! voids almost everything I said. That removes Rack::Lock from the stack, and means you will need to set a mutex manually to prevent double entry. Don't do it unless you have a really good reason.

Even without Rack::Lock you will still get one controller instance per request. The entry point to your controller ensures that, notice the call to new in process.

like image 155
cwninja Avatar answered Nov 09 '22 05:11

cwninja


My understanding is that a new controller instance is created for each HTTP request that is processed by a controller.

like image 32
John Topley Avatar answered Nov 09 '22 06:11

John Topley