Friday, September 22, 2017

Re: Channels architecture for chat application and subscriptions

Okay. Thank you. Really appreciate what you guys are building.

Sincerely,
Robin

On Thu, Sep 21, 2017 at 1:10 AM, Andrew Godwin <andrew@aeracode.org> wrote:
Yes, you can do as you suggest, but you're also right that it will be slow to send. Groups are more efficient in theory, but right now their send implementation is also a for loop (though it's a little bit tighter) so not sure how drastic the difference will be.

Andrew

On Sun, Sep 17, 2017 at 10:15 PM, Robin Lery <robinlery@gmail.com> wrote:
Thank you, Andrew. Also, after reading more about channels in SO and channel's GitHub and also here in Django-users group, it seems to create a group per user works as well.

So, like the solution above how you told about adding the users to all the groups (threads) on connect:

eg:
    def ws_connect(message):
        for thread in user.thread_set.all():
            Group("thread-%d" %thread.id).add(message.reply_channel)



Can I also do something like this - instead of adding the user to all threads group on connect, I will set per user per group, and then whenever a message is received, that thread will send to all the users in its user list using the user's group:

eg:

    def send_msg(message):
        for user in self.user.all():
            Group("%d" % user.id).send({
                "text": json.dumps({
                    "foo": 'bar'
                })
            })


Also to consider here is that suppose a thread has a large number of users (say, more than 20,000 users), will the above solution be unwise for this type of situation?

Sincerely,
Robin

On Sun, Sep 17, 2017 at 11:22 PM, Andrew Godwin <andrew@aeracode.org> wrote:
Hi Robin,

The most efficient way to do this is to have one WebSocket connection that all the messages are sent down. Have a Group per group-chat and per single-user chat (I would model those as a special case of the group-chat if I were you for simplicity), and when a user connects, add them to the groups for all the chats they are in. Note that you will need to include chat IDs in any messages you send down to the browsers via groups, and de-tangle them using JavaScript to go to the right places.

Note that you can add and remove a connection from groups in the middle of the connection - just have something in the "websocket.message" handler that does this.

Also note that you'll need a separate send of endpoints that gets historical chat messages before the WebSocket streaming begins, if that's a desired feature. I'd recommend doing this slightly after the WebSocket is established so you don't miss any messages that might get sent between getting history and opening the socket - you'll risk getting the same message twice, but giving each message an ID will let you de-duplicate on the client side in that case.

Channels is a piece of a solution for a full-featured chat, but you're going to have to write a lot of additional logic around it. I have on my backlog a proper event-sourcing solution that would solve many of these, but I am focused on channels 2.0 first and the changes that will bring.

Andrew

On Sun, Sep 17, 2017 at 8:19 AM, Robin Lery <robinlery@gmail.com> wrote:

I would like to make a chat application using django and channels. I have two models to achieve a chat like application.

  1. Thread - A thread can have list of users. So, it can be used for chat between two users, or groups of user. If it's a group thread, it can have a subject for the group (eg. group name).

  2. Message - A message is the actual message sent from one user (sender) to a thread. And any users of thread's user list will have access to it.

class Thread(models.Model):      subject = models.CharField(max_length=255, blank=True)      user = models.ManyToManyField(User)    class Message(models.Model):      thread = models.ForeignKey(Thread)      sender = models.ForeignKey(User)      sent_datetime = models.DateTimeField(default=timezone.now)      body = models.TextField()

So, the chat app will have the basic features:

  1. Chat with a single user

    When a user sends a message to a user, django will check if a thread with both sender and recipient exists as the users. If it exist, then create a new message with that existing thread as the foreign key. If it doesn't exits, create a new thread, and create a new message with newly created thread as its foreign key to the thread.

  2. Chat with a group of users

    When a user creates a new group, a new thread will be created and that user will be added to the thread's user list. More users can be added to group later on. And any message sent will be available to all the users in the thread's user list.

After reading the docs I am not sure how to actually layout the architecture for the websocket and routing of the channels. I have the following confusions:

  1. From the docs on models, I will have to specify the room name in the url path, and on connect, the consumer will add the client (message.reply_channel) to that group of room (here thread), and then any messages sent will be broadcasted to all the users in the group. However, that is just for one room (thread). How can the user again chat with other threads (rooms). Will I have to make a new Websocket connection for each thread (room)?..

  2. This question is out of context of a chat app, but I need to know this to better understand how to make the architecture. In the docs, there's a section of live blogs where all the clients (message.reply_channel) are added to the "liveblog" group. However, in this scenario, we already know that we need to connect to "liveblog" groups. Suppose, there's a website where many authors write their blogs, and a user is subscribed to many authors (e.g.: "Adam", "Mary", "Robin", ...). And, if a author starts its blog, a connected user will get notified.

    So here, if the user connects to the websocket connection, on consumer, should we add the user to all blogs listed in his/her subscription list

e.g:

for sub in subscriptions:      Group(sub).add(message.reply_channel)

Or is there some better way to handle these kinds of architecture? I really like channels, and if anyone can help me understand and guide through these concepts I will really appreciate the help.


Sincerely,

Robin

--
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+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@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/CA%2B4-nGrMeAZGzmJAL95BsJAG5q%3D-NWw0_Yb-KNnyFNnV%2BCCz3w%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

--
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+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@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/CAFwN1uqidqjrU3uFsUib_hBU7WUiTHyptp%3Ddu1fEtd-Nz_en7Q%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

--
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+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@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/CA%2B4-nGrZG93xTe%2B%2BY28-mbEJA3LGBKpXYXwDVWoamzJqVVL06g%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.

--
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+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@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/CAFwN1upwEZUnWw-uVnP5J1N%2BmpwAWc-prT1Dwe2aiJDkoUx7rA%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.

--
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+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@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/CA%2B4-nGpa1%2Brc6P%2B3waNGKT7C5PRwABGnGU9qK5AtT22EpeUt3A%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment