ai-debug-local-mcp
Version:
🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh
99 lines • 3.36 kB
JavaScript
/**
* AbortSignal Memory Leak Manager
* Critical fix for EventTarget memory leak: 11 abort listeners detected
* Centralized AbortController management with proper cleanup
*/
export class AbortSignalManager {
static activeControllers = new Set();
static listenerCount = 0;
/**
* Create a tracked AbortController with automatic cleanup
*/
static createController() {
const controller = new AbortController();
this.activeControllers.add(controller);
// Set up automatic cleanup when aborted
controller.signal.addEventListener('abort', () => {
this.activeControllers.delete(controller);
}, { once: true });
this.listenerCount++;
// Warn if listener count is getting high
if (this.listenerCount > 5) {
console.warn(`⚠️ AbortSignal listener count: ${this.listenerCount} (potential memory leak)`);
}
return controller;
}
/**
* Manually cleanup a controller and all its listeners
*/
static cleanupController(controller) {
if (this.activeControllers.has(controller)) {
if (!controller.signal.aborted) {
controller.abort();
}
this.activeControllers.delete(controller);
this.listenerCount = Math.max(0, this.listenerCount - 1);
}
}
/**
* Create a controller with automatic timeout cleanup
*/
static createWithTimeout(timeoutMs) {
const controller = this.createController();
const timeoutId = setTimeout(() => {
this.cleanupController(controller);
}, timeoutMs);
return { controller, timeoutId };
}
/**
* Emergency cleanup of all active controllers
*/
static emergencyCleanup() {
console.log(`🧹 Emergency AbortSignal cleanup: ${this.activeControllers.size} controllers`);
this.activeControllers.forEach(controller => {
try {
if (!controller.signal.aborted) {
controller.abort();
}
}
catch (error) {
console.error('Error during emergency AbortController cleanup:', error);
}
});
this.activeControllers.clear();
this.listenerCount = 0;
}
/**
* Get current AbortSignal memory usage stats
*/
static getStats() {
const activeControllers = this.activeControllers.size;
const estimatedListeners = this.listenerCount;
let memoryPressure = 'low';
if (estimatedListeners > 10)
memoryPressure = 'high';
else if (estimatedListeners > 5)
memoryPressure = 'medium';
return { activeControllers, estimatedListeners, memoryPressure };
}
/**
* Set up process-level cleanup
*/
static setupGlobalCleanup() {
// Clean up on process exit
process.on('beforeExit', () => {
this.emergencyCleanup();
});
process.on('SIGTERM', () => {
this.emergencyCleanup();
process.exit(0);
});
process.on('SIGINT', () => {
this.emergencyCleanup();
process.exit(0);
});
}
}
// Auto-setup global cleanup
AbortSignalManager.setupGlobalCleanup();
//# sourceMappingURL=abort-signal-manager.js.map