2021-02-03 21:09:17 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-02-20 13:28:05 +00:00
|
|
|
module Sidekiq
|
|
|
|
module Worker
|
2017-12-22 10:38:35 +00:00
|
|
|
EnqueueFromTransactionError = Class.new(StandardError)
|
|
|
|
|
2017-06-02 17:12:08 +00:00
|
|
|
def self.skipping_transaction_check(&block)
|
2019-07-04 13:46:46 +00:00
|
|
|
previous_skip_transaction_check = self.skip_transaction_check
|
|
|
|
Thread.current[:sidekiq_worker_skip_transaction_check] = true
|
2017-06-02 17:12:08 +00:00
|
|
|
yield
|
|
|
|
ensure
|
2019-07-04 13:46:46 +00:00
|
|
|
Thread.current[:sidekiq_worker_skip_transaction_check] = previous_skip_transaction_check
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.skip_transaction_check
|
|
|
|
Thread.current[:sidekiq_worker_skip_transaction_check]
|
2017-06-02 17:12:08 +00:00
|
|
|
end
|
2017-06-01 21:35:32 +00:00
|
|
|
|
2017-02-20 13:28:05 +00:00
|
|
|
module ClassMethods
|
2017-12-22 10:38:35 +00:00
|
|
|
module NoEnqueueingFromTransactions
|
2017-02-20 13:28:05 +00:00
|
|
|
%i(perform_async perform_at perform_in).each do |name|
|
|
|
|
define_method(name) do |*args|
|
2021-07-29 15:09:48 +00:00
|
|
|
if !Sidekiq::Worker.skip_transaction_check && Gitlab::Database.main.inside_transaction?
|
2018-03-05 11:31:23 +00:00
|
|
|
begin
|
|
|
|
raise Sidekiq::Worker::EnqueueFromTransactionError, <<~MSG
|
2017-11-29 15:30:17 +00:00
|
|
|
`#{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.
|
2017-02-20 13:28:05 +00:00
|
|
|
|
2017-11-29 15:30:17 +00:00
|
|
|
Use an `after_commit` hook, or include `AfterCommitQueue` and use a `run_after_commit` block instead.
|
2018-03-05 11:31:23 +00:00
|
|
|
MSG
|
|
|
|
rescue Sidekiq::Worker::EnqueueFromTransactionError => e
|
2020-09-09 12:08:22 +00:00
|
|
|
Gitlab::AppLogger.error(e.message) if ::Rails.env.production?
|
2019-12-16 12:07:43 +00:00
|
|
|
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
|
2018-03-05 11:31:23 +00:00
|
|
|
end
|
2017-11-29 15:30:17 +00:00
|
|
|
end
|
2017-02-20 13:28:05 +00:00
|
|
|
|
2017-11-29 15:30:17 +00:00
|
|
|
super(*args)
|
2017-02-20 13:28:05 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-12-22 10:38:35 +00:00
|
|
|
prepend NoEnqueueingFromTransactions
|
2017-02-20 13:28:05 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2017-06-01 21:35:32 +00:00
|
|
|
|
|
|
|
module ActiveRecord
|
|
|
|
class Base
|
2017-06-02 17:12:08 +00:00
|
|
|
module SkipTransactionCheckAfterCommit
|
2020-10-02 12:09:03 +00:00
|
|
|
def committed!(*args, **kwargs)
|
2017-06-02 17:12:08 +00:00
|
|
|
Sidekiq::Worker.skipping_transaction_check { super }
|
2017-06-01 21:35:32 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-06-02 17:12:08 +00:00
|
|
|
prepend SkipTransactionCheckAfterCommit
|
2017-06-01 21:35:32 +00:00
|
|
|
end
|
|
|
|
end
|