diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2004-12-22 00:48:24 +0000 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2004-12-22 00:48:24 +0000 |
commit | 44819b47179936492c093811ed0f625ce6e029a3 (patch) | |
tree | f6653b9e9a9c8fd41dab1cc40f78e4e4d565b65c /activerecord/lib/active_record | |
parent | 58f2bd0cfc1713ee3ed519d6b75bbfa386c131c3 (diff) | |
download | rails-44819b47179936492c093811ed0f625ce6e029a3.tar.gz rails-44819b47179936492c093811ed0f625ce6e029a3.tar.bz2 rails-44819b47179936492c093811ed0f625ce6e029a3.zip |
Fixed that nested transactions now work by letting the outer most transaction have the responsibilty of starting and rolling back the transaction. If any of the inner transactions swallow the exception raised, though, the transaction will not be rolled back. So always let the transaction bubble up even when you've dealt with local issues. Closes #231 and #340.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@242 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'activerecord/lib/active_record')
-rwxr-xr-x | activerecord/lib/active_record/connection_adapters/abstract_adapter.rb | 8 | ||||
-rw-r--r-- | activerecord/lib/active_record/transactions.rb | 24 |
2 files changed, 15 insertions, 17 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index b521a0fdf8..d41356ffa4 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -298,16 +298,16 @@ module ActiveRecord end # Wrap a block in a transaction. Returns result of block. - def transaction + def transaction(start_db_transaction = true) begin if block_given? - begin_db_transaction + begin_db_transaction if start_db_transaction result = yield - commit_db_transaction + commit_db_transaction if start_db_transaction result end rescue Exception => database_transaction_rollback - rollback_db_transaction + rollback_db_transaction if start_db_transaction raise end end diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index d440e74346..16c56c58f0 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -77,13 +77,17 @@ module ActiveRecord # Tribute: Object-level transactions are implemented by Transaction::Simple by Austin Ziegler. module ClassMethods def transaction(*objects, &block) - TRANSACTION_MUTEX.lock + TRANSACTION_MUTEX.synchronize do + Thread.current['open_transactions'] ||= 0 + Thread.current['start_db_transaction'] = (Thread.current['open_transactions'] == 0) + Thread.current['open_transactions'] += 1 + end begin objects.each { |o| o.extend(Transaction::Simple) } objects.each { |o| o.start_transaction } - result = connection.transaction(&block) + result = connection.transaction(Thread.current['start_db_transaction'], &block) objects.each { |o| o.commit_transaction } return result @@ -91,7 +95,9 @@ module ActiveRecord objects.each { |o| o.abort_transaction } raise ensure - TRANSACTION_MUTEX.unlock + TRANSACTION_MUTEX.synchronize do + Thread.current['open_transactions'] -= 1 + end end end end @@ -101,19 +107,11 @@ module ActiveRecord end def destroy_with_transactions #:nodoc: - if TRANSACTION_MUTEX.locked? - destroy_without_transactions - else - transaction { destroy_without_transactions } - end + transaction { destroy_without_transactions } end def save_with_transactions(perform_validation = true) #:nodoc: - if TRANSACTION_MUTEX.locked? - save_without_transactions(perform_validation) - else - transaction { save_without_transactions(perform_validation) } - end + transaction { save_without_transactions(perform_validation) } end end end |