Filip Kowalczyk
Filip Kowalczyk

Reputation: 55

Calling Channels AsyncWebCoscketConsumer function from Signals Receiver doesn't work

Firstly, here's the code. I have checked it now I don't know how many times for any errors, and debugged step by step to find out why the function isn't called.

# signals.py
@receiver(post_save, sender=Ticket)
def new_ticket(sender, instance, created, **kwargs):
    print("in receiver")
    if created:
        print("in created")
        channel_layer = get_channel_layer()
        print(channel_layer)
        async_to_sync(channel_layer.group_send(
        'tickets_updates_group',
        {
            'type': 'new_ticket',
            'subject': "from receiver"
        }))
        print("after async_to_sync")

All the print statements are always being called.

# consumers.py
class Tickets(AsyncWebsocketConsumer):
    async def connect(self):
        await self.channel_layer.group_add('tickets_updates_group', self.channel_name)
        await self.accept()
    
    async def disconnect(self, close_code):
        await self.channel_layer.group_discard('tickets_updates_group', self.channel_name)
        await self.close()

    async def new_ticket(self, event):
        print('in consumer.new_ticket')
        subject = event['subject']
        print("subject: " + subject)
        await self.send(text_data=json.dumps({
            'subject': subject
        }))
        print("after send")

Here, the new_ticket function is never being called, none of the print statements are being executed and my webpage isn't updated (as opposed to putting the group_send code in the connect funciton of the consumer class.

I know that the problem isn't syntax, because if I add receiver's code to the consumers connect function, the new_ticket function is always being called without a problem (after replacing async_to_sync with await.

I have seen all the possible working examples out there and I cannot seem to figure out why for the life of me I cannot call a consumer function from a signal receiver.

I am using the InMemoryChannelLayer:

# settings.py
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels.layers.InMemoryChannelLayer"
    }
}

Upvotes: 0

Views: 504

Answers (1)

Filip Kowalczyk
Filip Kowalczyk

Reputation: 55

SOLUTION: Fixing a syntax error! When calling from outside the consumers class, I wrapped the group_send call in async_to_sync and made an error with the parenthesis on the first line:

async_to_sync(channel_layer.group_send(
    'tickets_updates_group',
    {
        'type': 'new_ticket',
        'subject': "from receiver"
    }))

Changed to:

async_to_sync(channel_layer.group_send)(
    'tickets_updates_group',
    {
        'type': 'new_ticket',
        'subject': "from receiver"
    })

And all works (I have changed to redis channel layer also, as I was debugging before).

Upvotes: 1

Related Questions