ThreadPool execution should preserve contextvar context.
tomchristie opened this issue · comments
This is an implementation pattern, rather than something strictly for the ASGI spec.
Something that cropped up while implementing https://github.com/encode/sentry-asgi is that Python's ThreadPoolExecutor does not default to preserving the contextvars context, which really is what you want.
If you're using something like the Sentry SDK, then you needs contextvars
in order to properly tie otherwise unrelated events together into, and you need it to continue working properly when threadpools are used.
Here's my fix in Starlette: encode/starlette#192
Other ASGI tools and frameworks will want to use something similar when running sync code in threadpools.
Links to core issue here: encode/starlette#191
Given that this is what sync_to_async
does, are you suggesting we should apply it there? That's the only way Channels runs things in threadpools, I believe.
are you suggesting we should apply it there
I think it's the right way to do things if we want contextvars
to work correctly.
See the contextvars
PEP: https://www.python.org/dev/peps/pep-0567/#offloading-execution-to-other-threads
And this Python issue: https://bugs.python.org/issue34014
You could either wait until the issue manifests (eg. someone using sentry-asgi with Daphne / Channels, notices that in certain situations bits of logging are not being correctly tied in.) so that you've got some concrete evidence to work against, or just address it now on it's own merit.
FWIW we got bitten by this in our django-channels app and we're glad to see it fixed in the framework such that ContextVar
s just work as you'd expect them across that thread boundary. We used https://pypi.org/project/contextvars-executor/ and a
loop = asyncio.get_event_loop()
loop.set_default_executor(ContextVarExecutor(max_workers=int(os.environ.get("ASGI_THREADS", 1))))
to fix this for anything using asyncio internally, but I think this fix means we can get rid of that. +1 for Python changing this sooner rather than later!