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
JavaScript
'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