UNPKG

fortify2-js

Version:

MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.

437 lines (433 loc) 15.6 kB
'use strict'; var events = require('events'); var fs = require('fs'); var path = require('path'); var index$1 = require('../../../../components/fortified-function/index.js'); var cacheSys = require('../../../../components/cache/cacheSys.js'); var index = require('../../../../components/cache/index.js'); var SecureCacheAdapter = require('../../cache/SecureCacheAdapter.js'); var Logger = require('../../server/utils/Logger.js'); /** * Cluster Persistence Manager * Handles saving and loading cluster state to/from various storage backends */ //SCA = SecureCacheAdapter class ClusterPersistenceManager extends events.EventEmitter { constructor(config) { super(); this.memoryCache = index.Cache; this.redisClient = null; this.config = config; this.initializeStorage(); } /** * Initialize storage backend */ async initializeStorage() { try { switch (this.config.type) { case "redis": await this.initializeRedis(); break; case "file": await this.initializeFileStorage(); break; case "memory": await this.initializeMemoryStorage(); break; case "custom": Logger.logger.info("cluster", "Using custom persistence handlers"); break; default: throw new Error(`Unsupported persistence type: ${this.config.type}`); } Logger.logger.info("cluster", `Cluster persistence initialized (${this.config.type})`); } catch (error) { console.warn(`Failed to initialize persistence: ${error.message}`); this.emit("persistence:error", error); } } /** * Initialize Redis storage using SCA */ async initializeRedis() { try { const redisConfig = this.config.redis || { host: "localhost", port: 6379, }; // Initialize SCA with Redis support for better performance this.SCA = new SecureCacheAdapter.SecureCacheAdapter({ strategy: "hybrid", // Use hybrid strategy for maximum performance redis: { host: redisConfig.host, port: redisConfig.port, password: redisConfig.password, db: redisConfig.db || 0, }, memory: { maxSize: 50, // 50MB memory cache ttl: redisConfig.ttl || 86400000, // 24 hours algorithm: "lru", }, performance: { compressionThreshold: 1024, // Compress data > 1KB asyncWrite: true, pipeline: true, connectionPooling: true, }, security: { encryption: true, accessMonitoring: true, auditLogging: false, // Disable for performance }, resilience: { retryAttempts: 3, retryDelay: 100, circuitBreaker: true, fallback: true, }, }); Logger.logger.info("cluster", `Redis storage initialized with SCA: ${redisConfig.host}:${redisConfig.port}`); } catch (error) { console.warn("Redis not available, falling back to file storage"); this.config.type = "file"; await this.initializeFileStorage(); } } /** * Initialize file storage using FortifyJS FileCache */ async initializeFileStorage() { const fileConfig = this.config.file || { path: path.join(process.cwd(), ".nehonix", "cluster"), backup: true, maxBackups: 5, }; // Initialize FileCache with security and compression const cacheOptions = { directory: fileConfig.path, encrypt: true, // Enable encryption for security compress: true, // Enable compression for efficiency maxCacheSize: 100 * 1024 * 1024, // 100MB max cache size namingStrategy: "hierarchical", }; this.fileCache = new cacheSys.FileCache(cacheOptions); Logger.logger.info("cluster", `File storage initialized with FileCache: ${fileConfig.path}`); } /** * Initialize memory storage */ async initializeMemoryStorage() { const memoryConfig = this.config.memory || { maxSize: 100, ttl: 3600000, // 1 hour }; // Clean up expired entries periodically setInterval(() => { this.cleanupMemoryStorage(); }, 60000); // Every minute Logger.logger.info("cluster", `Memory storage initialized (max: ${memoryConfig.maxSize} entries)`); } /** * Save cluster state */ async saveClusterState(state) { return index$1.func(async () => { switch (this.config.type) { case "redis": await this.saveToRedis(state); break; case "file": await this.saveToFile(state); break; case "memory": await this.saveToMemory(state); break; case "custom": if (this.config.custom?.saveHandler) { await this.config.custom.saveHandler(state); } else { throw new Error("Custom save handler not provided"); } break; } this.emit("state:saved", state); }, { ultraFast: "maximum", auditLog: false, errorHandling: "graceful" } // 'ClusterPersistenceManager.saveClusterState', )(); } /** * Load cluster state */ async loadClusterState() { return index$1.func(async () => { let state = null; switch (this.config.type) { case "redis": state = await this.loadFromRedis(); break; case "file": state = await this.loadFromFile(); break; case "memory": state = await this.loadFromMemory(); break; case "custom": if (this.config.custom?.loadHandler) { // Custom handler now returns PersistentClusterState directly state = await this.config.custom.loadHandler(); } else { throw new Error("Custom load handler not provided"); } break; } if (state) { this.emit("state:loaded", state); } return state; }, { ultraFast: "maximum" })(); } /** * Save to Redis using SCA */ async saveToRedis(state) { if (!this.SCA) { throw new Error("SCA not initialized"); } const key = "cluster-state"; const ttl = this.config.redis?.ttl || 86400000; // 24 hours in ms // Use SCA for ultra-fast, secure Redis operations await this.SCA.set(key, state, { ttl }); Logger.logger.info("cluster", "✔ Cluster state saved to Redis using SCA"); } /** * Load from Redis using SCA */ async loadFromRedis() { if (!this.SCA) { throw new Error("SCA not initialized"); } try { const key = "cluster-state"; const data = await this.SCA.get(key); if (data) { Logger.logger.info("cluster", "✔ Cluster state loaded from Redis using SCA"); return data; } return null; } catch (error) { console.warn(`Failed to load from Redis: ${error}`); return null; } } /** * Save to file using FileCache */ async saveToFile(state) { if (!this.fileCache) { throw new Error("FileCache not initialized"); } const cacheKey = "cluster-state"; // FileCache handles backup automatically if configured await this.fileCache.set(cacheKey, state, { ttl: 0, // No expiration for cluster state }); Logger.logger.info("cluster", "✔ Cluster state saved using FileCache"); } /** * Load from file using FileCache */ async loadFromFile() { if (!this.fileCache) { throw new Error("FileCache not initialized"); } try { const cacheKey = "cluster-state"; const cachedData = await this.fileCache.get(cacheKey); if (cachedData && cachedData.data) { Logger.logger.info("cluster", "✔ Cluster state loaded from FileCache"); return cachedData.data; } return null; } catch (error) { console.warn(`Failed to load cluster state from FileCache: ${error}`); return null; } } /** * Save to memory using FortifyJS Cache */ async saveToMemory(state) { const key = "cluster:state"; const ttl = this.config.memory?.ttl || 3600000; // 1 hour default // Use FortifyJS Cache with encryption and compression await this.memoryCache.set(key, state, { ttl, encrypt: true, compress: true, }); Logger.logger.info("cluster", "✔ Cluster state saved to secure memory cache"); } /** * Load from memory using FortifyJS Cache */ async loadFromMemory() { const key = "cluster:state"; try { const cachedData = await this.memoryCache.get(key); if (cachedData) { Logger.logger.info("cluster", "✔ Cluster state loaded from secure memory cache"); return cachedData; } return null; } catch (error) { console.warn(`Failed to load from memory cache: ${error}`); return null; } } /** * Clean up old cache entries using FileCache built-in cleanup */ async cleanupBackups() { if (!this.fileCache) { console.warn("FileCache not initialized, cannot cleanup backups"); return; } try { // FileCache has built-in cleanup mechanisms // We can trigger cache cleanup and get stats const stats = await this.fileCache.getStats(); Logger.logger.info("cluster", `✔ Cache cleanup completed. Current cache files: ${stats.fileCount}, Total size: ${stats.totalSize} bytes`); } catch (error) { console.warn(`Failed to cleanup cache: ${error}`); } } /** * Clean up expired memory entries using FortifyJS Cache */ async cleanupMemoryStorage() { try { // FortifyJS Cache handles TTL and size limits automatically // We can get stats to monitor cache health const stats = this.memoryCache.getStats; Logger.logger.info("cluster", `✔ Memory cache cleanup completed. Hit rate: ${stats.hitRate}%, Entries: ${stats.entryCount}`); } catch (error) { console.warn(`Failed to cleanup memory cache: ${error}`); } } /** * Get comprehensive persistence statistics */ async getStats() { const memoryStats = this.memoryCache.getStats; const performance = { memoryCache: memoryStats }; const issues = []; const recommendations = []; // Get FileCache stats if available if (this.fileCache) { try { performance.fileCache = await this.fileCache.getStats(); // Health checks for file cache if (performance.fileCache.hitRate < 50) { issues.push("Low file cache hit rate"); recommendations.push("Consider increasing file cache TTL"); } if (performance.fileCache.diskUsage.percentage > 90) { issues.push("High disk usage"); recommendations.push("Run file cache cleanup"); } } catch (error) { issues.push("File cache statistics unavailable"); } } // Get Redis stats if available if (this.SCA) { try { performance.redisCache = await this.SCA.getStats(); // Health checks for Redis cache if (performance.redisCache.performance.averageResponseTime > 100) { issues.push("High Redis response time"); recommendations.push("Check Redis server performance"); } } catch (error) { issues.push("Redis cache statistics unavailable"); } } // Overall health assessment let overall = "healthy"; if (issues.length > 0) { overall = issues.length > 2 ? "critical" : "warning"; } return { type: this.config.type, isConnected: this.isConnected(), performance, health: { overall, issues, recommendations, }, }; } /** * Check if storage is connected/available */ isConnected() { switch (this.config.type) { case "redis": // Check SCA connection if available return this.SCA ? true : this.redisClient?.isOpen || false; case "file": return this.fileCache ? true : fs.existsSync(this.config.file?.path || ""); case "memory": return true; // Memory cache is always available case "custom": return !!(this.config.custom?.saveHandler && this.config.custom?.loadHandler); default: return false; } } /** * Close connections and cleanup */ async close() { try { // Close SecureCacheAdapter (handles Redis and memory cleanup) if (this.SCA) { await this.SCA.disconnect(); } // Fallback: close Redis client directly if not using SCA if (this.redisClient && !this.SCA) { await this.redisClient.quit(); } // Clear memory cache this.memoryCache.clear(); // Close file cache if initialized if (this.fileCache) { // FileCache doesn't have a close method, but we can clear it await this.fileCache.clear(); } Logger.logger.info("cluster", "✔ Cluster persistence manager closed with all cache systems cleaned up"); } catch (error) { console.warn(`Error closing persistence manager: ${error}`); } } } exports.ClusterPersistenceManager = ClusterPersistenceManager; //# sourceMappingURL=ClusterPersistenceManager.js.map