databases icon indicating copy to clipboard operation
databases copied to clipboard

"Connection is already acquired"

Open dswillr opened this issue 4 years ago • 3 comments

 ... my code
    await database.execute(query)
  File "/usr/local/lib/python3.10/site-packages/databases/core.py", line 169, in execute
    async with self.connection() as connection:
  File "/usr/local/lib/python3.10/site-packages/databases/core.py", line 256, in __aenter__
    raise e
  File "/usr/local/lib/python3.10/site-packages/databases/core.py", line 253, in __aenter__
    await self._connection.acquire()
  File "/usr/local/lib/python3.10/site-packages/databases/backends/aiopg.py", line 105, in acquire
    assert self._connection is None, "Connection is already acquired"
AssertionError: Connection is already acquired

Based on latest master commit c8171e2f4cda988b78a7ec5c1073623f93afdd3b

dswillr avatar Feb 03 '22 15:02 dswillr

Still an issue as of 0.6.2. For me, the traceback that led to connections ending up in this bad state, in case it is of any help;

Traceback (most recent call last):
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\databases\core.py", line 169, in execute_many
    return await connection.execute_many(query, values)
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\databases\core.py", line 281, in execute_many
    await self._connection.execute_many(queries)
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\databases\backends\postgres.py", line 226, in execute_many
    await self._connection.execute(single_query, *args)
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\asyncpg\connection.py", line 319, in execute
    _, status, _ = await self._execute(
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\asyncpg\connection.py", line 1658, in _execute
    result, _ = await self.__execute(
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\asyncpg\connection.py", line 1683, in __execute
    return await self._do_execute(
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\asyncpg\connection.py", line 1730, in _do_execute
    result = await executor(stmt, None)
  File "asyncpg\protocol\protocol.pyx", line 178, in bind_execute
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\...\Documents\Python\Gamewatch\gamewatch\events.py", line 140, in __call__
    return await self.func(*args, **kwargs)
  File "C:\Users\...\Documents\Python\Gamewatch\plugins\logger.py", line 174, in save_logs
    await get_db().execute_many(LogsTable.insert(), values=[
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\databases\core.py", line 168, in execute_many
    async with self.connection() as connection:
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\databases\core.py", line 243, in __aexit__
    await self._connection.release()
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\databases\backends\postgres.py", line 175, in release
    self._connection = await self._database._pool.release(self._connection)
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\lib\site-packages\asyncpg\pool.py", line 879, in release
    return await asyncio.shield(ch.release(timeout))
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\Lib\asyncio\tasks.py", line 456, in wait_for
    return fut.result()
asyncio.exceptions.CancelledError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\...\Documents\Python\Gamewatch\gamewatch\events.py", line 173, in invoke
    await asyncio.wait_for(self.__call__(sf, event, *args, **kwargs), timeout=self.timeout)
  File "C:\Users\...\AppData\Local\Programs\Python\Python310\Lib\asyncio\tasks.py", line 458, in wait_for
    raise exceptions.TimeoutError() from exc
asyncio.exceptions.TimeoutError

timraay avatar Jul 03 '23 11:07 timraay

@timraay is this resolved by https://github.com/encode/databases/pull/546 ?

zanieb avatar Jul 13 '23 20:07 zanieb

In short, no, I would assume it is not. But I couldn't get consistent reproduction steps working to test it out either. Why the issue occurs is rather easily explainable however.

What is happening is that the task responsible for releasing the connection gets cancelled, which in turn raises an exception before self._connection can be set to None.

What #461 does is simply swap the two around; First it sets self._connection to None, then it releases the (old) connection, so that if the task gets canceled, it has at least reset the connection property.

I tried to reproduce this with a simple wait_for, but getting it to time out exactly during the release of the connection is quite rare.

timraay avatar Jul 16 '23 22:07 timraay