Prevent one GraphQL subscription completion from unintentionally dropping sibling subscriptions sharing the same Channels group.
Describe the Bug
Strawberry adds and discards groups with the consumer's channel name, which every subscription on the connection shares. Without counting, the first subscription to end discards the shared channel and silently stops delivery for any other subscription still holding that group.
System Information
- Operating system: Ubuntu 26.04
- Python version: 3.14
- Strawberry version (if applicable):
- strawberry-graphql: 0.323.2
- strawberry-graphql-django: 0.86.5
Additional Context
Our workaround to that issue:
class RefCountedChannelGroupsMixin:
"""Ref-count Channels group membership for one WebSocket connection.
Strawberry adds and discards groups with the consumer's channel name, which
every subscription on the connection shares. Without counting, the first
subscription to end discards the shared channel and silently stops delivery
for any other subscription still holding that group.
"""
def __init__(self, *args: Any, **kwargs: Any) -> None:
self._group_refs: Counter[str] = Counter()
super().__init__(*args, **kwargs)
@contextlib.asynccontextmanager
async def listen_to_channel(
self,
type: str,
*,
timeout: float | None = None,
groups: Sequence[str] = (),
) -> AsyncGenerator[Any, None]:
async with super().listen_to_channel(type, timeout=timeout) as generator:
for group in groups:
if not self._group_refs[group]:
await self.channel_layer.group_add(group, self.channel_name)
self._group_refs[group] += 1
try:
yield generator
finally:
for group in groups:
self._group_refs[group] -= 1
if self._group_refs[group] <= 0:
del self._group_refs[group]
with contextlib.suppress(Exception):
await self.channel_layer.group_discard(
group, self.channel_name
)
--
from strawberry.channels import GraphQLWSConsumer
class AuthGraphQLWSConsumer(RefCountedChannelGroupsMixin, GraphQLWSConsumer):
async def receive(
self, text_data: str | None = None, bytes_data: bytes | None = None
) -> None:
...
Prevent one GraphQL subscription completion from unintentionally dropping sibling subscriptions sharing the same Channels group.
Describe the Bug
Strawberry adds and discards groups with the consumer's channel name, which every subscription on the connection shares. Without counting, the first subscription to end discards the shared channel and silently stops delivery for any other subscription still holding that group.
System Information
Additional Context
Our workaround to that issue: