socket io stuff entered

This commit is contained in:
2026-03-12 15:05:37 -05:00
parent bf7d765989
commit 81dc575b4f
44 changed files with 234 additions and 6895 deletions

View File

@@ -0,0 +1,8 @@
import type { RoomId } from "./types.socket.js";
export const MAX_HISTORY = 20;
export const FLUSH_INTERVAL = 100; // 50ms change higher if needed
export const roomHistory = new Map<RoomId, unknown[]>();
export const roomBuffers = new Map<RoomId, any[]>();
export const roomFlushTimers = new Map<RoomId, NodeJS.Timeout>();

View File

@@ -0,0 +1,33 @@
import { logs } from "backend/db/schema/logs.schema.js";
import { desc } from "drizzle-orm";
import { db } from "../db/db.controller.js";
import type { RoomId } from "./types.socket.js";
type RoomDefinition<T = unknown> = {
seed: (limit: number) => Promise<T[]>;
};
export const roomDefinition: Record<RoomId, RoomDefinition> = {
logs: {
seed: async (limit) => {
try {
const rows = await db
.select()
.from(logs)
.orderBy(desc(logs.createdAt))
.limit(limit);
return rows.reverse();
} catch (e) {
console.error("Failed to seed logs:", e);
return [];
}
},
},
labels: {
seed: async (limit) => {
return [];
},
},
};

View File

@@ -0,0 +1,27 @@
// the emitter setup
import type { RoomId } from "./types.socket.js";
let addDataToRoom: ((roomId: RoomId, payload: unknown[]) => void) | null = null;
export const registerEmitter = (
fn: (roomId: RoomId, payload: unknown[]) => void,
) => {
addDataToRoom = fn;
};
export const emitToRoom = (roomId: RoomId, payload: unknown[]) => {
if (!addDataToRoom) {
console.error("Socket emitter not initialized");
return;
}
addDataToRoom(roomId, payload);
};
/*
import { emitToRoom } from "../socket/socketEmitter.js";
// room name
// its payload
emitToRoom("logs", newLogRow);
*/

View File

@@ -0,0 +1,73 @@
import type { Server } from "socket.io";
import { createLogger } from "../logger/logger.controller.js";
import {
FLUSH_INTERVAL,
MAX_HISTORY,
roomBuffers,
roomFlushTimers,
roomHistory,
} from "./roomCache.socket.js";
import { roomDefinition } from "./roomDefinitions.socket.js";
import type { RoomId } from "./types.socket.js";
// get the db data if not exiting already
const log = createLogger({ module: "socket.io", subModule: "roomService" });
export const preseedRoom = async (roomId: RoomId) => {
if (roomHistory.has(roomId)) {
return roomHistory.get(roomId);
}
const roomDef = roomDefinition[roomId];
if (!roomDef) {
log.error({}, `Room ${roomId} is not defined`);
}
const latestData = await roomDef.seed(MAX_HISTORY);
roomHistory.set(roomId, latestData);
return latestData;
};
export const createRoomEmitter = (io: Server) => {
const addDataToRoom = <T>(roomId: RoomId, payload: T) => {
if (!roomHistory.has(roomId)) {
roomHistory.set(roomId, []);
}
const history = roomHistory.get(roomId)!;
history?.push(payload);
if (history?.length > MAX_HISTORY) {
history?.shift();
}
if (!roomBuffers.has(roomId)) {
roomBuffers.set(roomId, []);
}
roomBuffers.get(roomId)!.push(payload);
if (!roomFlushTimers.has(roomId)) {
const timer = setTimeout(() => {
const buffered = roomBuffers.get(roomId) || [];
if (buffered.length > 0) {
io.to(roomId).emit("room-update", {
roomId,
payloads: buffered, // ✅ array now
});
}
roomBuffers.set(roomId, []);
roomFlushTimers.delete(roomId);
}, FLUSH_INTERVAL);
roomFlushTimers.set(roomId, timer);
}
};
return { addDataToRoom };
};

View File

@@ -3,9 +3,13 @@ import type { Server as HttpServer } from "node:http";
//import { fileURLToPath } from "node:url";
import { instrument } from "@socket.io/admin-ui";
import { Server } from "socket.io";
import { createLogger } from "../logger/logger.controller.js";
import { registerEmitter } from "./roomEmitter.socket.js";
import { createRoomEmitter, preseedRoom } from "./roomService.socket.js";
//const __filename = fileURLToPath(import.meta.url);
//const __dirname = dirname(__filename);
const log = createLogger({ module: "socket.io", subModule: "setup" });
export const setupSocketIORoutes = (baseUrl: string, server: HttpServer) => {
const io = new Server(server, {
@@ -16,29 +20,49 @@ export const setupSocketIORoutes = (baseUrl: string, server: HttpServer) => {
},
});
// ✅ Create emitter instance
const { addDataToRoom } = createRoomEmitter(io);
registerEmitter(addDataToRoom);
io.on("connection", (s) => {
console.info(s.id);
log.info({}, `User connected: ${s.id}`);
s.emit("welcome", {
serverTime: Date.now(),
availableRooms: ["logs", "labels"],
version: "1.0.0",
});
s.on("join-room", async (rn) => {
s.join(rn);
// get room seeded
const history = await preseedRoom(rn);
// send the intial data
s.emit("room-update", {
roomId: rn,
payloads: history,
initial: true,
});
});
});
// admin stuff for socket io
// app.use(
// express.static(
// join(__dirname, "../../../node_modules/@socket.io/admin-ui/dist"),
// ),
// );
io.on("disconnect", (s) => {
log.info({}, "User disconnected:", s.id);
});
// admin stuff
// app.get(baseUrl + "/admindashboard", (_, res) => {
// res.sendFile(
// join(
// __dirname,
// "../../../node_modules/@socket.io/admin-ui/dist/index.js",
// ),
// );
// });
const admin = io.of("/admin");
admin.on("connection", () => {
console.info("Connected to admin userspace");
admin.on("connection", (s) => {
log.info({}, `User connected: ${s.id}`);
});
admin.on("disconnect", (s) => {
log.info({}, "User disconnected:", s.id);
});
instrument(io, {
auth: false,
//namespaceName: "/admin",

View File

@@ -0,0 +1 @@
export type RoomId = "logs" | "labels"; //| "alerts" | "metrics";