ms-analysis-reports-mcp-server
Version: 
PMS analysis reports server handling maintenance reports, equipment analysis, compliance tracking, and performance metrics with ERP access for data extraction
231 lines • 8.19 kB
JavaScript
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { MongoClient } from 'mongodb';
import { logger } from '../index.js';
// ============================================================================
// 🔧 DOMAIN-SPECIFIC CONFIGURATION - CUSTOMIZE FOR NEW MCP SERVERS
// ============================================================================
/**
 * Companies that should skip validation entirely
 * CUSTOMIZE: Add your development/test company names here
 */
const SKIP_VALIDATION_COMPANIES = ['synergy', 'development', 'test'];
/**
 * Database collection and field names for your authorization system
 * CUSTOMIZE: Change these to match your database schema
 */
const IMO_COLLECTION_NAME = 'common_group_details';
const IMO_FIELD_NAME = 'imoList';
const COMPANY_FIELD_NAME = 'groupName';
const DATABASE_NAME = 'syia-etl-dev';
/**
 * Cache file configuration
 * CUSTOMIZE: Change cache file name if needed
 */
const CACHE_FILENAME = 'company-imos.json';
// ============================================================================
// END CUSTOMIZABLE SECTION
// ============================================================================
// File path setup
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const DATA_DIR = join(__dirname, '../../data');
const CACHE_FILE = join(DATA_DIR, CACHE_FILENAME);
// In-memory storage
let companyImoCache = null;
// MongoDB connection options for better performance
const MONGO_OPTIONS = {
    maxPoolSize: 1,
    minPoolSize: 0,
    maxIdleTimeMS: 30000,
    serverSelectionTimeoutMS: 10000,
    connectTimeoutMS: 10000,
};
/**
 * Ensure data directory exists
 */
function ensureDataDirectory() {
    if (!existsSync(DATA_DIR)) {
        mkdirSync(DATA_DIR, { recursive: true });
        logger.debug('Created data directory for IMO cache');
    }
}
/**
 * Fetch IMO numbers for a company from MongoDB
 */
async function fetchCompanyImoNumbers(companyName) {
    let client = null;
    try {
        logger.info(`Fetching IMO numbers for company: ${companyName}`);
        if (!process.env.MONGODB_ETL_DEV_DATA_URI) {
            throw new Error('MONGODB_ETL_DEV_DATA_URI environment variable is required');
        }
        // Create optimized MongoDB client
        client = new MongoClient(process.env.MONGODB_ETL_DEV_DATA_URI, MONGO_OPTIONS);
        await client.connect();
        const db = client.db(DATABASE_NAME);
        const collection = db.collection(IMO_COLLECTION_NAME);
        // Query with timeout for reliability
        const result = await collection.findOne({ [COMPANY_FIELD_NAME]: companyName }, {
            projection: { imoList: 1, _id: 0 },
            maxTimeMS: 10000 // 10 second timeout
        });
        if (!result?.[IMO_FIELD_NAME] || !Array.isArray(result[IMO_FIELD_NAME])) {
            logger.warn(`No IMO numbers found for company: ${companyName}`);
            return [];
        }
        // Convert and validate IMO numbers
        const imoNumbers = result[IMO_FIELD_NAME]
            .filter(imo => typeof imo === 'number' && imo > 0)
            .map(imo => imo.toString());
        logger.info(`Found ${imoNumbers.length} valid IMO numbers for company: ${companyName}`);
        // Update in-memory cache
        companyImoCache = {
            companyName,
            imoNumbers,
            lastUpdated: new Date().toISOString()
        };
        return imoNumbers;
    }
    catch (error) {
        logger.error(`Error fetching IMO numbers for company ${companyName}:`, error);
        throw error;
    }
    finally {
        // Always close connection
        if (client) {
            try {
                await client.close();
            }
            catch (closeError) {
                logger.warn('Error closing MongoDB connection:', closeError);
            }
        }
    }
}
/**
 * Get cached company IMO numbers from memory
 */
function getCompanyImoNumbers() {
    return companyImoCache?.imoNumbers || [];
}
/**
 * Load cached IMO numbers from file
 */
export function loadCachedImos() {
    try {
        if (!existsSync(CACHE_FILE)) {
            logger.debug('IMO cache file does not exist');
            return [];
        }
        const data = readFileSync(CACHE_FILE, 'utf8');
        const cacheData = JSON.parse(data);
        // Validate cache structure
        if (!cacheData?.imoNumbers || !Array.isArray(cacheData.imoNumbers)) {
            logger.warn('Invalid cache file structure, ignoring cached data');
            return [];
        }
        // Update in-memory cache if valid
        companyImoCache = cacheData;
        logger.debug(`Loaded ${cacheData.imoNumbers.length} IMO numbers from cache file`);
        return cacheData.imoNumbers;
    }
    catch (error) {
        logger.warn('Failed to load cached IMOs, cache file may be corrupted:', error);
        return [];
    }
}
/**
 * Save IMO numbers to cache file
 */
export function saveCachedImos(imos, companyName) {
    try {
        ensureDataDirectory();
        const cacheData = {
            companyName,
            imoNumbers: imos,
            lastUpdated: new Date().toISOString()
        };
        writeFileSync(CACHE_FILE, JSON.stringify(cacheData, null, 2), 'utf8');
        logger.info(`Successfully cached ${imos.length} IMO numbers to file`);
    }
    catch (error) {
        logger.error('Failed to save IMO cache to file:', error);
    }
}
/**
 * Check if company should skip IMO validation (e.g., for development/testing)
 */
export function shouldSkipImoValidation(companyName) {
    return SKIP_VALIDATION_COMPANIES.includes(companyName.toLowerCase());
}
/**
 * Initialize IMO cache for the specified company
 */
export async function initializeImoCache(companyName) {
    try {
        logger.info(`Initializing IMO cache for company: "${companyName}"`);
        // Skip IMO initialization for special companies
        if (shouldSkipImoValidation(companyName)) {
            logger.info(`Skipping IMO cache initialization for company: "${companyName}" (no IMO validation required)`);
            clearCache(); // Clear any existing cache
            return;
        }
        // Clear existing cache to ensure fresh start
        clearCache();
        // Fetch fresh data from MongoDB
        const imos = await fetchCompanyImoNumbers(companyName);
        if (imos.length > 0) {
            // Save to file cache for persistence  
            saveCachedImos(imos, companyName);
            logger.info(`Successfully initialized IMO cache with ${imos.length} numbers for: "${companyName}"`);
        }
        else {
            logger.warn(`No IMO numbers found for company: "${companyName}". Cache remains empty.`);
        }
    }
    catch (error) {
        logger.error(`Failed to initialize IMO cache for company "${companyName}":`, error);
        // Try to load from file cache as fallback
        const cachedImos = loadCachedImos();
        if (cachedImos.length > 0) {
            logger.info(`Using cached IMO data as fallback (${cachedImos.length} IMOs)`);
        }
    }
}
/**
 * Get company IMOs with intelligent fallback strategy
 */
export function getCompanyImosWithFallback() {
    // Try in-memory cache first (fastest)
    let imos = getCompanyImoNumbers();
    // Fallback to file cache if memory is empty
    if (imos.length === 0) {
        imos = loadCachedImos();
        if (imos.length > 0) {
            logger.info(`Using cached IMO numbers from file (${imos.length} IMOs)`);
        }
    }
    return imos;
}
/**
 * Get cache status for monitoring/debugging
 */
export function getCacheStatus() {
    return {
        inMemory: companyImoCache !== null,
        inMemoryCount: companyImoCache?.imoNumbers?.length || 0,
        fileExists: existsSync(CACHE_FILE),
        lastUpdated: companyImoCache?.lastUpdated,
        companyName: companyImoCache?.companyName
    };
}
/**
 * Clear all cached data (for testing/reset purposes)
 */
export function clearCache() {
    companyImoCache = null;
    logger.debug('Cleared in-memory IMO cache');
}
//# sourceMappingURL=imoCache.js.map