mirror of
https://github.com/discourse/discourse.git
synced 2025-05-21 18:12:32 +08:00
DEV: Update DB.after_commit
to be compatible with 'real' transactions (#11294)
Previously it matched the behavior of standard ActiveRecord after_commit callbacks. They do not work well within `joinable: false` nested transactions. Now `DB.after_commit` callbacks will only be run when the outermost transaction has been committed. Tests always run inside transactions, so this also introduces some logic to run callbacks once the test-wrapping transaction is reached.
This commit is contained in:
@ -32,7 +32,12 @@ class MiniSqlMultisiteConnection < MiniSql::Postgres::Connection
|
||||
end
|
||||
|
||||
def committed!(*)
|
||||
@callback.call
|
||||
if DB.transaction_open?
|
||||
# Nested transaction. Pass the callback to the parent
|
||||
ActiveRecord::Base.connection.add_transaction_record(self)
|
||||
else
|
||||
@callback.call
|
||||
end
|
||||
end
|
||||
|
||||
def before_committed!(*); end
|
||||
@ -42,16 +47,25 @@ class MiniSqlMultisiteConnection < MiniSql::Postgres::Connection
|
||||
end
|
||||
end
|
||||
|
||||
def transaction_open?
|
||||
ActiveRecord::Base.connection.transaction_open?
|
||||
end
|
||||
|
||||
if Rails.env.test?
|
||||
def test_transaction=(transaction)
|
||||
@test_transaction = transaction
|
||||
end
|
||||
|
||||
def transaction_open?
|
||||
ActiveRecord::Base.connection.current_transaction != @test_transaction
|
||||
end
|
||||
end
|
||||
|
||||
# Allows running arbitrary code after the current transaction has been committed.
|
||||
# Works with nested ActiveRecord transaction blocks. Useful for scheduling sidekiq jobs.
|
||||
# If not currently in a transaction, will execute immediately
|
||||
def after_commit(&blk)
|
||||
return blk.call if !ActiveRecord::Base.connection.transaction_open?
|
||||
|
||||
# In tests, everything is run inside a transaction.
|
||||
# To run immediately, check for joinable? transaction
|
||||
# This mimics core rails behavior: https://github.com/rails/rails/blob/348e142b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb#L211
|
||||
return blk.call if Rails.env.test? && !ActiveRecord::Base.connection.current_transaction.joinable?
|
||||
return blk.call if !transaction_open?
|
||||
|
||||
ActiveRecord::Base.connection.add_transaction_record(
|
||||
AfterCommitWrapper.new(&blk)
|
||||
|
Reference in New Issue
Block a user