mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
create a transaction object and point AR objects at that object during a
transaction.
This commit is contained in:
parent
f24a5517e9
commit
c24c885209
4 changed files with 55 additions and 12 deletions
|
@ -193,7 +193,8 @@ module ActiveRecord
|
|||
rescue Exception => database_transaction_rollback
|
||||
if transaction_open && !outside_transaction?
|
||||
transaction_open = false
|
||||
decrement_open_transactions
|
||||
txn = decrement_open_transactions
|
||||
txn.aborted!
|
||||
if open_transactions == 0
|
||||
rollback_db_transaction
|
||||
rollback_transaction_records(true)
|
||||
|
@ -208,9 +209,10 @@ module ActiveRecord
|
|||
@transaction_joinable = last_transaction_joinable
|
||||
|
||||
if outside_transaction?
|
||||
@open_transactions = 0
|
||||
@current_transaction = nil
|
||||
elsif transaction_open
|
||||
decrement_open_transactions
|
||||
txn = decrement_open_transactions
|
||||
txn.committed!
|
||||
begin
|
||||
if open_transactions == 0
|
||||
commit_db_transaction
|
||||
|
|
|
@ -69,6 +69,7 @@ module ActiveRecord
|
|||
@last_use = false
|
||||
@logger = logger
|
||||
@open_transactions = 0
|
||||
@current_transaction = nil
|
||||
@pool = pool
|
||||
@query_cache = Hash.new { |h,sql| h[sql] = {} }
|
||||
@query_cache_enabled = false
|
||||
|
@ -236,14 +237,30 @@ module ActiveRecord
|
|||
@connection
|
||||
end
|
||||
|
||||
attr_reader :open_transactions
|
||||
def open_transactions
|
||||
count = 0
|
||||
txn = current_transaction
|
||||
|
||||
while txn
|
||||
count += 1
|
||||
txn = txn.next
|
||||
end
|
||||
|
||||
count
|
||||
end
|
||||
|
||||
attr_reader :current_transaction
|
||||
|
||||
def increment_open_transactions
|
||||
@open_transactions += 1
|
||||
@current_transaction = Transaction.new(current_transaction)
|
||||
end
|
||||
|
||||
def decrement_open_transactions
|
||||
@open_transactions -= 1
|
||||
return unless current_transaction
|
||||
|
||||
txn = current_transaction
|
||||
@current_transaction = txn.next
|
||||
txn
|
||||
end
|
||||
|
||||
def transaction_joinable=(joinable)
|
||||
|
|
|
@ -393,6 +393,7 @@ module ActiveRecord
|
|||
@marked_for_destruction = false
|
||||
@new_record = true
|
||||
@mass_assignment_options = nil
|
||||
@txn = nil
|
||||
@_start_transaction_state = {}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,32 @@
|
|||
require 'thread'
|
||||
|
||||
module ActiveRecord
|
||||
class Transaction
|
||||
attr_reader :next
|
||||
|
||||
def initialize(txn = nil)
|
||||
@next = txn
|
||||
@committed = false
|
||||
@aborted = false
|
||||
end
|
||||
|
||||
def committed!
|
||||
@committed = true
|
||||
end
|
||||
|
||||
def aborted!
|
||||
@aborted = true
|
||||
end
|
||||
|
||||
def committed?
|
||||
@committed
|
||||
end
|
||||
|
||||
def aborted?
|
||||
@aborted
|
||||
end
|
||||
end
|
||||
|
||||
# See ActiveRecord::Transactions::ClassMethods for documentation.
|
||||
module Transactions
|
||||
extend ActiveSupport::Concern
|
||||
|
@ -307,11 +333,11 @@ module ActiveRecord
|
|||
def with_transaction_returning_status
|
||||
status = nil
|
||||
self.class.transaction do
|
||||
@txn = self.class.connection.current_transaction
|
||||
add_to_transaction
|
||||
begin
|
||||
status = yield
|
||||
rescue ActiveRecord::Rollback
|
||||
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
|
||||
status = nil
|
||||
end
|
||||
|
||||
|
@ -327,20 +353,17 @@ module ActiveRecord
|
|||
@_start_transaction_state[:id] = id if has_attribute?(self.class.primary_key)
|
||||
@_start_transaction_state[:new_record] = @new_record
|
||||
@_start_transaction_state[:destroyed] = @destroyed
|
||||
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
|
||||
end
|
||||
|
||||
# Clear the new record state and id of a record.
|
||||
def clear_transaction_record_state #:nodoc:
|
||||
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
|
||||
@_start_transaction_state.clear if @_start_transaction_state[:level] < 1
|
||||
@_start_transaction_state.clear if @txn.committed?
|
||||
end
|
||||
|
||||
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
||||
def restore_transaction_record_state(force = false) #:nodoc:
|
||||
unless @_start_transaction_state.empty?
|
||||
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
|
||||
if @_start_transaction_state[:level] < 1 || force
|
||||
if @txn.aborted? || force
|
||||
restore_state = @_start_transaction_state
|
||||
was_frozen = @attributes.frozen?
|
||||
@attributes = @attributes.dup if was_frozen
|
||||
|
|
Loading…
Reference in a new issue