Permalink
Browse files

Fixed that nested transactions now work by letting the outer most tra…

…nsaction 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
  • Loading branch information...
1 parent 58f2bd0 commit 44819b47179936492c093811ed0f625ce6e029a3 @dhh dhh committed Dec 22, 2004
@@ -1,5 +1,9 @@
*SVN*
+* 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.
+
* Fixed validates_{confirmation,acceptance}_of to only happen when the virtual attributes are not nil #348 [dpiddy@gmail.com]
* Added a require_association hook on const_missing that makes it possible to use any model class without requiring it first. This makes STI look like:
@@ -298,16 +298,16 @@ def reset_runtime # :nodoc:
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
@@ -77,21 +77,27 @@ def self.append_features(base)
# 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
rescue Exception => object_transaction_rollback
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 @@ def transaction(*objects, &block)
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
@@ -84,7 +84,7 @@ def test_callback_rollback_in_save
end
end
- def xtest_nested_explicit_transactions
+ def test_nested_explicit_transactions
Topic.transaction do
Topic.transaction do
@first.approved = 1

0 comments on commit 44819b4

Please sign in to comment.