From 6635365369fbf08726348d41cb0a95c0a5602b2d Mon Sep 17 00:00:00 2001 From: Jake Cattrall Date: Wed, 22 Jul 2026 00:00:41 +0100 Subject: [PATCH] fix(hosts): detach connection-close listener when host disconnects handleRegisterHost registered a listener on the process-global NorayEvents bus for every register-host command and never removed it. The listener array (and the socket/host each closure retained) grew without bound, and every connection-close emit became O(number of connections ever made). Over long uptimes this leaked memory and starved the reactor until it stopped answering commands while the TCP socket still accepted connections, requiring a restart. Make the listener self-removing so it is detached once its socket has closed. Memory then plateaus and per-disconnect cost stays constant. Fixes #81 Co-Authored-By: Claude Fable 5 --- src/hosts/host.commands.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/hosts/host.commands.ts b/src/hosts/host.commands.ts index ab112a8..d803514 100644 --- a/src/hosts/host.commands.ts +++ b/src/hosts/host.commands.ts @@ -33,7 +33,7 @@ export function handleRegisterHost(hostRepository: HostRepository) { ); // TODO: Manage this via repo in `host.ts` or smth - NorayEvents.on("connection-close", (closed) => { + const onConnectionClose = (closed: Bun.Socket) => { if (closed !== socket) return; log.info( @@ -42,7 +42,10 @@ export function handleRegisterHost(hostRepository: HostRepository) { ); hostRepository.removeItem(host); activeHostsGauge.dec(); - }); + + NorayEvents.off("connection-close", onConnectionClose); + }; + NorayEvents.on("connection-close", onConnectionClose); }); }; }