Maybe you've been in this situation: you want to call some Ruby while responding to an HTTP request, but it's a time-consuming operation, its outcome won't impact the response you send, and naively invoking it will result in a slower page load or API response for your users.
In almost all cases like this, Rubyists will reach for a job queue. And that's usually the right answer! But for relatively trivial tasks—cases where the only reason you want to defer execution is a faster page load—creating a new job class and scheduling the work onto a queuing system can feel like overkill.
If this resonates with you, the maybe_later
gem might be the best way to run
that code for you (eventually).
maybe_later
didn't make it clear, this gem does nothing to
ensure that your after-action callbacks actually run. If the code you're calling
is very important, use sidekiq or
something!
Add the gem to your Gemfile:
gem "maybe_later"
If you're using Rails, the gem's middleware will be registered automatically. If
you're not using Rails but are using a rack-based server that supports
env["rack.after_reply"] (which
includes
puma
and
unicorn),
just add use MaybeLater::Middleware
to your config.ru
file.
Using the gem is pretty straightforward, just pass the code you want to run to
MaybeLater.run
as a block:
MaybeLater.run {
AnalyticsService.send_telemetry!
}
Each block passed to MaybeLater.run
will be run after the HTTP response is
sent.
If the code you're calling needs to be executed in the same thread that's
handling the HTTP request, you can pass inline: true
:
MaybeLater.run(inline: true) {
# Thread un-safe code here
}