Move into MiniSQLMultisiteConnection, and add test for rollback

This commit is contained in:
David Taylor 2018-07-24 09:41:55 +01:00
parent d7b5a374c2
commit 20a21b1240
5 changed files with 74 additions and 71 deletions

View File

@ -1,38 +0,0 @@
##
# Allows running arbitrary code after the current transaction has been committed.
# Works even with nested transactions. Useful for scheduling sidekiq jobs.
# Slightly simplified version of https://dev.to/evilmartians/rails-aftercommit-everywhere--4j9g
# Usage:
# Topic.transaction do
# puts "Some work before scheduling"
# TransactionHelper.after_commit do
# puts "Running after commit"
# end
# puts "Some work after scheduling"
# end
#
# Produces:
# > Some work before scheduling
# > Some work after scheduling
# > Running after commit
module TransactionHelper
class AfterCommitWrapper
def initialize
@callback = Proc.new
end
def committed!(*)
@callback.call
end
def before_committed!(*); end
def rolledback!(*); end
end
def self.after_commit(&blk)
ActiveRecord::Base.connection.add_transaction_record(
AfterCommitWrapper.new(&blk)
)
end
end

View File

@ -686,7 +686,7 @@ class Topic < ActiveRecord::Base
if post = self.ordered_posts.first
notified_user_ids = [post.user_id, post.last_editor_id].uniq
TransactionHelper.after_commit do
DB.after_commit do
Jobs.enqueue(:notify_category_change, post_id: post.id, notified_user_ids: notified_user_ids)
end
end

View File

@ -23,6 +23,27 @@ class MiniSqlMultisiteConnection < MiniSql::Connection
end
end
class AfterCommitWrapper
def initialize
@callback = Proc.new
end
def committed!(*)
@callback.call
end
def before_committed!(*); end
def rolledback!(*); end
end
# Allows running arbitrary code after the current transaction has been committed.
# Works even with nested transactions. Useful for scheduling sidekiq jobs.
def after_commit(&blk)
ActiveRecord::Base.connection.add_transaction_record(
AfterCommitWrapper.new(&blk)
)
end
def self.instance
new(nil, param_encoder: ParamEncoder.new)
end

View File

@ -1,32 +0,0 @@
require 'rails_helper'
describe TransactionHelper do
it "runs callbacks after outermost transaction is committed" do
outputString = "1"
# Main transaction
ActiveRecord::Base.transaction do
outputString += "2"
# Nested transaction
ActiveRecord::Base.transaction do
outputString += "3"
TransactionHelper.after_commit do
outputString += "6"
end
outputString += "4"
end
TransactionHelper.after_commit do
outputString += "7"
end
outputString += "5"
end
expect(outputString).to eq("1234567")
end
end

View File

@ -0,0 +1,52 @@
require 'rails_helper'
describe MiniSqlMultisiteConnection do
describe "after_commit" do
it "runs callbacks after outermost transaction is committed" do
outputString = "1"
# Main transaction
ActiveRecord::Base.transaction do
outputString += "2"
# Nested transaction
ActiveRecord::Base.transaction do
outputString += "3"
DB.after_commit do
outputString += "6"
end
outputString += "4"
end
DB.after_commit do
outputString += "7"
end
outputString += "5"
end
expect(outputString).to eq("1234567")
end
it "does not run if the transaction is rolled back" do
outputString = "1"
ActiveRecord::Base.transaction do
outputString += "2"
DB.after_commit do
outputString += "4"
end
outputString += "3"
raise ActiveRecord::Rollback
end
expect(outputString).to eq("123")
end
end
end