Hey guys I have made a small feed system which uses websockets and opens at the moment someone visits the website and login, all the new feeds will be send live and is updated realtime to those people who are subscribed to a particular user. I am using django-channels for this and have a non-unique room_name as of now, so that it is accessible to every user who is logged in and visits the website. but is it a good practice to do have a non unique room_name for such a system? Does it affect the performance or becomes obsolete if large number of users visits the website at the same time?
OR
Should I create a new table with the current user and a manyTomanyField which contains the subscribed users? if that's the case how do I add all the users to a channel group?
This is the code I have which is working fine now,
async def connect(self):
print('connected')
user = self.scope["user"]
self.user = user
room_name = f'sub-feeds'
self.room_name = room_name
await self.accept()
for now, I am checking a condition which returns True
if the user is subscribed to me else it returns False
.
async def external_feed(self, event): # sending from outside the consumer
user = self.user
oth_user = event['user']
condition = await self.get_subs_status(user, oth_user)
if condition == True:
await self.send_json({
'newFeed': event['feeds'],
})
I am actually concerned whether this breaks if the number of users increases a lot and using a separate room with subscribed users (new db table) will resolve the issue.
Please ask if you need more info. Help is much appreciated.
Thanks
If I was implementing this, I would use the username(which is assumed to be unique) as the room name. The implementation would be something like this,
from collections import defaultdict
class LiveFeedConsumer(WebsocketConsumer):
# map which uses the subscribed user's username as a key and stores the set of all users' username's who subscribed to their feeds as value.
# Ex - users 1, 2, 3, 4 are available
# __subscriptions[1] = {2, 3} -> Means 2 and 3 have subscribed to 1's feeds
__subscriptions = defaultdict(set)
def connect(self):
# authenticate
user_to_which_to_subscribe_to = get_user_somehow()
self.scope["session"]["room_name"] = user_to_which_to_subscribe_to.username
# Accept connection
self.__subscriptions[user_to_which_to_subscribe_to.username].add(self.scope["user"].username) # To extract users and their subscriptions
def disconnect(self, message):
# Disconnection logic
self.__subscriptions[ self.scope["session"]["room_name"] ].remove(self.scope["user"].username)
def get_subs_status(self, user, other_user):
return user.username in self.__subscriptions[other_user.username]
def external_feed(self, event): # sending from outside the consumer
user = self.user
oth_user = event['user']
condition = self.get_subs_status(user, oth_user)
if condition is True:
self.send_json({
'newFeed': event['feeds'],
})
# publish to pub/sub mechanism to support multiple processes/nodes
You can add the async/await parts of the code. You get the logic.
This way you'll have separate rooms for each user's live feed. Any user can subscribe to multiple other users. Furthermore, you can add a pub/sub listener to scale this horizontally, adding multiple nodes/processes.