MagicStack / MagicStack/asyncpg
Terminate function does not work when a stream is cancelled prematurely when in an anyio task group
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 8.1k
- Forks
- 468
- PR merge metrics
- No merged PRs in 30d
Description
* **asyncpg version**: 0.29.0
* **PostgreSQL version**: 14.10
* **Do you use a PostgreSQL SaaS? If so, which? Can you reproduce
the issue with a local PostgreSQL install?**: Yes, I can reproduce it locally
* **Python version**: 3.12
* **Platform**: linux and Mac OS
* **Do you use pgbouncer?**: No
* **Did you install asyncpg with pip?**: Yes
* **If you built asyncpg locally, which version of Cython did you use?**: n/a
* **Can the issue be reproduced under both asyncio and
[uvloop](https://github.com/magicstack/uvloop)?**: No, the issue is not producible with asyncio only with anyio
Hi, I have a Fast API application that uses `SQLAlchemy` and `asyncpg`. I opened up a discussion on the SQLAlchemy page [here (full discussion)](https://github.com/sqlalchemy/sqlalchemy/discussions/11128#discussion-6343846) reporting a major problem that affected my application after an update they released.
To summarize the problem and what we concluded in that discussion,
I asynchronously stream data from my API to a client using the `starlette` `StreamingResponse` class which takes advantage of`anyio` under the hood. For some reason when the `anyio` `task group` gets cancelled before the stream is finished the `asyncpg` `terminate` function does not terminate the connection when the `close` function is used first, leaving it stuck in an `idle in transaction` state. This causes connections to run up eventually stopping other applications from creating new connections.
With some help from the SQLAlchemy folks, after some time working through the problem we were able to reproduce a small example of my problem using only the `asyncpg` and `anyio` libraries [here (Example of problem)](https://github.com/sqlalchemy/sqlalchemy/discussions/11128#discussioncomment-9539469)
Any help resolving this issue would be greatly appreciated! If you need any more info from me please do not hesitate to message back
Thanks in advance!
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The minimal reproduction is linked in the SQLAlchemy discussion; start by running it with the reported asyncpg and anyio setup and trace the close-then-terminate path during task-group cancellation. Use asyncpg's terminate and close entry points to locate the connection lifecycle handling. Done means a cancelled stream no longer leaves the connection in an idle in transaction state.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fastapi, postgresql, python
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100