gitlab-org--gitlab-foss/config/initializers/forbid_sidekiq_in_transactions.rb

50 lines
1.5 KiB
Ruby
Raw Normal View History

module Sidekiq
module Worker
2017-06-02 13:12:08 -04:00
mattr_accessor :skip_transaction_check
self.skip_transaction_check = false
def self.skipping_transaction_check(&block)
skip_transaction_check = self.skip_transaction_check
self.skip_transaction_check = true
yield
ensure
self.skip_transaction_check = skip_transaction_check
end
module ClassMethods
module NoSchedulingFromTransactions
NESTING = ::Rails.env.test? ? 1 : 0
%i(perform_async perform_at perform_in).each do |name|
define_method(name) do |*args|
2017-06-02 13:12:08 -04:00
return super(*args) if Sidekiq::Worker.skip_transaction_check
return super(*args) unless ActiveRecord::Base.connection.open_transactions > NESTING
raise <<-MSG.strip_heredoc
`#{self}.#{name}` cannot be called inside a transaction as this can lead to
race conditions when the worker runs before the transaction is committed and
tries to access a model that has not been saved yet.
Use an `after_commit` hook, or include `AfterCommitQueue` and use a `run_after_commit` block instead.
MSG
end
end
end
prepend NoSchedulingFromTransactions
end
end
end
module ActiveRecord
class Base
2017-06-02 13:12:08 -04:00
module SkipTransactionCheckAfterCommit
def committed!(*)
2017-06-02 13:12:08 -04:00
Sidekiq::Worker.skipping_transaction_check { super }
end
end
2017-06-02 13:12:08 -04:00
prepend SkipTransactionCheckAfterCommit
end
end