Fix(PSRE-4513): Address Rails deprecation: use of exit statements in transaction#2
Open
aamirsahmad wants to merge 1 commit into
Open
Fix(PSRE-4513): Address Rails deprecation: use of exit statements in transaction#2aamirsahmad wants to merge 1 commit into
aamirsahmad wants to merge 1 commit into
Conversation
411e64b to
b1323c8
Compare
paul-ljh
approved these changes
May 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
https://stackadapt.atlassian.net/browse/PSRE-4513
sa-web integration: https://github.com/StackAdapt/stackadapt-web/pull/39398
Summary
#haltand#succeedpreviously usedthrow :abortto short-circuit out of#execute. When called from inside anActiveRecord::Base.transactionblock, thatthrowcrosses the transaction boundary, which Rails has deprecated:This change replaces the
throw :abortmechanism with a raised exception only whenhalt/succeedare called from inside#execute— the only context where a user transaction could be on the stack. From inside before/after callbacks, the existingthrow :abortis preserved so ActiveSupport's callback-chain halting (and the "after callbacks still run after halt-in-before" semantics) is unchanged.What changed
ActiveOperation::Halted,ActiveOperation::Succeeded). They inherit fromExceptionrather thanStandardErrorso consumer code's barerescuedoes not swallow them.Base#performtracks@in_executeand rescues the new exceptions around theexecutecall.Base#haltandBase#succeedraise the appropriate exception when@in_executeis true, otherwise fall back tothrow :abort.Behavioral impact on consumers
haltinside a transaction: now causes a rollback (previously committed with a deprecation warning). This matches the documented intent ofhalt(failure path).succeedinside a transaction: now causes a rollback. This is a behavior change for any caller that relied onsucceed-inside-transaction implicitly committing. There is no gem-only fix — Rails' rule is "the only way to commit is to fall off the end of the block." Call sites that need a commit must callsucceedafter the transaction block. See the companion app PR for the affected sites.haltedcallback compensating for the throw-commits bug (e.g. by destroying records that were "saved" before the throw) may need that callback removed — rollback now handles the cleanup automatically. See the companion app PR for one example.throw :abortcontinues to drive AS's callback halting.Thread safety
Profile is unchanged from the pre-patch gem:
@in_executeis a plain instance variable on instance methods, scoped to a single operation instance. The gem's idiom is one instance per call, matching the existing pattern (self.state = …,@output = …were already mutated during#execute).Halted/Succeededclasses are immutable class definitions, evaluated once at load.Thread.current).raise Haltedin one thread cannot be caught by another'srescue.rubocop --only ThreadSafetyon the patched gem reports zero new offenses (the 6 pre-existing offenses on@inputs/@operationsclass instance variables in the DSL are untouched by this patch).Tests
All 112 existing gem specs pass unchanged — the existing
control_flow_spec.rbcovershaltfrom before callbacks, in-execute halts, and the after-callback flow, all of which exercise both code paths.Test plan
bundle exec rspec) — 112 examples, 0 failuresrubocop --only ThreadSafety— no new offenses introduced