From 6bb396fd248e04cda9298c392d8ca176618659e9 Mon Sep 17 00:00:00 2001 From: Ben Allfree Date: Tue, 17 Jun 2025 12:49:17 +0000 Subject: [PATCH] refactor: enhance MultiChannelLimiter with idle cleanup and scheduling --- .../services/InstanceLoggerService/index.ts | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/packages/pockethost/src/services/InstanceLoggerService/index.ts b/packages/pockethost/src/services/InstanceLoggerService/index.ts index c742cbe0..789a6633 100644 --- a/packages/pockethost/src/services/InstanceLoggerService/index.ts +++ b/packages/pockethost/src/services/InstanceLoggerService/index.ts @@ -30,20 +30,49 @@ export type LogEntry = { const MultiChannelLimiter = () => { const channels = new Map() - setInterval(() => { - for (const [channel, limiter] of channels.entries()) { - if (limiter.empty()) { - // console.log(`Deleting empty limiter for ${channel}`) - channels.delete(channel) - } + const timeouts = new Map() + const IDLE_TIMEOUT = 1000 * 60 // 1 minute idle timeout per channel + + const cleanupChannel = (channel: string) => { + const limiter = channels.get(channel) + if (limiter && limiter.empty()) { + // console.log(`Deleting idle limiter for ${channel}`) + channels.delete(channel) + timeouts.delete(channel) } - }, 1000 * 60) + } + + const scheduleCleanup = (channel: string) => { + // Clear existing timeout if any + const existingTimeout = timeouts.get(channel) + if (existingTimeout) { + clearTimeout(existingTimeout) + } + + // Schedule new cleanup + const timeout = setTimeout(() => cleanupChannel(channel), IDLE_TIMEOUT) + timeouts.set(channel, timeout) + } return { schedule(channel: string, fn: () => Promise) { if (!channels.has(channel)) { - channels.set(channel, new Bottleneck({ maxConcurrent: 1 })) + const limiter = new Bottleneck({ maxConcurrent: 1 }) + channels.set(channel, limiter) + + // Set up cleanup when limiter becomes empty + limiter.on('idle', () => { + scheduleCleanup(channel) + }) } + + // Clear any pending cleanup since channel is active + const existingTimeout = timeouts.get(channel) + if (existingTimeout) { + clearTimeout(existingTimeout) + timeouts.delete(channel) + } + return channels.get(channel)!.schedule(fn)! }, }