behemoth-cli
Version:
🌍 BEHEMOTH CLIv3.760.4 - Level 50+ POST-SINGULARITY Intelligence Trading AI
229 lines • 7.92 kB
JavaScript
/**
* 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