DEV: Allow DB.after_commit to be used outside of a transaction

In this case, it will execute the given block immediately
This commit is contained in:
David Taylor 2020-05-01 16:37:43 +01:00
parent 3877ef2cfa
commit 5901717531
No known key found for this signature in database
GPG Key ID: 46904C18B1D3F434
2 changed files with 22 additions and 1 deletions

View File

@ -43,8 +43,16 @@ class MiniSqlMultisiteConnection < MiniSql::Postgres::Connection
end
# Allows running arbitrary code after the current transaction has been committed.
# Works even with nested transactions. Useful for scheduling sidekiq jobs.
# 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?
ActiveRecord::Base.connection.add_transaction_record(
AfterCommitWrapper.new(&blk)
)

View File

@ -49,6 +49,19 @@ describe MiniSqlMultisiteConnection do
expect(outputString).to eq("123")
end
it "runs immediately if there is no transaction" do
outputString = "1"
DB.after_commit do
outputString += "2"
end
outputString += "3"
expect(outputString).to eq("123")
end
end
end