summaryrefslogtreecommitdiff
path: root/config/initializers/forbid_sidekiq_in_transactions.rb
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2017-06-01 16:35:32 -0500
committerDouwe Maan <douwe@selenight.nl>2017-06-02 11:43:32 -0500
commita9dbda8605f2c3111c4e4775edf7f931e4260a41 (patch)
tree4fb2253f569d1c670ac4ddba8d81733c154334cd /config/initializers/forbid_sidekiq_in_transactions.rb
parent4edb505bb6783525444dd0179d1fb536a5cd1390 (diff)
downloadgitlab-ce-a9dbda8605f2c3111c4e4775edf7f931e4260a41.tar.gz
Allow scheduling from after_commit hooks
Diffstat (limited to 'config/initializers/forbid_sidekiq_in_transactions.rb')
-rw-r--r--config/initializers/forbid_sidekiq_in_transactions.rb36
1 files changed, 27 insertions, 9 deletions
diff --git a/config/initializers/forbid_sidekiq_in_transactions.rb b/config/initializers/forbid_sidekiq_in_transactions.rb
index 4eeb4ba4468..b22fb33748d 100644
--- a/config/initializers/forbid_sidekiq_in_transactions.rb
+++ b/config/initializers/forbid_sidekiq_in_transactions.rb
@@ -1,22 +1,24 @@
module Sidekiq
module Worker
+ mattr_accessor :inside_after_commit
+ self.inside_after_commit = false
+
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|
- if 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.
+ return super(*args) if Sidekiq::Worker.inside_after_commit
+ return super(*args) unless ActiveRecord::Base.connection.open_transactions > NESTING
- Schedule the worker from inside a `run_after_commit` block instead.
- MSG
- end
+ 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.
- super(*args)
+ Use an `after_commit` hook, or include `AfterCommitQueue` and use a `run_after_commit` block instead.
+ MSG
end
end
end
@@ -25,3 +27,19 @@ module Sidekiq
end
end
end
+
+module ActiveRecord
+ class Base
+ module InsideAfterCommit
+ def committed!(*)
+ inside_after_commit = Sidekiq::Worker.inside_after_commit
+ Sidekiq::Worker.inside_after_commit = true
+ super
+ ensure
+ Sidekiq::Worker.inside_after_commit = inside_after_commit
+ end
+ end
+
+ prepend InsideAfterCommit
+ end
+end