UNPKG

@gati-framework/runtime

Version:

Gati runtime execution engine for running handler-based applications

177 lines 4.75 kB
/** * @module runtime/debug-gate-manager * @description Manages debug gates for pausing execution */ import { EventEmitter } from 'events'; /** * Manages debug gates for execution control */ export class DebugGateManager extends EventEmitter { gates = new Map(); pausedExecutions = new Map(); config; constructor(config = {}) { super(); this.config = { enabled: config.enabled ?? false, defaultTimeout: config.defaultTimeout ?? 300000, // 5 minutes }; } /** * Create a debug gate */ createGate(traceId, stage, condition) { const gate = { id: `gate_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`, traceId, stage, condition, status: 'active', createdAt: Date.now(), }; this.gates.set(gate.id, gate); return gate; } /** * Check if execution should pause at gate */ async checkGate(traceId, stage, context) { if (!this.config.enabled) return; const gate = this.findActiveGate(traceId, stage); if (!gate) return; // Evaluate condition if present if (gate.condition && !this.evaluateCondition(gate.condition, context)) { return; } // Trigger gate gate.status = 'triggered'; gate.triggeredAt = Date.now(); this.emit('gate:triggered', { gateId: gate.id, traceId, stage, timestamp: Date.now(), }); // Pause execution await this.pauseExecution(gate.id); } /** * Release a gate and resume execution */ releaseGate(gateId) { const gate = this.gates.get(gateId); if (!gate) return false; gate.status = 'released'; const paused = this.pausedExecutions.get(gateId); if (paused) { if (paused.timeout) clearTimeout(paused.timeout); paused.resolve(); this.pausedExecutions.delete(gateId); } this.emit('gate:released', { gateId, timestamp: Date.now() }); return true; } /** * Remove a gate */ removeGate(gateId) { const gate = this.gates.get(gateId); if (!gate) return false; // Release if triggered if (gate.status === 'triggered') { this.releaseGate(gateId); } return this.gates.delete(gateId); } /** * Get gate by ID */ getGate(gateId) { return this.gates.get(gateId) || null; } /** * List all gates for a trace */ listGates(traceId) { const gates = Array.from(this.gates.values()); return traceId ? gates.filter(g => g.traceId === traceId) : gates; } /** * Clear all gates */ clear() { // Release all paused executions for (const gateId of this.pausedExecutions.keys()) { this.releaseGate(gateId); } this.gates.clear(); } /** * Enable debug gates */ enable() { this.config.enabled = true; } /** * Disable debug gates */ disable() { this.config.enabled = false; } /** * Check if enabled */ isEnabled() { return this.config.enabled; } /** * Find active gate for trace and stage */ findActiveGate(traceId, stage) { for (const gate of this.gates.values()) { if (gate.traceId === traceId && gate.stage === stage && gate.status === 'active') { return gate; } } return null; } /** * Pause execution until gate is released */ pauseExecution(gateId) { return new Promise((resolve) => { const timeout = setTimeout(() => { this.releaseGate(gateId); }, this.config.defaultTimeout); this.pausedExecutions.set(gateId, { resolve, timeout }); }); } /** * Evaluate gate condition */ evaluateCondition(condition, context) { if (!context) return true; try { // Simple condition evaluation (e.g., "userId === '123'") // In production, use a safe expression evaluator const func = new Function('context', `with(context) { return ${condition}; }`); return func(context); } catch { return false; } } } /** * Create a debug gate manager instance */ export function createDebugGateManager(config) { return new DebugGateManager(config); } //# sourceMappingURL=debug-gate-manager.js.map