@@ -87,7 +87,7 @@ def dirty!; end
87
87
88
88
class Transaction # :nodoc:
89
89
attr_reader :connection , :state , :savepoint_name , :isolation_level
90
- attr_accessor :written
90
+ attr_accessor :written , :written_indirectly
91
91
92
92
def initialize ( connection , isolation : nil , joinable : true , run_commit_callbacks : false )
93
93
@connection = connection
@@ -384,6 +384,10 @@ def commit_transaction
384
384
385
385
dirty_current_transaction if transaction . dirty?
386
386
387
+ if current_transaction . open?
388
+ current_transaction . written_indirectly ||= transaction . written || transaction . written_indirectly
389
+ end
390
+
387
391
transaction . commit
388
392
transaction . commit_records
389
393
end
@@ -420,19 +424,37 @@ def within_new_transaction(isolation: nil, joinable: true)
420
424
# @connection still holds an open or invalid transaction, so we must not
421
425
# put it back in the pool for reuse.
422
426
@connection . throw_away! unless transaction . state . rolledback?
423
- elsif Thread . current . status == "aborting" || ( !completed && transaction . written )
424
- # The transaction is still open but the block returned earlier.
425
- #
426
- # The block could return early because of a timeout or because the thread is aborting,
427
- # so we are rolling back to make sure the timeout didn't caused the transaction to be
428
- # committed incompletely.
429
- rollback_transaction
430
427
else
431
- begin
432
- commit_transaction
433
- rescue Exception
434
- rollback_transaction ( transaction ) unless transaction . state . completed?
435
- raise
428
+ if Thread . current . status == "aborting"
429
+ rollback_transaction
430
+ elsif !completed && transaction . written
431
+ # This was deprecated in 6.1, and has now changed to a rollback
432
+ rollback_transaction
433
+ elsif !completed && !transaction . written_indirectly
434
+ # This was a silent commit in 6.1, but now becomes a rollback; we skipped
435
+ # the warning because (having not been written) the change generally won't
436
+ # have any effect
437
+ rollback_transaction
438
+ else
439
+ if !completed && transaction . written_indirectly
440
+ # This is the case that was missed in the 6.1 deprecation, so we have to
441
+ # do it now
442
+ ActiveSupport ::Deprecation . warn ( <<~EOW )
443
+ Using `return`, `break` or `throw` to exit a transaction block is
444
+ deprecated without replacement. If the `throw` came from
445
+ `Timeout.timeout(duration)`, pass an exception class as a second
446
+ argument so it doesn't use `throw` to abort its block. This results
447
+ in the transaction being committed, but in the next release of Rails
448
+ it will rollback.
449
+ EOW
450
+ end
451
+
452
+ begin
453
+ commit_transaction
454
+ rescue Exception
455
+ rollback_transaction ( transaction ) unless transaction . state . completed?
456
+ raise
457
+ end
436
458
end
437
459
end
438
460
end
0 commit comments