with (yield from engine) as conn:
trans = yield from conn.begin()
try:
yield from conn.execute("insert into x (a, b) values (1, 2)")
except Exception:
yield from trans.rollback()
else:
yield from trans.commit()
with (yield from engine) as conn:
trans = yield from conn.begin()
# note this sleep() call
yield from asyncio.sleep(1)
try:
yield from conn.execute("insert into x (a, b) values (1, 2)")
except Exception:
yield from trans.rollback()
else:
yield from trans.commit()
Cannot release a connection with not finished transactionTraceback (most recent call last): File "example_server.py", line 56, in create_tables yield from asyncio.sleep(1) File "/usr/local/lib/python3.5/asyncio/tasks.py", line 495, in sleep return (yield from future) File "/usr/local/lib/python3.5/asyncio/futures.py", line 385, in __iter__ yield self # This tells Task to wait for completion. File "/usr/local/lib/python3.5/asyncio/tasks.py", line 288, in _wakeup value = future.result() File "/usr/local/lib/python3.5/asyncio/futures.py", line 266, in result raise CancelledErrorconcurrent.futures._base.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "example_server.py", line 67, in create_tables yield from trans.commit() File "/home/legat/Projects/bugs_testing/aio_bugs/env/lib/python3.5/site-packages/aiomysql/sa/engine.py", line 189, in __exit__ self._engine.release(self._conn) File "/home/legat/Projects/bugs_testing/aio_bugs/env/lib/python3.5/site-packages/aiomysql/sa/engine.py", line 117, in release raise InvalidRequestError("Cannot release a connection with "aiomysql.sa.exc.InvalidRequestError: Cannot release a connection with not finished transactionwith (yield from engine) as conn:
try:
trans = yield from conn.begin()
try:
yield from conn.execute("insert into x (a, b) values (1, 2)")
except Exception:
yield from trans.rollback()
else:
yield from trans.commit()
except CancelledError:
conn._transaction = None
trans = yield from conn.begin()@asyncio.coroutinedef begin(self): if self._transaction is None: self._transaction = RootTransaction(self) yield from self._begin_impl() ...def release(self, conn): if conn.in_transaction: raise InvalidRequestError("Cannot release a connection with " "not finished transaction") ...@propertydef in_transaction(self): return self._transaction is not None and self._transaction.is_active
with (yield from engine) as conn:
trans = conn.transaction()
try:
yield from trans.begin()trans = yield from conn.begin() # outermost transactiontrans2 = yield from conn.begin() # "nested"yield from trans2.commit() # does nothingyield from trans.commit() # actually commitsself._transaction = RootTransaction(self) yield from self._begin_impl()
This two lines should be
yield from self._begin_impl()
self._transaction = RootTransaction(self)
So in case of CancelledError, connection could return to the pool, but even if connection did moved to transaction state despite exception, connection pool will drop it.
https://github.com/aio-libs/aiomysql/blob/master/aiomysql/pool.py#L194-L198