Reliable Background Work in Rails with Active Job
Move slow work out of the request
Sending email or calling an external service during a form submission ties the response to another system's availability. Save the user's change first, then enqueue the slow work. Active Job provides a Rails interface; configure a persistent backend such as Sidekiq for work that must survive a process restart.
class NotifyAuthorJob < ApplicationJob
queue_as :default
discard_on ActiveRecord::RecordNotFound
def perform(post_id)
post = Post.find(post_id)
return unless post.published? && post.verified?
AuthorMailer.published(post).deliver_now
end
end
Enqueue NotifyAuthorJob.perform_later(post.id) after the publishing transaction commits. The job loads current state, so a post withdrawn before execution will not trigger the notification. The mailer shown here is an application component you need to implement.
Expect repeated execution
A worker can fail after the email provider accepts a request but before the queue records completion. Retries can therefore send twice. For important side effects, store a delivery record with a unique event key and use the provider's idempotency feature when available. A simple sent_at flag alone does not close every failure window.
Retry deliberately
Distinguish temporary timeouts from invalid input. Bound retries and external request timeouts. Active Job and the backend may both retry, so inspect their combined behavior before choosing a policy. Missing records can usually be discarded; persistent configuration errors need attention rather than endless retries.
Operate the queue
Watch queue age and failed jobs, not just worker uptime. Keep expensive indexing work in a separate queue so it cannot delay user notifications. Test stale records and duplicate executions as well as the happy path.
Reference: Active Job Basics.
Quy
Reactions
Comments
Sign in to join the conversation.