django / channels_redis

Redis channel layer backend for Django Channels

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mismatched `group_discard` behavior on RedisPubSub and core Redis layers

nbhargava opened this issue · comments

Versions:

  • channels 4.0.0
  • channels-redis 4.0.0

With RedisChannelLayer, group_discard explicitly does nothing if the channel is not in the group:

    async def group_discard(self, group, channel):
        """
        Removes the channel from the named group if it is in the group;
        does nothing otherwise (does not error)
        """
        assert self.valid_group_name(group), "Group name not valid"
        assert self.valid_channel_name(channel), "Channel name not valid"
        key = self._group_key(group)
        connection = self.connection(self.consistent_hash(group))
        await connection.zrem(key, channel)

In contrast, RedisPubSubChannelLayer will assert and fail if that's not the case:

    async def group_discard(self, group, channel):
        """
        Removes the channel from a group.
        """
        group_channel = self._get_group_channel_name(group)
        assert group_channel in self.groups
        group_channels = self.groups[group_channel]
        assert channel in group_channels
        group_channels.remove(channel)
        if len(group_channels) == 0:
            del self.groups[group_channel]
            shard = self._get_shard(group_channel)
            await shard.unsubscribe(group_channel)

For improved end-user expectations, they should both do the same thing. In my opinion, the original behavior of do nothing is more predictable and user-friendly, as any user of this library would have to otherwise functionally maintain self.groups on their own independently in order to verify that sending a group_discard method will not yield a crash.

If this change seems reasonable, I'm happy to put up a PR to this effect.

Via the Channel Layer spec:

A channel layer implementing the groups extension must also provide:

...
coroutine group_discard(group, channel), that removes the channel from the group if it is in it, and does nothing otherwise.

Looks like the PubSub layer behaviour is wrong.

If this change seems reasonable, I'm happy to put up a PR to this effect.

Yes please. 🎁