E40F The outermost `after_commit` callback not executed upon exception within nested transaction · Issue #854 · aasm/aasm · GitHub
[go: up one dir, main page]

Skip to content

The outermost after_commit callback not executed upon exception within nested transaction #854

@kevink1103

Description

@kevink1103

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0