Skip to main content
Glama
asyncExecutionSystem.js7.78 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AsyncExecutionSystem = void 0; const operation_1 = require("./operation"); const operationRegistry_1 = require("./operationRegistry"); const types_1 = require("./types"); const StorageAdapterFactory_1 = require("./storage/StorageAdapterFactory"); const logger_1 = __importDefault(require("../utils/logger")); /** * AsyncExecutionSystem class * * Manages the execution of asynchronous operations. */ class AsyncExecutionSystem { /** * Get the singleton instance */ static getInstance() { if (!AsyncExecutionSystem.instance) { AsyncExecutionSystem.instance = new AsyncExecutionSystem(); } return AsyncExecutionSystem.instance; } /** * Constructor * * @param registry Optional operation registry * @param cleanupInterval Optional cleanup interval in milliseconds * @param maxOperationAge Optional maximum operation age in milliseconds */ constructor(storageOptions = {}, cleanupInterval = 60000, // Default: 1 minute maxOperationAge = 3600000 // Default: 1 hour ) { this.maxOperationAge = maxOperationAge; this.defaultOptions = { timeoutMs: 30000 // Default timeout: 30 seconds }; this.cleanupInterval = null; // Create the storage adapter this.storage = StorageAdapterFactory_1.StorageAdapterFactory.createAdapter(storageOptions); // Create the registry this.registry = new operationRegistry_1.OperationRegistry(this.storage); // Start the cleanup interval if (cleanupInterval > 0) { this.startCleanupInterval(cleanupInterval); } } /** * Execute an operation * * @param executor Operation executor function * @param options Operation options * @returns Operation result */ async executeOperation(executor, options) { try { // Merge options with defaults const mergedOptions = { ...this.defaultOptions, ...options }; // Create and register the operation const operation = new operation_1.Operation(executor, mergedOptions); await this.registry.registerOperation(operation); // Execute the operation const result = await operation.execute(); // Store the result await this.storage.storeResult(result); // If the operation is complete, unregister it if (result.isComplete) { await this.registry.unregisterOperation(result.logId); } return result; } catch (error) { logger_1.default.error(`Error executing operation: ${error instanceof Error ? error.message : String(error)}`); return { status: types_1.OperationStatus.ERROR, logId: 'error', error: error instanceof Error ? error.message : String(error), isComplete: true }; } } /** * Get a result by log ID * * @param logId Log ID * @returns Operation result */ async getResult(logId) { try { // Try to get the result from the registry const result = await this.registry.getOperationResult(logId); if (!result) { return { status: types_1.OperationStatus.ERROR, logId, error: `Result not found for log ID: ${logId}`, isComplete: true }; } return result; } catch (error) { logger_1.default.error(`Error getting result: ${error instanceof Error ? error.message : String(error)}`); return { status: types_1.OperationStatus.ERROR, logId, error: error instanceof Error ? error.message : String(error), isComplete: true }; } } /** * Cancel an operation * * @param logId Log ID * @returns Operation result */ async cancelOperation(logId) { try { // Try to cancel the operation const cancelled = await this.registry.cancelOperation(logId); if (!cancelled) { return { status: types_1.OperationStatus.ERROR, logId, error: `Operation not found for log ID: ${logId}`, isComplete: true }; } // Get the updated result const result = await this.getResult(logId); return { status: types_1.OperationStatus.SUCCESS, logId, message: `Operation cancelled: ${logId}`, isComplete: true }; } catch (error) { logger_1.default.error(`Error cancelling operation: ${error instanceof Error ? error.message : String(error)}`); return { status: types_1.OperationStatus.ERROR, logId, error: error instanceof Error ? error.message : String(error), isComplete: true }; } } /** * List all operations * * @returns Array of operation info */ async listOperations() { return await this.registry.listOperations(); } /** * Start the cleanup interval * * @param interval Cleanup interval in milliseconds */ startCleanupInterval(interval) { // Clear any existing interval if (this.cleanupInterval) { clearInterval(this.cleanupInterval); } // Start a new interval this.cleanupInterval = setInterval(async () => { try { await this.registry.cleanupCompletedOperations(this.maxOperationAge); } catch (error) { logger_1.default.error(`Error cleaning up operations: ${error instanceof Error ? error.message : String(error)}`); } }, interval); // Ensure the interval doesn't keep the process alive if (this.cleanupInterval.unref) { this.cleanupInterval.unref(); } } /** * Stop the cleanup interval */ stopCleanupInterval() { if (this.cleanupInterval) { clearInterval(this.cleanupInterval); this.cleanupInterval = null; } } /** * Generate a unique ID * * @returns Unique ID */ generateId() { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); } /** * Store a log entry * * @param logName Log name * @param logEntry Log entry * @returns Log ID */ async storeLogEntry(logName, logEntry) { const logId = this.generateId(); // Store the log entry await this.storage.storeLogEntry(logId, logName, logEntry); return logId; } /** * Get logs by name * * @param logName Log name * @param limit Maximum number of logs to return * @returns Logs */ async getLogsByName(logName, limit = 10) { return this.storage.getLogsByName(logName, limit); } /** * Dispose of the AsyncExecutionSystem */ async dispose() { this.stopCleanupInterval(); await this.storage.close(); } } exports.AsyncExecutionSystem = AsyncExecutionSystem;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TSavo/Unity-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server