Slowpoke
Rack::Timeout enhancements for Rails
- safer service timeouts
- dynamic timeouts
- custom error pages
Installation
Add this line to your application’s Gemfile:
gem "slowpoke"
And run:
rails generate slowpoke:install
This creates a public/503.html
you can customize.
Development
To try out custom error pages in development, temporarily add to config/environments/development.rb
:
config.slowpoke.timeout = 1
config.consider_all_requests_local = false
And add a sleep
call to one of your actions:
sleep(2)
The custom error page should appear.
Production
The default timeout is 15 seconds. You can change this in config/environments/production.rb
with:
config.slowpoke.timeout = 5
For dynamic timeouts, use:
config.slowpoke.timeout = lambda do |env|
request = Rack::Request.new(env)
request.path.start_with?("/admin") ? 15 : 5
end
Subscribe to timeouts with:
ActiveSupport::Notifications.subscribe "timeout.slowpoke" do |name, start, finish, id, payload|
# report timeout
end
To learn more, see the Rack::Timeout documentation.
Safer Service Timeouts
Rack::Timeout can raise an exception at any point in the code, which can leave your app in an unclean state. The safest way to recover from a request timeout is to spawn a new process. This is the default behavior for Slowpoke.
For threaded servers like Puma, this means killing all threads when any one of them times out. This can have a significant impact on performance.
You can customize this behavior with:
Slowpoke.on_timeout do |env|
next if Rails.env.development? || Rails.env.test?
exception = env["action_dispatch.exception"]
if exception && exception.backtrace.first.include?("/active_record/")
Slowpoke.kill
end
end
Note: To access env["action_dispatch.exception"]
in development, temporarily add to config/environments/development.rb
:
config.consider_all_requests_local = false
Database Timeouts
It’s a good idea to set a statement timeout and a connect timeout. For Postgres, your config/database.yml
should include something like:
production:
connect_timeout: 3 # sec
variables:
statement_timeout: 5s
History
View the changelog
Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- Report bugs
- Fix bugs and submit pull requests
- Write, clarify, or fix documentation
- Suggest or add new features
To get started with development:
git clone https://github.com/ankane/slowpoke.git
cd slowpoke
bundle install
bundle exec rake test