UNPKG

@cyanheads/pubmed-mcp-server

Version:

Production-ready PubMed Model Context Protocol (MCP) server that empowers AI agents and research tools with comprehensive access to PubMed's article database. Enables advanced, automated LLM workflows for searching, retrieving, analyzing, and visualizing

94 lines 3.89 kB
/** * @fileoverview Manages a queue for NCBI E-utility requests to ensure compliance with rate limits. * @module src/services/NCBI/core/ncbiRequestQueueManager */ import { config } from "../../../config/index.js"; import { logger, requestContextService, sanitizeInputForLogging, } from "../../../utils/index.js"; export class NcbiRequestQueueManager { requestQueue = []; isProcessingQueue = false; lastRequestTime = 0; constructor() { // The constructor is kept for future initializations, if any. } /** * Processes the request queue, ensuring delays between requests to respect NCBI rate limits. */ async processQueue() { if (this.isProcessingQueue || this.requestQueue.length === 0) { return; } this.isProcessingQueue = true; const requestItem = this.requestQueue.shift(); if (!requestItem) { this.isProcessingQueue = false; return; } const { resolve, reject, task, context, endpoint, params } = requestItem; try { const now = Date.now(); const timeSinceLastRequest = now - this.lastRequestTime; const delayNeeded = config.ncbiRequestDelayMs - timeSinceLastRequest; if (delayNeeded > 0) { logger.debug(`Delaying NCBI request by ${delayNeeded}ms to respect rate limit.`, requestContextService.createRequestContext({ ...context, operation: "NCBI_RateLimitDelay", delayNeeded, endpoint, })); await new Promise((r) => setTimeout(r, delayNeeded)); } this.lastRequestTime = Date.now(); logger.info(`Executing NCBI request via queue: ${endpoint}`, requestContextService.createRequestContext({ ...context, operation: "NCBI_ExecuteFromQueue", endpoint, params: sanitizeInputForLogging(params), })); const result = await task(); resolve(result); } catch (error) { logger.error("Error processing NCBI request from queue", error instanceof Error ? error : new Error(String(error)), requestContextService.createRequestContext({ ...context, operation: "NCBI_QueueError", endpoint, params: sanitizeInputForLogging(params), errorMessage: error?.message, })); reject(error); } finally { this.isProcessingQueue = false; if (this.requestQueue.length > 0) { // Ensure processQueue is called without awaiting it here to prevent deep stacks Promise.resolve().then(() => this.processQueue()); } } } /** * Enqueues a task (an NCBI API call) to be processed. * @param task A function that returns a Promise resolving to the API call result. * @param context The request context for logging and correlation. * @param endpoint The NCBI endpoint being called (e.g., "esearch", "efetch"). * @param params The parameters for the NCBI request. * @returns A Promise that resolves or rejects with the result of the task. */ enqueueRequest(task, context, endpoint, params) { return new Promise((resolve, reject) => { this.requestQueue.push({ resolve, reject, task, context, endpoint, params, }); if (!this.isProcessingQueue) { // Ensure processQueue is called without awaiting it here Promise.resolve().then(() => this.processQueue()); } }); } } //# sourceMappingURL=ncbiRequestQueueManager.js.map