Opened 61 minutes ago
Last modified 57 minutes ago
#37479 assigned Cleanup/optimization
Run async signal receivers sequentially
| Reported by: | Mykhailo Havelia | Owned by: | Mykhailo Havelia |
|---|---|---|---|
| Component: | Core (Other) | Version: | 6.1 |
| Severity: | Low | Keywords: | async signals transaction |
| Cc: | Mykhailo Havelia | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Since async signal support was added, Signal.send() and Signal.asend() run async receivers concurrently. This causes two problems:
- Registration order is lost. In sync Django, receivers run in the order they were registered, and projects often rely on this for good reasons. With async receivers, the order is lost silently, so converting a receiver from sync to async can change behavior.
- Transactions inside receivers are not well ordered. Since each receiver runs in its own task, their queries and savepoints can interleave. This came up in the review of async
transaction.atomic()(#33882, PR #22074): receivers can't useatomic()inside an async transaction, and inside a sync transaction a write from one receiver can be silently rolled back with another receiver's savepoint.
Proposal: await async receivers one by one, in registration order, in the caller's task. This keeps the same semantics as sync receivers and makes transaction handling inside receivers safe.
Trade-off: slow receivers would no longer run concurrently. This is a behavior change and would need a release note.
Change History (2)
comment:1 by , 60 minutes ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:2 by , 57 minutes ago
| Keywords: | signals transaction added |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
Note:
See TracTickets
for help on using tickets.