import { DefaultEventsMap, Server } from "socket.io"; import { createAdapter } from "@socket.io/redis-adapter"; import { createClient } from "redis"; let io: Server; let pubClient: ReturnType; let subClient: ReturnType; export const initWebsocket = (server: any) => { io = new Server(server, { cors: { origin: "*" }, transports: ["websocket"], }); io.on("connection", (socket) => { console.log(`New client connected: ${socket.id}`); socket.on("join", (login: string) => { if (login && typeof login === "string") { socket.join(`user:${login}`); } }); socket.on("message", (message) => { io.emit("message", message); }); socket.on("disconnect", () => { console.log(`Client disconnected: ${socket.id}`); }); }); return io; }; /** Připojí Redis adapter pro cross-pod broadcasting. Volat až po inicializaci Redis klienta. */ export const initRedisAdapter = async () => { const HOST = process.env.REDIS_HOST ?? 'localhost'; const PORT = process.env.REDIS_PORT ?? 6379; const url = `redis://${HOST}:${PORT}`; pubClient = createClient({ url }) as ReturnType; subClient = pubClient.duplicate(); await Promise.all([pubClient.connect(), subClient.connect()]); io.adapter(createAdapter(pubClient as any, subClient as any)); console.log('Socket.io: Redis adapter connected'); }; /** Zavře pub/sub Redis klienty adaptéru při graceful shutdown. */ export const shutdownWebsocketClients = async () => { await Promise.allSettled([pubClient?.quit(), subClient?.quit()]); }; export const getWebsocket = () => io; /** Pošle event konkrétnímu přihlášenému uživateli (pokud je připojen). */ export const emitToUser = (login: string, event: string, data: unknown) => { if (!io) return; io.to(`user:${login}`).emit(event, data); };