{"action":"created","issue":{"url":"https://api.github.com/repos/heroku/rack-timeout/issues/76","labels_url":"https://api.github.com/repos/heroku/rack-timeout/issues/76/labels{/name}","comments_url":"https://api.github.com/repos/heroku/rack-timeout/issues/76/comments","events_url":"https://api.github.com/repos/heroku/rack-timeout/issues/76/events","html_url":"https://github.com/heroku/rack-timeout/issues/76","id":68722716,"number":76,"title":"Rescuing timeout errors in middleware","user":{"login":"chanks","id":300058,"avatar_url":"https://avatars.githubusercontent.com/u/300058?v=3","gravatar_id":"","url":"https://api.github.com/users/chanks","html_url":"https://github.com/chanks","followers_url":"https://api.github.com/users/chanks/followers","following_url":"https://api.github.com/users/chanks/following{/other_user}","gists_url":"https://api.github.com/users/chanks/gists{/gist_id}","starred_url":"https://api.github.com/users/chanks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chanks/subscriptions","organizations_url":"https://api.github.com/users/chanks/orgs","repos_url":"https://api.github.com/users/chanks/repos","events_url":"https://api.github.com/users/chanks/events{/privacy}","received_events_url":"https://api.github.com/users/chanks/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":11,"created_at":"2015-04-15T16:06:34Z","updated_at":"2015-04-21T20:27:01Z","closed_at":null,"body":"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).\r\n\r\nI've worked around this with a quick rack middleware to catch Rack::Timeout's errors and wrap them in StandardErrors:\r\n\r\n```\r\nclass TimeoutRecovery\r\n  def initialize(app, options = {})\r\n    @app, @options = app, options\r\n  end\r\n\r\n  # Rack::Timeout, as of 0.2.4, raises errors that descend from the Exception\r\n  # class when a request takes too long - however, this is a very strong\r\n  # exception level and will kill Puma's worker if we let it continue down the\r\n  # stack. So instead, catch it and wrap it in a recoverable StandardError.\r\n\r\n  class Error < StandardError; end\r\n\r\n  def call(env)\r\n    @app.call(env)\r\n  rescue Rack::Timeout::Error => e\r\n    raise Error, \"Original Error: #{e.class.inspect}, #{e.message.inspect}, #{e.backtrace.inspect}\"\r\n  end\r\nend\r\n```\r\n\r\nIt 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."},"comment":{"url":"https://api.github.com/repos/heroku/rack-timeout/issues/comments/94929905","html_url":"https://github.com/heroku/rack-timeout/issues/76#issuecomment-94929905","issue_url":"https://api.github.com/repos/heroku/rack-timeout/issues/76","id":94929905,"user":{"login":"kch","id":8216,"avatar_url":"https://avatars.githubusercontent.com/u/8216?v=3","gravatar_id":"","url":"https://api.github.com/users/kch","html_url":"https://github.com/kch","followers_url":"https://api.github.com/users/kch/followers","following_url":"https://api.github.com/users/kch/following{/other_user}","gists_url":"https://api.github.com/users/kch/gists{/gist_id}","starred_url":"https://api.github.com/users/kch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kch/subscriptions","organizations_url":"https://api.github.com/users/kch/orgs","repos_url":"https://api.github.com/users/kch/repos","events_url":"https://api.github.com/users/kch/events{/privacy}","received_events_url":"https://api.github.com/users/kch/received_events","type":"User","site_admin":false},"created_at":"2015-04-21T20:27:01Z","updated_at":"2015-04-21T20:27:01Z","body":"> We've been tracking an issue where unicorn workers will die without closing database connections; I wonder if something similar is happening?\r\n\r\nYeah but that's a known possibility and the solution to that is similar. Add on observer or rescue the error, close the connections, then probably re-raise.\r\n\r\nI 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… \r\n\r\n![250px-054psyduck](https://cloud.githubusercontent.com/assets/8216/7261876/046ae5d0-e82a-11e4-91a4-bff60fd73ab8.png)\r\n"}}