fix: support persistent lifespans in asgi - #231
Conversation
| async def lifespan_state(): | ||
| nonlocal lifespan | ||
| if lifespan is None: | ||
| # Assign before awaiting so concurrent first requests share startup. | ||
| lifespan = create_task(start_application(app)) | ||
| _, state = await lifespan | ||
| return state |
There was a problem hiding this comment.
A cancelled first request propagates cancellation into this shared task, leaving lifespan permanently cancelled and causing every later request in the isolate to be cancelled. Shield the shared startup task from an individual request cancellation.
| async def lifespan_state(): | |
| nonlocal lifespan | |
| if lifespan is None: | |
| # Assign before awaiting so concurrent first requests share startup. | |
| lifespan = create_task(start_application(app)) | |
| _, state = await lifespan | |
| return state | |
| async def lifespan_state(): | |
| from asyncio import shield | |
| nonlocal lifespan | |
| if lifespan is None: | |
| # Assign before awaiting so concurrent first requests share startup. | |
| lifespan = create_task(start_application(app)) | |
| _, state = await shield(lifespan) | |
| return state |
|
I'm Bonk, and I've done a quick review of your PR. Makes ASGI entrypoint lifespan state persist across requests.
|
864cb45 to
5b8cb5e
Compare
hoodmane
left a comment
There was a problem hiding this comment.
Generally looks reasonable, though I'd set _start_future on the AsgiWorkerEntrypoint instance rather than the class and initialize _start_future to None in AsgiWorkerEntrypoint.__init__(). Could adjust it in a followup if you like though.
5b8cb5e to
8b7b84c
Compare
8b7b84c to
afea9e1
Compare
|
So we do actually want it set on the class because the instance is re-created on every worker invocation. The lifespan is supposed to stay alive for the duration of the lifetime of the isolate. I added a comment to explain this. |
That is really weird, can we migrate away from that? |
|
In JavaScript is the WorkerEntrypoint instantiated on every request? |
Ensures that mutable lifespans are persisted across requests. Adds fastapi and asgi-specific tests.