On Friday, 10 January 2014 08:06:16 UTC-8, Michael Bayer wrote: maybe. I was thinking, is the Session really doing the right thing here by not getting involved, but I think yeah that still might be appropriate. so we’d need to carry along some extra information about the transaction with the connection so that do_rollback() and do_commit() can pick up on that.
or maybe session.close() needs to do some bookkeeping with the SessionTransaction. not sure.
The call stack here is:
-> session.close() sqlalchemy/orm/session.py(999)close() -> transaction.close() sqlalchemy/orm/session.py(437)close() -> connection.close() sqlalchemy/engine/base.py(583)close() -> conn.close() sqlalchemy/pool.py(579)close() -> self.checkin() sqlalchemy/pool.py(506)checkin() -> self._pool, None, self._echo, fairy=self) sqlalchemy/pool.py(432)_finalize_fairy() -> pool._dialect.do_rollback(fairy)
The tpc state (xid, is_prepared) is held on the TwoPhaseTransaction object, referenced (self.__transaction) by the engine Connection object which calls conn.close(). I don't think SessionTransaction need be involved here, but perhaps the engine Connection / Transaction should. Some options are:
In engine Connection.close(), when self.transaction.is_active pass down xid, is_prepared to the _ConnectionFairy. That would imply muddying the DBAPI Connection contract of the engine Connection.connection.
Make the engine Transaction aware of the configured reset_on_return behaviour so that Transaction.close() can either rollback or commit. Connection.close() could then call Transaction.close().
Keep track of xid, is_prepared on the pool's connection_record.