Describe the bug
When there are multiple after_commit callbacks within nested transaction and an exception occurs, the last after_commit callback is not fired while others are.
To Reproduce
class Test < ApplicationRecord
include AASM
aasm column: :state, timestamp: false do
state :initial, initial: true
state :submitted, :accepted, :ready, :completed
event :submit, after: :after_submit, after_commit: :after_commit_submit do
transitions from: :initial, to: :submitted
end
event :accept, after: :after_accept, after_commit: :after_commit_accept do
transitions from: :submitted, to: :accepted
end
event :ready, after: :after_ready, after_commit: :after_commit_ready do
transitions from: :accepted, to: :ready
end
event :complete, after: :after_complete, after_commit: :after_commit_complete do
transitions from: :ready, to: :completed
end
end
def after_submit
ap "AFTER_SUBMIT"
accept!
end
def after_commit_submit
ap "AFTER_COMMIT_SUBMIT"
end
def after_accept
ap "AFTER_ACCEPT"
ready!
end
def after_commit_accept
ap "AFTER_COMMIT_ACCEPT"
end
def after_ready
ap "AFTER_READY"
complete!
end
def after_commit_ready
ap "AFTER_COMMIT_READY"
end
def after_complete
ap "AFTER_COMPLETE"
end
def after_commit_complete
ap "AFTER_COMMIT_COMPLETE"
raise "Oh my god, something's wrong!"
end
end
when running Test.create!.submit!, after_commit_submit won't get called.
"AFTER_SUBMIT"
"AFTER_ACCEPT"
"AFTER_READY"
"AFTER_COMPLETE" --> innermost transaction is commited
"AFTER_COMMIT_COMPLETE"
"AFTER_COMMIT_READY"
"AFTER_COMMIT_ACCEPT"
# where is "AFTER_COMMIT_SUBMIT"? --> outermost callback not executed
Expected behavior
"AFTER_SUBMIT"
"AFTER_ACCEPT"
"AFTER_READY"
"AFTER_COMPLETE"
"AFTER_COMMIT_COMPLETE"
"AFTER_COMMIT_READY"
"AFTER_COMMIT_ACCEPT"
"AFTER_COMMIT_SUBMIT"
Screenshots
If applicable, add screenshots to help explain your problem.
Additional context
The root cause of this problem is that the first submit!'s aasm_transaction raises an exception originated from nested transaction (after_commit_complete) and fails to call aasm_execute_after_commit in the code below.
|
begin |
|
success = if options[:persist] && use_transactions?(state_machine_name) |
|
aasm_transaction(requires_new?(state_machine_name), requires_lock?(state_machine_name)) do |
|
super |
|
end |
|
else |
|
super |
|
end |
|
|
|
if success && !(event.options.keys & [:after_commit, :after_all_commits]).empty? |
|
aasm_execute_after_commit do |
|
event.fire_callbacks(:after_commit, self, *args) |
|
event.fire_global_callbacks(:after_all_commits, self, *args) |
|
end |
|
end |
|
|
|
success |
|
ensure |
|
event.fire_callbacks(:after_transaction, self, *args) |
|
event.fire_global_callbacks(:after_all_transactions, self, *args) |
|
end |
If everyone sees this as an issue to be handled, I will work on a PR.
cc. @njw1204
Describe the bug
When there are multiple
after_commitcallbacks within nested transaction and an exception occurs, the lastafter_commitcallback is not fired while others are.To Reproduce
when running
Test.create!.submit!,after_commit_submitwon't get called.Expected behavior
Screenshots
If applicable, add screenshots to help explain your problem.
Additional context
The root cause of this problem is that the first
submit!'saasm_transactionraises an exception originated from nested transaction (after_commit_complete) and fails to callaasm_execute_after_commitin the code below.aasm/lib/aasm/persistence/orm.rb
Lines 129 to 149 in 666ef70
If everyone sees this as an issue to be handled, I will work on a PR.
cc. @njw1204