Skip to content

caching an async dependency method on the router level #1102

@euri10

Description

@euri10

Describe the bug

I have an expensive file loading whose result is used in a router in each and every endpoint.
I don't want the loading to be performed each and every request but I need to use it as a depends so I I'd like to cache it.

The linked gist is a minimal example of the bug

I'm using in my router get_users_queries = AsyncGetQueries("users.sql") and in my endpoints router users_queries: Queries = Depends(get_users_queries.loaded)

If I'm using the sync method of my dependable class, the cache works fine and I'm able to use the dependency in all my subsequent requests.

But if I want to use an async method users_queries: Queries = Depends(get_users_queries.async_load) as a dependency I got the below error

Traceback (most recent call last):
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 385, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/fastapi/applications.py", line 149, in __call__
    await super().__call__(scope, receive, send)
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/starlette/applications.py", line 102, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc from None
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/starlette/routing.py", line 550, in __call__
    await route.handle(scope, receive, send)
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/starlette/routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/starlette/routing.py", line 41, in app
    response = await func(request)
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/fastapi/routing.py", line 137, in app
    solved_result = await solve_dependencies(
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/fastapi/dependencies/utils.py", line 504, in solve_dependencies
    solved = await solve_generator(
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/fastapi/dependencies/utils.py", line 419, in solve_generator
    return await stack.enter_async_context(cm)
  File "/home/lotso/.pyenv/versions/3.8.1/lib/python3.8/contextlib.py", line 568, in enter_async_context
    result = await _cm_type.__aenter__(cm)
  File "/home/lotso/.pyenv/versions/3.8.1/lib/python3.8/contextlib.py", line 171, in __aenter__
    return await self.gen.__anext__()
  File "/home/lotso/.cache/pypoetry/virtualenvs/simplefapi-xWVIRhl2-py3.8/lib/python3.8/site-packages/fastapi/concurrency.py", line 45, in contextmanager_in_threadpool
    raise e
  File "/home/lotso/.pyenv/versions/3.8.1/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
RuntimeError: There is no current event loop in thread 'ThreadPoolExecutor-0_0'.

To Reproduce

run the gist provided, happy to consider alternative on how to achieve a global cache on a router dependency used in endpoints

Environment

  • OS: debian buster
  • FastAPI Version 0.52.0

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions