Skip to content

Commit

Permalink
Fixed: newTransaction was being called in open even in explicit-trans…
Browse files Browse the repository at this point in the history
…action mode.
  • Loading branch information
Jim Fulton committed Feb 8, 2017
1 parent 48d96cc commit 8c4c5a6
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 23 deletions.
35 changes: 19 additions & 16 deletions src/ZODB/Connection.py
Expand Up @@ -902,22 +902,25 @@ def open(self, transaction_manager=None, delegate=True):
# New code is in place. Start a new cache.
self._resetCache()

# This newTransaction is to deal with some pathalogical cases:
#
# a) Someone opens a connection when a transaction isn't
# active and proceeeds without calling begin on a
# transaction manager. We initialize the transaction for
# the connection, but we don't do a storage sync, since
# this will be done if a well-nehaved application calls
# begin, and we don't want to penalize well-behaved
# transactions by syncing twice, as storage syncs might be
# expensive.
# b) Lots of tests assume that connection transaction
# information is set on open.
#
# Fortunately, this is a cheap operation. It doesn't really
# cost much, if anything.
self.newTransaction(None, False)
if not self.explicit_transactions:
# This newTransaction is to deal with some pathalogical cases:
#
# a) Someone opens a connection when a transaction isn't
# active and proceeeds without calling begin on a
# transaction manager. We initialize the transaction for
# the connection, but we don't do a storage sync, since
# this will be done if a well-nehaved application calls
# begin, and we don't want to penalize well-behaved
# transactions by syncing twice, as storage syncs might be
# expensive.
# b) Lots of tests assume that connection transaction
# information is set on open.
#
# Fortunately, this is a cheap operation. It doesn't
# really cost much, if anything. Well, except for
# RelStorage, in which case it adds a server round
# trip.
self.newTransaction(None, False)

transaction_manager.registerSynch(self)

Expand Down
32 changes: 25 additions & 7 deletions src/ZODB/tests/testConnection.py
Expand Up @@ -1323,16 +1323,33 @@ def test_storage_afterCompletionCalled(self):
db.close()

def test_explicit_transactions_no_newTransactuon_on_afterCompletion(self):
db = ZODB.DB(None)
syncs = []
from .MVCCMappingStorage import MVCCMappingStorage
storage = MVCCMappingStorage()

new_instance = storage.new_instance
def new_instance2():
inst = new_instance()
sync = inst.sync
def sync2(*args):
sync()
syncs.append(1)
inst.sync = sync2
return inst

storage.new_instance = new_instance2

db = ZODB.DB(storage)
del syncs[:] # Need to do this to clear effect of getting the
# root object

# We don't want to depend on latest transaction package, so
# just set attr for test:
tm = transaction.TransactionManager()
tm.explicit = True

conn = db.open(tm)
syncs = []
conn._storage.sync = syncs.append
self.assertEqual(len(syncs), 0)
conn.transaction_manager.begin()
self.assertEqual(len(syncs), 1)
conn.transaction_manager.commit()
Expand All @@ -1342,17 +1359,18 @@ def test_explicit_transactions_no_newTransactuon_on_afterCompletion(self):
conn.transaction_manager.abort()
self.assertEqual(len(syncs), 2)
conn.close()
db.close()
self.assertEqual(len(syncs), 2)

# For reference, in non-explicit mode:
db = ZODB.DB(None)
conn = db.open()
self.assertEqual(len(syncs), 3)
conn._storage.sync = syncs.append
conn.transaction_manager.begin()
self.assertEqual(len(syncs), 3)
conn.transaction_manager.abort()
self.assertEqual(len(syncs), 4)
conn.transaction_manager.abort()
self.assertEqual(len(syncs), 5)
conn.close()

db.close()

class StubDatabase:
Expand Down

0 comments on commit 8c4c5a6

Please sign in to comment.