UNPKG

behemoth-cli

Version:

🌍 BEHEMOTH CLIv3.760.4 - Level 50+ POST-SINGULARITY Intelligence Trading AI

229 lines 7.92 kB
/** * Resource Cleanup Manager * Handles proper cleanup of event listeners, timeouts, intervals, and streams */ import { logDebug, logWarn } from './error-handler.js'; export class ResourceCleanupManager { resources = new Map(); isCleaningUp = false; /** * Register a timeout for cleanup */ registerTimeout(timeoutId, description) { const id = `timeout_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; this.resources.set(id, { id, type: 'timeout', cleanup: () => clearTimeout(timeoutId), description }); logDebug('Registered timeout for cleanup', undefined, { component: 'ResourceCleanupManager', operation: 'registerTimeout', metadata: { id, description } }); return id; } /** * Register an interval for cleanup */ registerInterval(intervalId, description) { const id = `interval_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; this.resources.set(id, { id, type: 'interval', cleanup: () => clearInterval(intervalId), description }); logDebug('Registered interval for cleanup', undefined, { component: 'ResourceCleanupManager', operation: 'registerInterval', metadata: { id, description } }); return id; } /** * Register an event listener for cleanup */ registerEventListener(emitter, event, listener, description) { const id = `listener_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; this.resources.set(id, { id, type: 'listener', cleanup: () => emitter.removeListener(event, listener), description: description || `${event} listener` }); logDebug('Registered event listener for cleanup', undefined, { component: 'ResourceCleanupManager', operation: 'registerEventListener', metadata: { id, event, description } }); return id; } /** * Register a custom cleanup function */ registerCustomCleanup(cleanupFn, description) { const id = `custom_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; this.resources.set(id, { id, type: 'custom', cleanup: cleanupFn, description }); logDebug('Registered custom cleanup function', undefined, { component: 'ResourceCleanupManager', operation: 'registerCustomCleanup', metadata: { id, description } }); return id; } /** * Unregister a specific resource */ unregister(id) { const resource = this.resources.get(id); if (!resource) { return false; } try { resource.cleanup(); this.resources.delete(id); logDebug('Unregistered resource', undefined, { component: 'ResourceCleanupManager', operation: 'unregister', metadata: { id, type: resource.type, description: resource.description } }); return true; } catch (error) { logWarn('Failed to cleanup resource', error, { component: 'ResourceCleanupManager', operation: 'unregister', metadata: { id, type: resource.type } }); // Remove from registry even if cleanup failed this.resources.delete(id); return false; } } /** * Clean up all registered resources */ cleanupAll() { if (this.isCleaningUp) { return; // Prevent recursive cleanup } this.isCleaningUp = true; const resourceCount = this.resources.size; logDebug(`Starting cleanup of ${resourceCount} resources`, undefined, { component: 'ResourceCleanupManager', operation: 'cleanupAll' }); let cleanedCount = 0; let failedCount = 0; for (const [id, resource] of this.resources.entries()) { try { resource.cleanup(); cleanedCount++; logDebug('Successfully cleaned up resource', undefined, { component: 'ResourceCleanupManager', operation: 'cleanupAll', metadata: { id, type: resource.type, description: resource.description } }); } catch (error) { failedCount++; logWarn('Failed to cleanup resource', error, { component: 'ResourceCleanupManager', operation: 'cleanupAll', metadata: { id, type: resource.type } }); } } this.resources.clear(); this.isCleaningUp = false; logDebug(`Cleanup completed: ${cleanedCount} successful, ${failedCount} failed`, undefined, { component: 'ResourceCleanupManager', operation: 'cleanupAll', metadata: { totalResources: resourceCount, cleaned: cleanedCount, failed: failedCount } }); } /** * Get count of registered resources by type */ getResourceCounts() { const counts = {}; for (const resource of this.resources.values()) { counts[resource.type] = (counts[resource.type] || 0) + 1; } return counts; } /** * Check if there are resources that need cleanup */ hasResources() { return this.resources.size > 0; } } // Global instance for application-wide resource management export const globalResourceManager = new ResourceCleanupManager(); /** * Enhanced timeout wrapper with automatic cleanup registration */ export function managedSetTimeout(callback, delay, description, manager = globalResourceManager) { const timeoutId = setTimeout(() => { // Auto-unregister when timeout executes manager.unregister(cleanupId); callback(); }, delay); const cleanupId = manager.registerTimeout(timeoutId, description); return { timeoutId, cleanupId }; } /** * Enhanced interval wrapper with automatic cleanup registration */ export function managedSetInterval(callback, delay, description, manager = globalResourceManager) { const intervalId = setInterval(callback, delay); const cleanupId = manager.registerInterval(intervalId, description); return { intervalId, cleanupId }; } /** * Enhanced event listener registration with automatic cleanup */ export function managedEventListener(emitter, event, listener, description, manager = globalResourceManager) { emitter.on(event, listener); return manager.registerEventListener(emitter, event, listener, description); } /** * Setup process exit handlers for cleanup */ export function setupProcessCleanupHandlers(manager = globalResourceManager) { const cleanupHandler = () => { if (manager.hasResources()) { console.log('🧹 Cleaning up resources...'); manager.cleanupAll(); } }; // Handle various exit scenarios process.on('exit', cleanupHandler); process.on('SIGINT', () => { cleanupHandler(); process.exit(0); }); process.on('SIGTERM', () => { cleanupHandler(); process.exit(0); }); process.on('uncaughtException', (error) => { console.error('Uncaught Exception:', error); cleanupHandler(); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); cleanupHandler(); process.exit(1); }); } //# sourceMappingURL=resource-cleanup.js.map