1
0
Fork 0
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:
Aaron Patterson 2012-08-28 11:59:45 -07:00
parent f24a5517e9
commit c24c885209
4 changed files with 55 additions and 12 deletions

View file

@ -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

View file

@ -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)

View file

@ -393,6 +393,7 @@ module ActiveRecord
@marked_for_destruction = false
@new_record = true
@mass_assignment_options = nil
@txn = nil
@_start_transaction_state = {}
end
end

View file

@ -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