1

TL;DR - How do I maintain a list of users in each room so that I can send that data to the front-end to display a list of participants in this room.

I'm designing a collaborative web application that uses django-channels for websocket communication between the browser and the server. A room can be joined by more than one user and every user should be aware of every other user in the room. How would I go about achieving this using django-channels (v2)?

I already went through the documentation and a few example projects available online but none of them have added a similar functionality. I also know about django-channels-presence but the project doesn't seem to be actively maintained so I didn't really bother looking into examples using that.

Here's what I've come up with so far:

- For every room, I create an object in the database and those objects can keep track of the users that are in the room. So for e.g in the WS consumer's connect() method I could do a get_or_create_room() call and room.add_participant(self.user_name) (or fetch this from the scope) and in the disconnect() method I could remove myself from the room. The problem with this, however, is that I might end up creating race conditions? I think? Also since I'm fetching objects from the ORM, I have to make sure that every time, before using this object I have to re-fetch it from the DB because it can (and will) become outdated quickly. This doesn't seem ideal at all.

- Another way I can think of is attaching data to self.channel_layer in the consumer where I can do something like setattr(self.channel_layer, f'users_{room_id}', {}) and maintain this dictionary for every user entering and leaving. This again doesn't sound very safe and I didn't see anyone using this so I'm unsure.

Any help regarding this would be appreciated. I'd also like to be able to see how existing applications do this if anyone can point me to one?

Areeb
  • 366
  • 1
  • 3
  • 16

1 Answers1

1

so in short there is no way to ask channels for the members in a group so you either need to:

  • Write some info into the db, with a timestamp so that you can see if it is old

or

  • send a message every (n seconds) over the channel group (machine readable item with the users id) then your consumers (or frontend) can maintain a list of users and filter this to those that have a resent timestamp. The disadvantage here is it might take a few seconds to detect all the users in a chat room.

You can't do anything like writing to a dict or global object since this is not shared over all the consumers.

Matthaus Woolard
  • 2,310
  • 11
  • 13
  • Do you know any examples that implement this? – Areeb Apr 16 '20 at 06:30
  • Also do you mean can't* in the end? – Areeb Apr 16 '20 at 06:39
  • i have having seen any examples listed on the web for this that go int the detail, is it important for you to know the number of users in a chatroom quickly? – Matthaus Woolard Apr 16 '20 at 09:47
  • Yes. Ideally, I'd want the list of users in the room – Areeb Apr 16 '20 at 09:53
  • 1
    then go with the db approach. create a DB table ChatRoomOcupancy that maps the user to the room (masicly a many to many table between user and room with a datetime field on it) then have the frontend message the consumer every 30 seconds when the consuerm gets this message it updates all the ChatRoomOcupancy entires for this user. You can then determine who is actively in a room based on the ChatRoomOcupancy with a recent datatime. – Matthaus Woolard Apr 16 '20 at 09:57