Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rack middleware and thread-safety

I have a custom rack middleware used by my Rails 4 application. The middleware itself is just here to default Accept and Content-Type headers to application/json if the client did not provide a valid information (I'm working on an API). So before each request it changes those headers and after each request it adds a custom X-Something-Media-Type head with a custom media type information.

I would like to switch to Puma, therefore I'm a bit worried about the thread-safety of such a middleware. I did not play with instances variables, except once for the common @app.call that we encounter in every middleware, but even here I reproduced something I've read in RailsCasts' comments :

def initialize(app)
 @app = app
end

def call(env)
 dup._call(env)
end

def _call(env)
 ...
 status, headers, response = @app.call(env)
 ...

Is the dup._call really useful in order to handle thread-safety problems ?

Except that @app instance variable I only play with the current request built with the current env variable :

request      = Rack::Request.new(env)

And I call env.update to update headers and forms informations.

Is it dangerous enough to expect some issues with that middleware when I'll switch from Webrick to a concurrent web server such as Puma ?

If yes, do you know a handful way to make some tests en isolate portions of my middleware which are non-thread-safe ?

Thanks.

like image 886
Mich Avatar asked Apr 12 '14 08:04

Mich


1 Answers

Yes, it's necessary to dup the middleware to be thread-safe. That way, anything instance variables you set from _call will be set on the duped instance, not the original. You'll notice that web frameworks that are built around Rack work this way:

  • Pakyow
  • Sinatra

One way to unit test this is to assert that _call is called on a duped instance rather than the original.

like image 114
bryanp Avatar answered Sep 28 '22 09:09

bryanp