image / src /services /websocketManager.js
hadadrjt's picture
image: Production!
4f33245
//
// SPDX-FileCopyrightText: Hadad <hadad@linuxmail.org>
// SPDX-License-Identifier: Apache-2.0
//
import config from '../../config.js';
import { generateId } from '../utils/idGenerator.js';
const clients = new Map();
export const setupWebSocket = (wss) => {
wss.on('connection', (ws) => {
const clientId = generateId();
let clientSessionId = null;
ws.clientId = clientId;
ws.isAlive = true;
ws.on('pong', () => {
ws.isAlive = true;
});
ws.on('message', (data) => {
try {
const message = JSON.parse(data.toString());
if (message.type === 'register' && message.sessionId) {
clientSessionId = message.sessionId;
if (clients.has(clientSessionId)) {
const oldClient = clients.get(clientSessionId);
if (oldClient && oldClient.readyState === 1) {
oldClient.close();
}
}
clients.set(clientSessionId, ws);
ws.sessionId = clientSessionId;
ws.send(JSON.stringify({
type: 'registered',
sessionId: clientSessionId
}));
}
handleWebSocketMessage(ws, message);
} catch (error) {}
});
ws.on('close', () => {
if (clientSessionId) {
clients.delete(clientSessionId);
}
});
ws.on('error', () => {
if (clientSessionId) {
clients.delete(clientSessionId);
}
});
ws.send(JSON.stringify({
type: 'connected',
clientId
}));
});
const interval = setInterval(() => {
wss.clients.forEach((ws) => {
if (ws.isAlive === false) {
return ws.terminate();
}
ws.isAlive = false;
ws.ping();
});
}, config.websocket.heartbeat);
wss.on('close', () => {
clearInterval(interval);
});
};
const handleWebSocketMessage = (ws, message) => {
if (message.type === 'ping') {
ws.send(JSON.stringify({ type: 'pong' }));
}
};
export const sendToSession = (sessionId, data) => {
const client = clients.get(sessionId);
if (client && client.readyState === 1) {
client.send(JSON.stringify({
...data,
sessionId
}));
}
};
export const broadcastToAll = (data) => {
clients.forEach((client, sessionId) => {
if (client.readyState === 1) {
client.send(JSON.stringify({
...data,
sessionId
}));
}
});
};