syia-mcp-utils
Version:
Global utility functions for MCP server
243 lines (242 loc) • 9.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.initializeConnections = initializeConnections;
exports.getMongoClient = getMongoClient;
exports.getDevApiClient = getDevApiClient;
exports.getEtlDevClient = getEtlDevClient;
exports.getEtlDevDataClient = getEtlDevDataClient;
exports.getEtlDevDataDbName = getEtlDevDataDbName;
exports.getDevApiDbName = getDevApiDbName;
exports.getEtlDevDbName = getEtlDevDbName;
exports.getConnectionStatus = getConnectionStatus;
exports.closeConnections = closeConnections;
const mongodb_1 = require("mongodb");
const logger_js_1 = require("./logger.js");
const config_1 = require("./config");
// MongoDB connection options for better resilience
const mongoOptions = {
serverApi: {
version: mongodb_1.ServerApiVersion.v1,
strict: true,
deprecationErrors: true,
},
maxPoolSize: 10,
minPoolSize: 5,
maxIdleTimeMS: 60000,
connectTimeoutMS: 30000,
socketTimeoutMS: 45000,
retryWrites: true,
retryReads: true,
};
// Main MongoDB clients
let client = null;
let secondaryClient = null;
// Specific database clients
let devApiClient = null;
let etlDevClient = null;
let etlDevDataClient = null;
// Connection status tracking
const connectionStatus = {
primary: false,
secondary: false,
devApi: false,
etlDev: false,
etlDevData: false,
};
/**
* Connect to MongoDB with retry logic
* @param uri MongoDB connection URI
* @param name Connection name for logging
* @returns MongoDB client instance
*/
async function connectWithRetry(uri, name) {
const maxRetries = 5;
const retryDelayMs = 2000;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const client = new mongodb_1.MongoClient(uri, mongoOptions);
await client.connect();
// Verify connection by pinging the database
await client.db().command({ ping: 1 });
logger_js_1.logger.info(`Connected to ${name} MongoDB instance (attempt ${attempt})`);
return client;
}
catch (error) {
logger_js_1.logger.error(`Failed to connect to ${name} MongoDB (attempt ${attempt}/${maxRetries}):`, error);
if (attempt === maxRetries) {
logger_js_1.logger.error(`Max retries reached for ${name} MongoDB connection`);
return null;
}
// Wait before retrying
logger_js_1.logger.info(`Retrying ${name} MongoDB connection in ${retryDelayMs}ms...`);
await new Promise(resolve => setTimeout(resolve, retryDelayMs));
}
}
return null;
}
/**
* Initialize all MongoDB connections
* This should be called during server startup
*/
async function initializeConnections() {
// Skip MongoDB connection in test environment
if (process.env.NODE_ENV === 'test') {
logger_js_1.logger.info('Test environment detected, skipping MongoDB connections');
return;
}
try {
// Initialize primary connection
if (!client && (0, config_1.getConfig)().mongoUri) {
client = await connectWithRetry((0, config_1.getConfig)().mongoUri, 'primary');
connectionStatus.primary = client !== null;
}
// Initialize secondary connection if configured
if (!secondaryClient && (0, config_1.getConfig)().secondaryMongoUri) {
secondaryClient = await connectWithRetry((0, config_1.getConfig)().secondaryMongoUri, 'secondary');
connectionStatus.secondary = secondaryClient !== null;
}
// Initialize dev-api connection
if (!devApiClient && (0, config_1.getConfig)().devApiMongoUri) {
devApiClient = await connectWithRetry((0, config_1.getConfig)().devApiMongoUri, 'dev-syia-api');
connectionStatus.devApi = devApiClient !== null;
}
// Initialize etl-dev connection
if (!etlDevClient && (0, config_1.getConfig)().etlDevMongoUri) {
etlDevClient = await connectWithRetry((0, config_1.getConfig)().etlDevMongoUri, 'syia-etl-dev');
connectionStatus.etlDev = etlDevClient !== null;
}
// Initialize etl-dev-data connection
if (!etlDevDataClient && (0, config_1.getConfig)().etlDevDataUri) {
etlDevDataClient = await connectWithRetry((0, config_1.getConfig)().etlDevDataUri, 'syia-etl-dev-data');
connectionStatus.etlDevData = etlDevDataClient !== null;
}
// Check if primary connection is established
if (!connectionStatus.primary) {
throw new Error('Failed to establish primary MongoDB connection');
}
logger_js_1.logger.info('MongoDB connections initialized', { connectionStatus });
}
catch (error) {
logger_js_1.logger.error('Error initializing MongoDB connections:', error);
throw error;
}
}
/**
* Get MongoDB client based on URI or default
*/
async function getMongoClient(uri) {
// Skip MongoDB connection in test environment
if (process.env.NODE_ENV === 'test') {
logger_js_1.logger.info('Test environment detected, skipping MongoDB connection');
return {};
}
// If URI is provided, use it for a specific connection
if (uri) {
// Check for dev-api connection
if (uri === (0, config_1.getConfig)().devApiMongoUri) {
if (!devApiClient) {
// If not initialized during startup, initialize now
devApiClient = await connectWithRetry(uri, 'dev-syia-api');
connectionStatus.devApi = devApiClient !== null;
}
return devApiClient || {};
}
// Check for etl-dev connection
if (uri === (0, config_1.getConfig)().etlDevMongoUri) {
if (!etlDevClient) {
// If not initialized during startup, initialize now
etlDevClient = await connectWithRetry(uri, 'syia-etl-dev');
connectionStatus.etlDev = etlDevClient !== null;
}
return etlDevClient || {};
}
// Check for etl-dev-data connection
if (uri === (0, config_1.getConfig)().etlDevDataUri) {
if (!etlDevDataClient) {
// If not initialized during startup, initialize now
etlDevDataClient = await connectWithRetry(uri, 'syia-etl-dev-data');
connectionStatus.etlDevData = etlDevDataClient !== null;
}
return etlDevDataClient || {};
}
// Check for secondary connection
if (uri === (0, config_1.getConfig)().secondaryMongoUri) {
if (!secondaryClient) {
// If not initialized during startup, initialize now
secondaryClient = await connectWithRetry(uri, 'secondary');
connectionStatus.secondary = secondaryClient !== null;
}
return secondaryClient || {};
}
// For custom URI, create a new connection
logger_js_1.logger.info('Creating new MongoDB connection for custom URI');
const customClient = await connectWithRetry(uri, 'custom');
return customClient || {};
}
// Use primary connection by default
if (!client) {
// If not initialized during startup, initialize now
client = await connectWithRetry((0, config_1.getConfig)().mongoUri, 'primary');
connectionStatus.primary = client !== null;
}
return client || {};
}
// Remaining helper functions for specific clients
async function getDevApiClient() {
return getMongoClient((0, config_1.getConfig)().devApiMongoUri);
}
async function getEtlDevClient() {
return getMongoClient((0, config_1.getConfig)().etlDevMongoUri);
}
async function getEtlDevDataClient() {
return getMongoClient((0, config_1.getConfig)().etlDevDataUri);
}
function getEtlDevDataDbName() {
return (0, config_1.getConfig)().etlDevDataDbName;
}
function getDevApiDbName() {
return (0, config_1.getConfig)().devApiDbName;
}
function getEtlDevDbName() {
return (0, config_1.getConfig)().etlDevDbName;
}
/**
* Get connection status for monitoring
*/
function getConnectionStatus() {
return { ...connectionStatus };
}
/**
* Close all MongoDB connections
*/
async function closeConnections() {
logger_js_1.logger.info('Closing MongoDB connections...');
const closePromises = [];
if (client) {
closePromises.push(client.close().catch(err => {
logger_js_1.logger.error('Error closing primary MongoDB connection:', err);
}));
}
if (secondaryClient) {
closePromises.push(secondaryClient.close().catch(err => {
logger_js_1.logger.error('Error closing secondary MongoDB connection:', err);
}));
}
if (devApiClient) {
closePromises.push(devApiClient.close().catch(err => {
logger_js_1.logger.error('Error closing dev-api MongoDB connection:', err);
}));
}
if (etlDevClient) {
closePromises.push(etlDevClient.close().catch(err => {
logger_js_1.logger.error('Error closing etl-dev MongoDB connection:', err);
}));
}
if (etlDevDataClient) {
closePromises.push(etlDevDataClient.close().catch(err => {
logger_js_1.logger.error('Error closing etl-dev-data MongoDB connection:', err);
}));
}
await Promise.all(closePromises);
logger_js_1.logger.info('All MongoDB connections closed');
}