Syncing issue within Socket IO

138 views Asked by At

I've implemented a website chat with python-socketio and socket.io-client.

At times, when we simultaneously open multiple tabs in different browsers or incognito sessions with the same logged-in user, the newly opened tabs can successfully send and receive messages. However, the older tabs CAN send but DO NOT receive messages, even though they remain connected to Python Socket.IO and socket.io-client. Additionally, I've already used a room session for managing the connections. This Problem happens on a live server where, at any point about 50-100 users are connected to the socket, not on localhost.

The versions I'm using are as follows:

python-socketio==5.9.0
uvicorn==0.16.0
eventlet==0.33.3
socket.io-client = 4.7.2

Backend:

    import socketio
    sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins='*', logger=True, engineio_logger=True)
    connected_users = {}
    room_user_count = {}
    @sio.on("connect")
    async def connect(sid, environ):
      try:
        query_string = environ.get("QUERY_STRING") or "Anonymous"
        if query_string:
          username = query_string.split("username=")[1].split("&")[0]
          await sio.save_session(sid, {'username': username})
          room_name = await change_group_name(username)
          sio.enter_room(sid, room_name)
        print(f"[Connected] {sid}")
      except Exception as e:
        print("Connected error", str(e))
    @sio.on("login")
    async def handle_login(sid, data):
      username = data.get("username")
      session_id = await sio.get_session(sid)
      connected_users[sid] = {"username": username, "session_id": session_id['username']}
      print(f"{username} logged in.")
    @sio.on("disconnect")
    async def disconnect(sid):
      try:
        username = connected_users.get(sid, {}).get("username", "Anonymous")
        connected_users.pop(sid, None)
        leave_room = await change_group_name(username)
        sio.leave_room(sid, leave_room)
        print(f"Disconnected: {sid}, Username: {username}")
      except Exception as e:
        print(f"Disconnected Error: {e}")
    @sio.on("client_chat_app")
    async def message_from_client(sid, data):
      username = connected_users.get(sid, {}).get("username", "Anonymous")
      user = await get_user_obj(username)
      await chat_app_function(data, user, sid)

Frontend:

import socketIOClient from "socket.io-client";
useEffect(() => {
  let username = “username”;
  socket = socketIOClient(WEB_SOCKET_IO, {
   query: { username: username },
   secure: true,
   transports: ["websocket"],
   path: "/socket.io/",
   reconnectionDelay: 1000,
   reconnection: true,
   reconnectionAttempts: Infinity,
  });
  socket.on("connect", () => {
   socket.emit("login", { username });
  });
  let event_chat_app = username + "sent_chat_app";
  socket.on(event_chat_app, (value) => {
   try {
    console.log(“value”, value)
   } catch (e) {}
  });
 }
 return () => {
  socket?.disconnect();
 };
}, []);

What can I do to ensure that the syncing issue does not happen again?

1

There are 1 answers

1
Yash Mittra On BEST ANSWER

The issue was that client_manager was missing. I had to add the AsyncRedisManager to the AsyncServer. Use a message broker: Implement a message broker like Redis, RabbitMQ, or Kafka to manage the synchronization of messages and events between your multiple workers. When a user sends a message or event, it can be published to the message broker, and all workers can subscribe to it to receive updates.

Without it, multiple instances of Socket IO were initiated. In other words, room1 and room1 could be different for two different users.

The code to fix it is below:

manager = socketio.AsyncRedisManager("redis://localhost:6379/0")
sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*", client_manager=manager)

I needed to use pip3 install aioredis as well to make this work.