32
loading...
This website collects cookies to deliver better user experience
isolator
, a gem by the folks over at Evil Martians that detects non-atomic interactions within a database transaction. What do we mean by that? A simple example taken from the documentation that uses background jobs is something like the following:User.transaction do
user.update!(confirmed_at: Time.now)
UserMailer.successful_confirmation(user).deliver_later
end
after_create
, after_update
, after_save
, or even some combination of those. This particular set of hooks occur while the database transaction is still active. An example:class Comment < ApplicationRecord
after_create :notify_author
private
def notify_author
CommentMailer.comment_created(self).deliver_later
end
end
Using Redis as its data store, Sidekiq processes jobs very, very quickly. This is where we start running into problems when queuing workers mid-transaction.
Comment
model, it might mean that when the delayed mailer runs to notify the author about a new comment, that comment doesn't exist yet when the job starts processing.Isolator::BackgroundJobError:
You are trying to enqueue background job inside db transaction.
In case of transaction failure, this may lead to data inconsistency and unexpected bugs.
after_commit
instead (we'll get to ad hoc transactions in a bit). We could rewrite the Comment
model above like so:class Comment < ApplicationRecord
after_create_commit :notify_author
...
end
strong_migrations
, the author of the changes will get messages about these patterns ahead of time, and reviewers have one less thing to watch out for and can focus on other things.after_commit_everywhere
gem allows you to use similar transactional callbacks outside of your models, so something like this:ActiveRecord::Base.transaction do
after_commit { puts "We're all done!" }
end
after_commit
hooks provided by aasm
, where we're queuing jobs on state changes. But, I like the syntax in theory; I think it reads pretty well, and if you're doing a bit of work inside a transaction, having that block at the bottom would express the intent clearly.