UNPKG

@ufdevsllc/authme2.0

Version:

SDK for license management and remote monitoring with automatic system tracking, license validation, and remote control capabilities

299 lines (269 loc) 10.6 kB
import mongoose from 'mongoose'; class DatabaseManager { constructor(errorHandler = null) { this.monitoringConnection = null; this.isConnected = false; this.connectionString = process.env.MONGODB_URI || 'mongodb+srv://incrypto09:VcFzmdvSgSbqHx5m@transcoding.jcngo.mongodb.net/?retryWrites=true&w=majority&appName=transcoding'; this.databaseName = process.env.MONGODB_DB_NAME || 'authme20'; this.maxRetries = 5; this.retryDelay = 1000; // Start with 1 second this.errorHandler = errorHandler; } /** * Initialize connection to monitoring database * @returns {Promise<void>} */ async initMonitoringConnection() { if (this.isConnected && this.monitoringConnection) { return; } let retries = 0; while (retries < this.maxRetries) { try { // Create a new connection for monitoring database this.monitoringConnection = mongoose.createConnection(this.connectionString, { dbName: this.databaseName, maxPoolSize: 10, serverSelectionTimeoutMS: 5000, socketTimeoutMS: 45000, bufferCommands: false }); // Wait for connection to be established await new Promise((resolve, reject) => { this.monitoringConnection.once('open', resolve); this.monitoringConnection.once('error', reject); }); this.isConnected = true; // Set up connection event handlers this.setupConnectionHandlers(); if (this.errorHandler) { await this.errorHandler.logInfo('Successfully connected to monitoring database', { component: 'database-manager', operation: 'init-connection', database: this.databaseName }); } else { console.log('Successfully connected to monitoring database'); } return; } catch (error) { retries++; if (this.errorHandler) { await this.errorHandler.handleDatabaseError(error, { type: 'connection', database: this.databaseName }, retries); } else { console.error(`Database connection attempt ${retries} failed:`, error.message); } if (retries >= this.maxRetries) { throw new Error(`Failed to connect to monitoring database after ${this.maxRetries} attempts: ${error.message}`); } // Exponential backoff const delay = this.retryDelay * Math.pow(2, retries - 1); if (this.errorHandler) { await this.errorHandler.logWarn(`Retrying connection in ${delay}ms...`, { component: 'database-manager', operation: 'retry-connection', attempt: retries, delay }); } else { console.log(`Retrying connection in ${delay}ms...`); } await this.sleep(delay); } } } /** * Set up connection event handlers for monitoring and reconnection */ setupConnectionHandlers() { if (!this.monitoringConnection) return; this.monitoringConnection.on('error', async (error) => { if (this.errorHandler) { await this.errorHandler.handleDatabaseError(error, { type: 'connection-error', database: this.databaseName }); } else { console.error('Monitoring database connection error:', error); } this.isConnected = false; }); this.monitoringConnection.on('disconnected', async () => { if (this.errorHandler) { await this.errorHandler.logWarn('Monitoring database disconnected', { component: 'database-manager', operation: 'connection-lost', database: this.databaseName }); } else { console.warn('Monitoring database disconnected'); } this.isConnected = false; // Attempt to reconnect this.handleReconnection(); }); this.monitoringConnection.on('reconnected', async () => { if (this.errorHandler) { await this.errorHandler.logInfo('Monitoring database reconnected', { component: 'database-manager', operation: 'reconnection-success', database: this.databaseName }); } else { console.log('Monitoring database reconnected'); } this.isConnected = true; }); } /** * Handle reconnection logic */ async handleReconnection() { if (this.isConnected) return; try { await this.initMonitoringConnection(); } catch (error) { if (this.errorHandler) { await this.errorHandler.handleDatabaseError(error, { type: 'reconnection-failed', database: this.databaseName }); } else { console.error('Failed to reconnect to monitoring database:', error.message); } // Schedule another reconnection attempt setTimeout(() => this.handleReconnection(), 10000); // Try again in 10 seconds } } /** * Get the monitoring database connection * @returns {mongoose.Connection} */ getMonitoringDB() { if (!this.isConnected || !this.monitoringConnection) { const error = new Error('Monitoring database not connected. Call initMonitoringConnection() first.'); if (this.errorHandler) { this.errorHandler.handleError(error, { component: 'database-manager', operation: 'get-connection', connectionState: this.isConnected ? 'connected' : 'disconnected' }); } throw error; } return this.monitoringConnection; } /** * Save user data to monitoring database * @param {string} collectionName - Name of the collection * @param {Object} data - Data to save * @returns {Promise<Object>} */ async saveUserData(collectionName, data) { // Validate inputs if (this.errorHandler) { const validation = this.errorHandler.validateInput(collectionName, { type: 'string', required: true, minLength: 1, maxLength: 100 }, { field: 'collectionName' }); if (!validation.isValid) { const error = new Error(`Invalid collection name: ${validation.errors.join(', ')}`); await this.errorHandler.handleError(error, { component: 'database-manager', operation: 'save-user-data', collectionName, validationErrors: validation.errors }); throw error; } } if (!this.isConnected) { const error = new Error('Monitoring database not connected'); if (this.errorHandler) { await this.errorHandler.handleDatabaseError(error, { type: 'save-operation', collection: collectionName }); } throw error; } const context = { component: 'database-manager', operation: 'save-user-data', collection: collectionName }; try { const collection = this.monitoringConnection.collection(collectionName); const result = await collection.insertOne({ ...data, timestamp: new Date(), _createdAt: new Date() }); if (this.errorHandler) { await this.errorHandler.logInfo(`Successfully saved data to collection: ${collectionName}`, context); } return result; } catch (error) { if (this.errorHandler) { await this.errorHandler.handleDatabaseError(error, { type: 'save-operation', collection: collectionName }); } throw error; } } /** * Check if monitoring database is connected * @returns {boolean} */ isMonitoringConnected() { return this.isConnected && this.monitoringConnection && this.monitoringConnection.readyState === 1; } /** * Close the monitoring database connection * @returns {Promise<void>} */ async closeConnection() { if (this.monitoringConnection) { const context = { component: 'database-manager', operation: 'close-connection', database: this.databaseName }; try { await this.monitoringConnection.close(); this.isConnected = false; if (this.errorHandler) { await this.errorHandler.logInfo('Monitoring database connection closed', context); } else { console.log('Monitoring database connection closed'); } } catch (error) { if (this.errorHandler) { await this.errorHandler.handleDatabaseError(error, { type: 'close-connection', database: this.databaseName }); } else { console.error('Error closing monitoring database connection:', error); } throw error; } } } /** * Utility function for sleep/delay * @param {number} ms - Milliseconds to sleep * @returns {Promise<void>} */ sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } export default DatabaseManager;