[Stefan H. Holek]
> I found that I now need to explicitly abort (or commit) the transaction
> before closing a connection,

Only if changes are still pending to objects loaded from that connection.

>>> import ZODB
>>> from ZODB.FileStorage import FileStorage
>>> st = FileStorage("Temp.fs")
>>> db = ZODB.DB(st)
>>> cn = db.open()
>>> rt = cn.root()
>>> rt['a'] = 1
>>> get_transaction().commit()

No problem closing here:  all pending changes were committed.

>>> cn.close()

Or here:  no _changes_ are pending:

>>> cn = db.open()
>>> rt = cn.root()
>>> rt['a']
>>> cn.close()

But problem here:

>>> cn = db.open()
>>> rt = cn.root()
>>> rt['b'] = 1
>>> cn.close()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "ZODB\Connection.py", line 306, in close
    raise ConnectionStateError("Cannot close a connection joined to "
ZODB.POSException.ConnectionStateError: Cannot close a connection joined to
a transaction

> as otherwise the connection pool would not be freed?

No, it's because it's impossible to guess what you intended when you close a
connection with changes pending.  ZODB used to return the connection to the
pool with the changes still pending.  Connections are reused.  The next time
that connection got used, it came with pending changes DB.open()'s caller
knew nothing about.  Horrible, hard-to-track-down, bugs were the result.
Thanks to cooperating bugs in Zope 2.7.2, POSKeyErrors also resulted.

> Is this a recent change? I am pretty sure this was not always necessary
> but I may be wrong. Zope 2.7.6 here.

Read ZODB's news for 3.2.4 release candidate 1 (07-Sep-2004):


    New exception ConnectionStateError is raised ...

In a real sense, it was always necessary, but not enforced before ZODB 3.2.4
(== Zope 2.7.3).

For more information about ZODB, see the ZODB Wiki:

ZODB-Dev mailing list  -  ZODB-Dev@zope.org

Reply via email to