UNPKG

cubeforall-dbconnection

Version:

A centralized MongoDB connection handler with connection pooling and graceful shutdown support.

161 lines (141 loc) 4.98 kB
const { MongoClient } = require("mongodb"); const dotenv = require("dotenv"); dotenv.config(); const { ObjectId, GridFSBucket, Timestamp, Binary } = require("mongodb"); const mongoClients = {}; // Store clients dynamically /** * Initialize a MongoDB connection dynamically with retry * @param {string} name - Connection name (e.g., "boxMongo", "platformMongo") * @param {string} url - MongoDB connection URL * @param {object} options - Additional connection options (optional) * @param {number} retryAttempts - Number of retry attempts (default 3) * @param {number} retryInterval - Interval between retries in ms (default 1000ms) */ async function connectMongoDB(name, url, options = {}, retryAttempts = 3, retryInterval = 1000) { if (!url) throw new Error(`Database URL for ${name} is required.`); // If connection exists and is active, return it if (mongoClients[name] && mongoClients[name].topology?.isConnected()) { return mongoClients[name]; } let attempt = 0; let connected = false; const clientOptions = { maxPoolSize: 10, minPoolSize: 5, maxIdleTimeMS: 30000, useUnifiedTopology: true, ...options, }; while (attempt < retryAttempts && !connected) { try { console.log(`🔄 Connecting to MongoDB (${name}), Attempt ${attempt + 1}/${retryAttempts}`); mongoClients[name] = new MongoClient(url, clientOptions); await mongoClients[name].connect(); connected = true; console.log(`✅ Connected to MongoDB (${name})`); return mongoClients[name]; } catch (err) { console.error(`❌ Failed to connect to MongoDB (${name}) on attempt ${attempt + 1}:`, err.message); attempt++; if (attempt < retryAttempts) { await new Promise((resolve) => setTimeout(resolve, retryInterval)); } else { throw new Error(`Failed to connect to MongoDB (${name}) after ${retryAttempts} attempts.`); } } } } /** * Get a database instance from the specified connection * @param {string} name - Connection name * @param {string} dbName - Database name */ async function getDatabase(name, dbName) { const client = mongoClients[name]; if (!client) throw new Error(`No active connection found for ${name}`); return client.db(dbName); } /** * Get a collection from a specific database * @param {string} name - Connection name * @param {string} dbName - Database name * @param {string} collectionName - Collection name */ async function getCollection(name, dbName, collectionName) { const client = mongoClients[name]; if (!client || !client.topology?.isConnected()) { throw new Error(`No active connection found for ${name}. Make sure connectMongoDB() was called.`); } const db = await getDatabase(name, dbName); return db.collection(collectionName); } /** * Get raw MongoClient instance * @param {string} name - Connection name */ function getClient(name) { return mongoClients[name] || null; } /** * Close all active MongoDB connections */ async function closeAllConnections() { for (const [name, client] of Object.entries(mongoClients)) { if (client) { await client.close(); console.log(`🛑 MongoDB connection (${name}) closed.`); } } } /** * Get MongoDB server connection statuses */ async function getMongoDBStatus() { const statuses = {}; try { for (const name of Object.keys(mongoClients)) { const client = mongoClients[name]; if (client && client.topology?.isConnected()) { const adminDb = client.db("admin"); const status = await adminDb.command({ serverStatus: 1 }); statuses[name] = status.connections; } else { statuses[name] = "Disconnected"; } } } catch (error) { console.error("Error fetching MongoDB status:", error); return { error: "Failed to fetch MongoDB connection status" }; } return statuses; } // Automatically close all connections on exit process.on('exit', async () => { console.log('Process is exiting...'); await closeAllConnections(); }); // Handle uncaught exceptions to ensure connections are closed process.on('uncaughtException', async (err) => { console.error('Uncaught exception:', err); await closeAllConnections(); process.exit(1); }); // Handle uncaught promise rejections process.on('unhandledRejection', async (reason) => { console.error('Unhandled rejection:', reason); await closeAllConnections(); process.exit(1); }); module.exports = { connectMongoDB, getDatabase, getCollection, getClient, closeAllConnections, getMongoDBStatus, // Expose commonly used MongoDB classes ObjectId, GridFSBucket, Timestamp, Binary, };