rack-timeout: Rescuing timeout errors in middleware

Hi - I’ve been running into a problem recently with Rack::Timeout’s errors killing Puma workers (since they now descend from Exception rather than StandardError and are not caught by most rescue blocks).

I’ve worked around this with a quick rack middleware to catch Rack::Timeout’s errors and wrap them in StandardErrors:

class TimeoutRecovery
  def initialize(app, options = {})
    @app, @options = app, options
  end

  # Rack::Timeout, as of 0.2.4, raises errors that descend from the Exception
  # class when a request takes too long - however, this is a very strong
  # exception level and will kill Puma's worker if we let it continue down the
  # stack. So instead, catch it and wrap it in a recoverable StandardError.

  class Error < StandardError; end

  def call(env)
    @app.call(env)
  rescue Rack::Timeout::Error => e
    raise Error, "Original Error: #{e.class.inspect}, #{e.message.inspect}, #{e.backtrace.inspect}"
  end
end

It seems like this is something that Rack::Timeout should be doing, though. Unless I’ve missed something and this is actually a terrible idea. Sure, we should be avoiding long request times where possible, but when they come up they’re leaving Puma’s workers crashed and unable to serve requests at all until a restart.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 34 (14 by maintainers)

Commits related to this issue

Most upvoted comments

We’ve been tracking an issue where unicorn workers will die without closing database connections; I wonder if something similar is happening?

Yeah but that’s a known possibility and the solution to that is similar. Add an observer or rescue the error, close the connections, then probably re-raise.

I don’t know if there’s a one-size-fits-all solution here, and more and more I’m leaning against raising at all. Just provide a hook for people to do whatever they want with it? Then maybe provide some standard behaviours: log, raise, die… which I suppose one could do with observers already…

250px-054psyduck