Channels - Updating client when the long running celery job finishes

502 views
Skip to first unread message

Suresh Jeevanandam

unread,
Mar 18, 2019, 8:21:18 AM3/18/19
to Django users
In my web application based on Django and Channels, the user makes a web-socket and send a JSON message. This initiates a celery task and a reference to the task is sent to the user. Now, I want to update the client when the results are ready.

The possible solutions I thought were:
1. The client sends a message through the same WebSocket asking for an update on the particular task with its ID. The server will reply not-ready and will send the result once ready.
2. Use https://github.com/fanout/django-eventstream and make a stream in a view (/task/ID/update/). This might result in wasting the server-side resources (because of continuous polling in the view).

Is there any other better way.

Is there any background task that we can initiate in the consumer and it will initiate communitation (send message) when needed. Or better yet, is there a way we can write to the client's web-socket from the celery task.

-
Suresh

Manas Nikam

unread,
Mar 18, 2019, 8:28:38 AM3/18/19
to django...@googlegroups.com
You can use firebase cloud messaging 

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/d6ee181c-8d02-4a51-9215-3da10a75773c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Aldian Fazrihady

unread,
Mar 18, 2019, 8:37:39 AM3/18/19
to django...@googlegroups.com
Hi Suresh,

Yes, celery task can send websocket message to client/JS.
My celery task uses websockets Python module to contact a Daphne channel belongs to JS client.

Suresh Jeevanandam

unread,
Mar 18, 2019, 9:04:55 AM3/18/19
to django...@googlegroups.com
Can you give some pointers on how you do that? In particular, will the client be notified on the same web socket it established with Django server?

Suresh Jeevanandam

unread,
Mar 18, 2019, 9:05:56 AM3/18/19
to django...@googlegroups.com
It's a closed network application. So, no access to firebase.

Aldian Fazrihady

unread,
Mar 18, 2019, 9:41:22 AM3/18/19
to django...@googlegroups.com
On Mon, Mar 18, 2019 at 9:04 PM Suresh Jeevanandam <jm.s...@gmail.com> wrote:
Can you give some pointers on how you do that? In particular, will the client be notified on the same web socket it established with Django server?

When the JS client established the Web Socket connection, you create a channel group for it:
from asgiref.sync import async_to_sync
from channels.generic.websocket import JsonWebsocketConsumer

class MessageConsumer(JsonWebsocketConsumer):
def accept(self):
scope_user = self.scope['user']

async_to_sync(self.channel_layer.group_add)("user-" + scope_user.username, self.channel_name)
super().accept()

Your celery task will do this:

import asyncio
import json
import websockets
from celery import shared_task
from django.conf import settings

async def async_send_message(
url, message, to_user, message_type="system.message"
):
async with websockets.connect(url) as websocket:
payload = {
"type": message_type, "message": message, "to": {"user": to_user}
}
await websocket.send(json.dumps(payload))

@shared_task
def send_text(text, to_user):
asyncio.get_event_loop().run_until_complete(
messaging_utils.async_send_message(
settings.CHANNEL_MESSAGING_URL, text,username
)
)
 
Inside the same MessageConsumer class above, define the methods that handles message from celery tasks, to be sent back to JS:

...

class MessageConsumer(JsonWebsocketConsumer):
...

def receive_json(self, content, **kwargs):

async_to_sync(self.channel_layer.group_send)("user-" + content["to"]["user"], content)

def system_message(self, content):
self.send_json(content)

Good Luck!

Aldian Fazrihady

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Suresh Jeevanandam

unread,
Mar 18, 2019, 11:35:49 AM3/18/19
to django...@googlegroups.com
Thanks a lot. Somehow it did not occur to me that this is the same problem as a group chat ...

Reply all
Reply to author
Forward
0 new messages