Challenge 2: Wire Up Redis Pub/Sub for Presence — Possible Solution ==================================================================== // --- Subscription, set up once per server process --- redisSubscriber.subscribe("room-presence", (message) => { const { roomName, payload } = JSON.parse(message); sendToRoom(roomName, payload); // Chapter 6's local broadcast, now Redis-fed }); // --- Updated joinRoom, publishing instead of calling sendToRoom directly --- function joinRoom(socket, roomName) { if (!rooms.has(roomName)) rooms.set(roomName, new Set()); rooms.get(roomName).add(socket); socket.rooms.add(roomName); const presencePayload = JSON.stringify({ type: "presence", event: "joined", userId: socket.userId }); redisPublisher.publish("room-presence", JSON.stringify({ roomName, payload: presencePayload })); } // --- Updated leaveRoom, same change applied --- function leaveRoom(socket, roomName) { const members = rooms.get(roomName); if (!members) return; members.delete(socket); socket.rooms.delete(roomName); const presencePayload = JSON.stringify({ type: "presence", event: "left", userId: socket.userId }); redisPublisher.publish("room-presence", JSON.stringify({ roomName, payload: presencePayload })); } WHY THIS WORKS -------------- - joinRoom and leaveRoom no longer call sendToRoom() directly — they publish to a single shared "room-presence" Redis channel instead, wrapping BOTH the roomName and the actual message payload into one JSON envelope, since a single Redis channel is being reused here for presence events across every room rather than one Redis channel per room (a valid simplification for presence specifically, since presence messages are relatively low volume compared to regular chat traffic). - Every server instance's subscription callback fires when ANY server publishes to "room-presence" — including the server that itself just published the message. That callback unpacks the envelope and calls sendToRoom(roomName, payload), which is Chapter 6's original local broadcast function, completely unchanged — it still only reaches sockets that happen to be connected to THIS particular server process. - The net effect: a user joining a room on Server A triggers a "joined" presence event that reaches room members regardless of which server instance they're connected to, because the message travels through Redis to every server, and each server then delivers it only to its own local members — exactly the "publish once, deliver everywhere" pattern described in the chapter, now applied specifically to presence rather than regular chat messages. - This mirrors the exact structure of the chapter's own broadcastToRoom example — the only real change is bundling roomName into the published payload, since this version deliberately uses one shared channel for all rooms' presence events rather than a channel per room.