Skip to content

Cannot release connection after query is canceled. #18

Open
@thomas-maschler

Description

@thomas-maschler

Expected Behavior

When canceling query, connection should be released back into pool.

Actual Behavior

After canceling query (and catching errors in code) gino_startlette stills throws error asyncpg.exceptions.QueryCanceledError when trying to release connection.

Steps to Reproduce the Problem

from asyncpg import QueryCanceledError
from fastapi import FastAPI
from gino_starlette import Gino

app = FastAPI()

db = Gino(
    app,
    kwargs=dict(server_settings=dict(statement_timeout="1")), # cancel query after 1 ms
)


@app.get("/")
async def root():
    message = "success"
    try:
        await db.scalar("SELECT 1")
    except QueryCanceledError:
        message = "timeout"

    return {"message": message}

When called, Endpoint will correctly return {"message": "timeout"} but app will still throw QueryCanceledError

Traceback (most recent call last):
  File "****/site-packages/uvicorn/protocols/http/httptools_impl.py", line 385, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "****/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "****/site-packages/fastapi/applications.py", line 181, in __call__
    await super().__call__(scope, receive, send)
  File "****/site-packages/starlette/applications.py", line 102, in __call__
    await self.middleware_stack(scope, receive, send)
  File "****/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "****/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "****/site-packages/gino_starlette.py", line 83, in __call__
    await conn.release()
  File "****/site-packages/gino/engine.py", line 300, in release
    await dbapi_conn.release(True)
  File "****/site-packages/gino/engine.py", line 48, in release
    return await self._release()
  File "****/site-packages/gino/engine.py", line 84, in _release
    await self._pool.release(conn)
  File "****/site-packages/gino/dialects/asyncpg.py", line 280, in release
    await self._pool.release(conn)
  File "****/site-packages/asyncpg/pool.py", line 654, in release
    return await asyncio.shield(ch.release(timeout))
  File "****/site-packages/asyncpg/pool.py", line 216, in release
    raise ex
  File "****/site-packages/asyncpg/pool.py", line 206, in release
    await self._con.reset(timeout=budget)
  File "****/site-packages/asyncpg/connection.py", line 1137, in reset
    await self.execute(reset_query, timeout=timeout)
  File "****/site-packages/asyncpg/connection.py", line 295, in execute
    return await self._protocol.query(query, timeout)
  File "asyncpg/protocol/protocol.pyx", line 316, in query
asyncpg.exceptions.QueryCanceledError: canceling statement due to statement timeout

Specifications

  • Python version: 3.8
  • GINO version: 1.0.1
  • Starlette version: 0.1.1

Workarounds

I can suppress the error message when replacing this line
https://github.com/python-gino/gino-starlette/blob/master/src/gino_starlette.py#L83
with this:

try:
    await conn.release()
except QueryCanceledError:
    pass

But I am not quite sure if this is the best approach

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions