UNPKG

@sirmrmarty/n8n-nodes-tmux-orchestrator

Version:

n8n nodes for orchestrating Claude AI agents through tmux sessions

293 lines 9.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.REQUIRED_DEPENDENCIES = exports.PerformanceMonitor = exports.BatchProcessor = exports.ConnectionPool = exports.PerformanceCache = void 0; exports.debounce = debounce; exports.throttle = throttle; const lru_cache_1 = require("lru-cache"); class PerformanceCache { constructor(config = {}) { this.hits = 0; this.misses = 0; this.cache = new lru_cache_1.LRUCache({ max: config.maxSize || 1000, ttl: config.maxAge || 300000, updateAgeOnGet: config.updateAgeOnGet ?? true }); } set(key, value, ttl) { this.cache.set(key, value, { ttl }); } get(key) { const value = this.cache.get(key); if (value !== undefined) { this.hits++; return value; } this.misses++; return undefined; } has(key) { return this.cache.has(key); } delete(key) { return this.cache.delete(key); } clear() { this.cache.clear(); this.hits = 0; this.misses = 0; } getMetrics() { const total = this.hits + this.misses; return { hits: this.hits, misses: this.misses, hitRate: total > 0 ? (this.hits / total) * 100 : 0, size: this.cache.size }; } } exports.PerformanceCache = PerformanceCache; class ConnectionPool { constructor(createConnection, destroyConnection, config = {}) { this.connections = []; this.inUse = new Set(); this.waiting = []; this.idleTimers = new Map(); this.createConnection = createConnection; this.destroyConnection = destroyConnection; this.maxConnections = config.maxConnections || 10; this.idleTimeout = config.idleTimeout || 30000; this.acquireTimeout = config.acquireTimeout || 10000; } async acquire() { const idleConnection = this.connections.find(conn => !this.inUse.has(conn)); if (idleConnection) { this.inUse.add(idleConnection); this.clearIdleTimer(idleConnection); return idleConnection; } if (this.connections.length < this.maxConnections) { try { const newConnection = await this.createConnection(); this.connections.push(newConnection); this.inUse.add(newConnection); return newConnection; } catch (error) { throw new Error(`Failed to create connection: ${error.message}`); } } return new Promise((resolve, reject) => { const timeout = setTimeout(() => { const index = this.waiting.findIndex(w => w.resolve === resolve); if (index !== -1) { this.waiting.splice(index, 1); } reject(new Error('Connection acquire timeout')); }, this.acquireTimeout); this.waiting.push({ resolve, reject, timeout }); }); } release(connection) { if (!this.inUse.has(connection)) { return; } this.inUse.delete(connection); if (this.waiting.length > 0) { const waiter = this.waiting.shift(); clearTimeout(waiter.timeout); this.inUse.add(connection); waiter.resolve(connection); return; } this.setIdleTimer(connection); } setIdleTimer(connection) { const timer = setTimeout(async () => { if (!this.inUse.has(connection)) { try { await this.destroyConnection(connection); const index = this.connections.indexOf(connection); if (index !== -1) { this.connections.splice(index, 1); } this.idleTimers.delete(connection); } catch (error) { console.error('Error destroying idle connection:', error); } } }, this.idleTimeout); this.idleTimers.set(connection, timer); } clearIdleTimer(connection) { const timer = this.idleTimers.get(connection); if (timer) { clearTimeout(timer); this.idleTimers.delete(connection); } } getMetrics() { return { totalConnections: this.connections.length, activeConnections: this.inUse.size, idleConnections: this.connections.length - this.inUse.size, queuedRequests: this.waiting.length }; } async destroy() { this.waiting.forEach(waiter => { clearTimeout(waiter.timeout); waiter.reject(new Error('Connection pool destroyed')); }); this.waiting.length = 0; this.idleTimers.forEach(timer => clearTimeout(timer)); this.idleTimers.clear(); const destroyPromises = this.connections.map(conn => this.destroyConnection(conn)); await Promise.allSettled(destroyPromises); this.connections.length = 0; this.inUse.clear(); } } exports.ConnectionPool = ConnectionPool; class BatchProcessor { constructor(processor, maxBatchSize = 50, batchDelay = 10) { this.batch = []; this.batchTimeout = null; this.waitingResolvers = []; this.processor = processor; this.maxBatchSize = maxBatchSize; this.batchDelay = batchDelay; } async process(item) { return new Promise((resolve, reject) => { this.batch.push(item); this.waitingResolvers.push({ resolve, reject }); if (this.batch.length >= this.maxBatchSize) { this.processBatch(); } else if (!this.batchTimeout) { this.batchTimeout = setTimeout(() => { this.processBatch(); }, this.batchDelay); } }); } async processBatch() { if (this.batch.length === 0) return; const currentBatch = this.batch.splice(0); const currentResolvers = this.waitingResolvers.splice(0, currentBatch.length); if (this.batchTimeout) { clearTimeout(this.batchTimeout); this.batchTimeout = null; } try { const results = await this.processor(currentBatch); results.forEach((result, index) => { if (currentResolvers[index]) { currentResolvers[index].resolve(result); } }); } catch (error) { currentResolvers.forEach(resolver => { resolver.reject(error); }); } } } exports.BatchProcessor = BatchProcessor; class PerformanceMonitor { constructor() { this.metrics = { cacheHits: 0, cacheMisses: 0, averageExecutionTime: 0, activeConnections: 0, queuedRequests: 0 }; this.executionTimes = []; this.maxExecutionTimesSamples = 100; } recordExecutionTime(time) { this.executionTimes.push(time); if (this.executionTimes.length > this.maxExecutionTimesSamples) { this.executionTimes.shift(); } const sum = this.executionTimes.reduce((a, b) => a + b, 0); this.metrics.averageExecutionTime = sum / this.executionTimes.length; } updateCacheMetrics(hits, misses) { this.metrics.cacheHits = hits; this.metrics.cacheMisses = misses; } updateConnectionMetrics(active, queued) { this.metrics.activeConnections = active; this.metrics.queuedRequests = queued; } getMetrics() { return { ...this.metrics }; } getDetailedStats() { const totalCacheRequests = this.metrics.cacheHits + this.metrics.cacheMisses; const cacheHitRate = totalCacheRequests > 0 ? (this.metrics.cacheHits / totalCacheRequests) * 100 : 0; return { ...this.metrics, cacheHitRate, executionTimeSamples: this.executionTimes.length, medianExecutionTime: this.calculateMedian(this.executionTimes), p95ExecutionTime: this.calculatePercentile(this.executionTimes, 95) }; } calculateMedian(arr) { if (arr.length === 0) return 0; const sorted = [...arr].sort((a, b) => a - b); const mid = Math.floor(sorted.length / 2); return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]; } calculatePercentile(arr, percentile) { if (arr.length === 0) return 0; const sorted = [...arr].sort((a, b) => a - b); const index = Math.ceil((percentile / 100) * sorted.length) - 1; return sorted[Math.max(0, index)]; } } exports.PerformanceMonitor = PerformanceMonitor; function debounce(func, delay) { let timeoutId; return (...args) => { return new Promise((resolve, reject) => { clearTimeout(timeoutId); timeoutId = setTimeout(async () => { try { const result = await func(...args); resolve(result); } catch (error) { reject(error); } }, delay); }); }; } function throttle(func, delay) { let lastCall = 0; return async (...args) => { const now = Date.now(); if (now - lastCall >= delay) { lastCall = now; return await func(...args); } return null; }; } exports.REQUIRED_DEPENDENCIES = { 'lru-cache': '^10.1.0' }; //# sourceMappingURL=performanceOptimizations.js.map