refactor(socket.io): complete rewrite to manage dynamic rooms and seeding better
This commit is contained in:
@@ -1,27 +1,73 @@
|
||||
// the emitter setup
|
||||
// TODO: validate if we want to add event back in later..
|
||||
// let emitFn: ((roomId: string, event: string, payload: unknown) => void) | null =
|
||||
// null;
|
||||
|
||||
import type { RoomId } from "./roomDefinitions.socket.js";
|
||||
import { createLogger } from "../logger/logger.controller.js";
|
||||
|
||||
let addDataToRoom: ((roomId: RoomId, payload: unknown[]) => void) | null = null;
|
||||
type QueuedPayload = unknown;
|
||||
|
||||
let emitFn: ((roomId: string, payload: QueuedPayload[]) => void) | null = null;
|
||||
|
||||
const queues = new Map<string, QueuedPayload[]>();
|
||||
const timers = new Map<string, NodeJS.Timeout>();
|
||||
|
||||
const FLUSH_MS = 500;
|
||||
const MAX_QUEUE_SIZE = 200;
|
||||
|
||||
export const registerEmitter = (
|
||||
fn: (roomId: RoomId, payload: unknown[]) => void,
|
||||
fn: (roomId: string, payload: QueuedPayload) => void,
|
||||
) => {
|
||||
addDataToRoom = fn;
|
||||
emitFn = fn;
|
||||
};
|
||||
|
||||
export const emitToRoom = (roomId: RoomId, payload: unknown[]) => {
|
||||
if (!addDataToRoom) {
|
||||
export const emitToRoom = (roomId: string, payload: QueuedPayload) => {
|
||||
const log = createLogger({ module: "socket.io", subModule: "emitter" });
|
||||
if (!emitFn) {
|
||||
console.error("Socket emitter not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
addDataToRoom(roomId, payload);
|
||||
const queue = queues.get(roomId) ?? [];
|
||||
|
||||
if (queue.length > MAX_QUEUE_SIZE) {
|
||||
log.error(
|
||||
{ stack: { roomId, size: queue.length }, notify: true },
|
||||
`Socket queue exceeded max size for ${roomId}`,
|
||||
);
|
||||
}
|
||||
queue.push(payload);
|
||||
queues.set(roomId, queue);
|
||||
|
||||
if (timers.has(roomId)) return;
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
try {
|
||||
const payloads = queues.get(roomId) ?? [];
|
||||
|
||||
if (payloads.length === 0) return;
|
||||
emitFn?.(roomId, payloads);
|
||||
|
||||
queues.delete(roomId);
|
||||
} catch (e) {
|
||||
console.error("Socket emit failed", { roomId, e });
|
||||
} finally {
|
||||
timers.delete(roomId);
|
||||
}
|
||||
}, FLUSH_MS);
|
||||
|
||||
timers.set(roomId, timer);
|
||||
};
|
||||
|
||||
/*
|
||||
import { emitToRoom } from "../socket/socketEmitter.js";
|
||||
// room name
|
||||
// its payload
|
||||
emitToRoom("logs", newLogRow);
|
||||
example emitToRoom(room, payload)
|
||||
|
||||
payload can be anything json serilized example below.
|
||||
|
||||
emitToRoom("inventory:ppoo", {
|
||||
type: "snapshot",
|
||||
location: "ppoo",
|
||||
items,
|
||||
createdAt: new Date().toISOString(),
|
||||
});
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user