-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feature request] support ContextVars #45
Comments
Hi, Would this be a ASGI server/framework-dependant issue instead? Or do you mean that a no-server, plain asyncio code example produces this behavior as well? Asking because I think I saw a similar discussion over either Uvicorn or Starlette repos — mostly likely Starlette, which would run startup handlers in a long running lifespan task, and handle requests in another task, leading to different contexts and more broadly a lack of contextvars support for lifespan in Starlette. |
@florimondmanca I think you may be right, I'm using fastapi/starlette/uvicorn and andeed my context var setup needs tricky context saving/switching because lifespan is a separate call (from middleware's point of view). |
Right. I think that’s the current state of things, so gently going to close this as being not related to ASGI-lifespan per se. Thanks :) |
I'm pretty sure I know what happens now: I made a middelware that listens to lifespan events, and I'm using with fastapi/starlette/uvicorn. However, in the tests, I'm trying to use the context manager from this project. Key difference is that I Both call the middleware fastapi/starlette/uvicorn waits for This library kindof assumes that middleware lifespan processing is synchronous. Thus test requests arrive before my custom thing is actually set up. |
I'm not sure this is accurate, as we do asgi-lifespan/src/asgi_lifespan/_manager.py Lines 29 to 33 in fbb0f44
I think at this point sharing a bit of minimal reproduction code would be super helpful to see if there's anything we should be doing differently. In particular, you're mentioning "lifespan hook". |
🤔 the code appears to do the right thing... |
Hi, I've also been running into this issue 😢 I haven't dug into the code yet but it seems that startup and shutdown are being invoked in different contexts. With this minimal example: from fastapi import FastAPI
from contextvars import ContextVar
api = FastAPI()
ctx_var = ContextVar('mycontextvar')
async def lifespan(*args):
token = ctx_var.set(True)
try:
yield
finally:
ctx_var.reset(token)
api.router.lifespan_context = lifespan The below exception occurs:
|
A few questions to get the investigation going…
If we know in what happens in these situations then we may be able to pinpoint where the problem might be. Now that I think about it, I said at the beginning of this thread that lifespan is a long running task, but more precisely I believe that’s how Uvicorn does it. Still, this « token was created in a different Context » error seems different, even odd. I looked up Starlette code, and the lifespan_context there runs as a single async with call, no strange task stuff going on. Which strengthens my belief that we might want to look at how Uvicorn runs lifespan.. |
It seems like ASGI lifespan state allows addressing this use case, by allowing to store state initialized in the lifespan task for use in other places in the app. We just merged #57 which adds support for it in this package, so I'll close this now! |
It seem that setting context variables in
on_startup
is not supported.My naïve understanding is that there needs to be a new (copied) context in which all of
on_startup
, asgi request and thenon_shutdown
are ran.Otherwise, the value that's been set is not accessible in the request handlers and/or the context var cannot be reset in the shutdown function using the token that was generated in the startup function.
The text was updated successfully, but these errors were encountered: