javascriptpythonwebsocketredis

How to kick the old session from websocket


async def connect(self):

    self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"]
    pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
    self.redis = redis.Redis(connection_pool=pool)

    logger.info("channel_name:{} / group_name {}".format(self.channel_name,self.room_group_name))
    await self.channel_layer.group_add(
        self.room_group_name,
        self.channel_name
    )
    await self.accept()
    
    for key in self.redis.keys():
        if self.redis.type(key).decode() == "zset":
            print("key:",key)
            print("len:",len(self.redis.zrange(key,0,-1)))

async def disconnect(self, close_code):
    logger.info("somehow disconnect")
    await self.channel_layer.group_discard(
        self.room_group_name,
        self.channel_name
    )

I have this script for websockt connection.

then

I am directly checking the record in redis to get the current members of chatroom.

If a user log-out and call disconnect , session is disappeared.

However If a user didn't call the disconnect function, session will be stored in redis table forver.

How can I remove the old session or set the timeout??


Solution

  • In a Django WebSocket (using Channels) setup, when users disconnect properly, their session is removed. However, if they don't call the disconnect() function (e.g., due to a network issue or force closing the browser), their session remains in Redis forever.

    Here are some steps you can follow to remove stale sessions:

    1. When a user connects, store their session with a timestamp and set an expiry for the room:

    import time
    import redis
    
    async def connect(self):
        self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"]
        pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
        self.redis = redis.Redis(connection_pool=pool)
    
        timestamp = time.time()
        self.redis.zadd(self.room_group_name, {self.channel_name: timestamp})  
        self.redis.expire(self.room_group_name, 600)  # Auto-remove if inactive for 10 minutes
    
        await self.channel_layer.group_add(self.room_group_name, self.channel_name)
        await self.accept()
    

    2. When a user disconnects, remove them from the Redis set:

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(self.room_group_name, self.channel_name)
        self.redis.zrem(self.room_group_name, self.channel_name)
    

    3. Before checking active users, clean up sessions older than 10 minutes:

    self.redis.zremrangebyscore(self.room_group_name, 0, time.time() - 600)