Created
January 24, 2018 02:43
-
-
Save sj26/fca6e25ea902f36c87bc57bbc8a3c6e2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Weak ACID semantics for Sidekiq jobs | |
# | |
# Include this module in a Sidekiq::Worker class and it will defer enqueuing | |
# jobs for that worker within an open ActiveRecord transaction until it is | |
# committed. Rollbacks will prevent any jobs being enqueued at all. | |
# | |
# ActiveRecord keeps track of all records which are being utilized within a | |
# transaction so it can fulfil commit and rollback callbacks. We create a fake | |
# record that quacks the same way for the same hooks. | |
# | |
# Inspired by: http://blog.arkency.com/2015/10/run-it-in-background-job-after-commit/ | |
# | |
module Sidekiq::AfterTransaction | |
extend ActiveSupport::Concern | |
class Error < RuntimeError; end | |
class PushError < Error; end | |
module ClassMethods | |
def client_push(*args) | |
if ActiveRecord::Base.connection.transaction_open? | |
ActiveRecord::Base.connection.current_transaction.add_record(Record.new(self, *args)) | |
else | |
super(*args) | |
end | |
end | |
end | |
class Record | |
def initialize(klass, *args) | |
@klass = klass | |
@args = args | |
end | |
delegate :logger, to: :Sidekiq | |
def has_transaction_callbacks? | |
true | |
end | |
def before_committed!(*) | |
end | |
def committed!(*) | |
logger.debug("[Sidekiq::AfterTransaction]: Commit, pushing Sidekiq job: #{@klass.name}.client_push(#{@args.inspect[1...-1]})") | |
@klass.client_push(*@args) | |
rescue | |
raise PushError.new("Transaction committed but Sidekiq push failed") | |
end | |
def rolledback!(*) | |
logger.debug "[Sidekiq::AfterTransaction]: Rollback, discarding Sidekiq job: #{@klass.name}.client_push(#{@args.inspect[1...-1]})" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment