63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
/**
|
|
* Socket Tracker Utility
|
|
* Provides standardized socket cleanup with proper listener and timer management
|
|
*/
|
|
|
|
import type { Socket } from 'net';
|
|
|
|
export type SocketTracked = {
|
|
cleanup: () => void;
|
|
addListener: <E extends string>(event: E, listener: (...args: any[]) => void) => void;
|
|
addTimer: (t: NodeJS.Timeout | null | undefined) => void;
|
|
safeDestroy: (reason?: Error) => void;
|
|
};
|
|
|
|
/**
|
|
* Create a socket tracker to manage listeners and timers
|
|
* Ensures proper cleanup and prevents memory leaks
|
|
*/
|
|
export function createSocketTracker(socket: Socket): SocketTracked {
|
|
const listeners: Array<{ event: string; listener: (...args: any[]) => void }> = [];
|
|
const timers: NodeJS.Timeout[] = [];
|
|
let cleaned = false;
|
|
|
|
const addListener = (event: string, listener: (...args: any[]) => void) => {
|
|
socket.on(event, listener);
|
|
listeners.push({ event, listener });
|
|
};
|
|
|
|
const addTimer = (t: NodeJS.Timeout | null | undefined) => {
|
|
if (!t) return;
|
|
timers.push(t);
|
|
// Unref timer so it doesn't keep process alive
|
|
if (typeof t.unref === 'function') {
|
|
t.unref();
|
|
}
|
|
};
|
|
|
|
const cleanup = () => {
|
|
if (cleaned) return;
|
|
cleaned = true;
|
|
|
|
// Clear all tracked timers
|
|
for (const t of timers) {
|
|
clearTimeout(t);
|
|
}
|
|
timers.length = 0;
|
|
|
|
// Remove all tracked listeners
|
|
for (const { event, listener } of listeners) {
|
|
socket.off(event, listener);
|
|
}
|
|
listeners.length = 0;
|
|
};
|
|
|
|
const safeDestroy = (reason?: Error) => {
|
|
cleanup();
|
|
if (!socket.destroyed) {
|
|
socket.destroy(reason);
|
|
}
|
|
};
|
|
|
|
return { cleanup, addListener, addTimer, safeDestroy };
|
|
} |