#36714: Async signals lose ContextVar state due to use of asyncio.gather
----------------------------------+------------------------------------
Reporter: Mykhailo Havelia | Owner: (none)
Type: Bug | Status: new
Component: HTTP handling | Version: dev
Severity: Normal | Resolution:
Keywords: asyncio, signals | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------+------------------------------------
Comment (by Mykhailo Havelia):
Replying to [comment:12 Carlton Gibson]:
> sync_to_async already propagates the parent context.
[https://github.com/django/asgiref/blob/2138f0317d79cedd065571447ae0a7571989550e/tests/test_sync_contextvars.py#L37-L55
See tests]. Is it not the case that the `asyncio.TaskGroup()` call in
`_gather` needs to take the context parameter? 🤔
>
> I think this is going to be easier to look at in a PR than a series of
comments on the issue here.
I’ve already attached the link to the MR above:
https://github.com/Arfey/django/pull/3/files. Did you have a chance to
look at it? 🙂
`sync_to_async` does support modifying contextvars, but what we need is
the ability to share the same context between tasks running in parallel.
There’s a test included in my MR that demonstrates exactly what behavior
we have to achieve
{{{
async def test_asend_correct_contextvars_sharing_mix_receivers(self):
handler1 = self.CtxSyncHandler(self.ctx_var)
handler2 = self.CtxAsyncHandler(self.ctx_var)
signal = dispatch.Signal()
signal.connect(handler1)
signal.connect(handler2)
# set custom value outer signal
self.ctx_var.set(1)
await signal.asend(self.__class__)
self.assertEqual(len(handler1.values), 1)
self.assertEqual(len(handler2.values), 1)
self.assertEqual(
sorted([*handler1.values, *handler2.values]),
[2, 3]
)
self.assertEqual(self.ctx_var.get(), 3)
}}}
Right now we don't end up with all 3. We only get 2, because `handler1`
and `handler2` don't share context with each other. The reason is that
`sync_to_async` copies the context (see:
https://github.com/django/asgiref/blob/2138f0317d79cedd065571447ae0a7571989550e/asgiref/sync.py#L483),
but in our case we need them to share it.
--
Ticket URL: <https://code.djangoproject.com/ticket/36714#comment:13>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/0107019a6d7ed122-85a90716-85ef-4f01-a896-25d70e937454-000000%40eu-central-1.amazonses.com.