UNPKG

@ahmedhegazee/nestjs-telescope

Version:

Advanced observability and monitoring solution for NestJS applications with ML-powered analytics, enterprise features, and production-ready scaling

207 lines 8.9 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var StorageManagerService_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.StorageManagerService = void 0; const common_1 = require("@nestjs/common"); const memory_storage_driver_1 = require("./drivers/memory-storage.driver"); const file_storage_driver_1 = require("./drivers/file-storage.driver"); const redis_storage_driver_1 = require("./drivers/redis-storage.driver"); let StorageManagerService = StorageManagerService_1 = class StorageManagerService { constructor(config) { this.config = config; this.logger = new common_1.Logger(StorageManagerService_1.name); this.drivers = new Map(); this.healthStatus = new Map(); } async onModuleInit() { await this.initializeDrivers(); this.startHealthChecks(); } async initializeDrivers() { try { this.drivers.set('memory', new memory_storage_driver_1.MemoryStorageDriver()); this.drivers.set('file', new file_storage_driver_1.FileStorageDriver(this.config.storage)); this.drivers.set('redis', new redis_storage_driver_1.RedisStorageDriver(this.config.storage)); const primaryDriverName = this.config.storage.driver; this.primaryDriver = this.drivers.get(primaryDriverName); if (!this.primaryDriver) { this.logger.warn(`Primary driver '${primaryDriverName}' not available, falling back to memory`); this.primaryDriver = this.drivers.get('memory'); } const fallbackDriverName = this.config.storage.fallback; if (fallbackDriverName && fallbackDriverName !== primaryDriverName) { this.fallbackDriver = this.drivers.get(fallbackDriverName); if (!this.fallbackDriver) { this.logger.warn(`Fallback driver '${fallbackDriverName}' not available`); } } this.logger.log(`Storage manager initialized with primary: ${primaryDriverName}, fallback: ${fallbackDriverName || 'none'}`); await this.checkAllDriversHealth(); } catch (error) { this.logger.error('Failed to initialize storage drivers:', error); throw error; } } async store(entry) { return this.executeWithFallback(async () => { await this.primaryDriver.store(entry); this.logger.debug(`Stored entry ${entry.id} with primary driver`); }, async () => { if (this.fallbackDriver) { await this.fallbackDriver.store(entry); this.logger.debug(`Stored entry ${entry.id} with fallback driver`); } }, 'store'); } async storeBatch(entries) { return this.executeWithFallback(async () => { await this.primaryDriver.storeBatch(entries); this.logger.debug(`Stored batch of ${entries.length} entries with primary driver`); }, async () => { if (this.fallbackDriver) { await this.fallbackDriver.storeBatch(entries); this.logger.debug(`Stored batch of ${entries.length} entries with fallback driver`); } }, 'storeBatch'); } async find(filter) { return this.executeWithFallback(() => this.primaryDriver.find(filter), () => this.fallbackDriver?.find(filter), 'find'); } async findById(id) { return this.executeWithFallback(() => this.primaryDriver.findById(id), () => this.fallbackDriver?.findById(id), 'findById'); } async delete(id) { return this.executeWithFallback(() => this.primaryDriver.delete(id), () => this.fallbackDriver?.delete(id), 'delete'); } async clear() { return this.executeWithFallback(() => this.primaryDriver.clear(), () => this.fallbackDriver?.clear(), 'clear'); } async prune(olderThan) { return this.executeWithFallback(() => this.primaryDriver.prune(olderThan), () => this.fallbackDriver?.prune(olderThan), 'prune'); } async getStats() { return this.executeWithFallback(() => this.primaryDriver.getStats(), () => this.fallbackDriver?.getStats(), 'getStats'); } async executeWithFallback(primary, fallback, operation) { try { const result = await primary(); return result; } catch (error) { this.logger.warn(`Primary storage failed for ${operation}: ${error.message}`); if (fallback) { try { const result = await fallback(); this.logger.log(`Fallback storage succeeded for ${operation}`); return result; } catch (fallbackError) { this.logger.error(`Fallback storage failed for ${operation}: ${fallbackError.message}`); throw error; } } throw error; } } async checkAllDriversHealth() { for (const [name, driver] of this.drivers) { try { const isHealthy = await this.checkDriverHealth(driver); this.healthStatus.set(name, isHealthy); if (isHealthy) { this.logger.debug(`Driver '${name}' is healthy`); } else { this.logger.warn(`Driver '${name}' is unhealthy`); } } catch (error) { this.logger.error(`Health check failed for driver '${name}':`, error); this.healthStatus.set(name, false); } } } async checkDriverHealth(driver) { try { if ('healthCheck' in driver && typeof driver.healthCheck === 'function') { return await driver.healthCheck(); } await driver.getStats(); return true; } catch (error) { return false; } } startHealthChecks() { setInterval(async () => { await this.checkAllDriversHealth(); }, 30000); } getDriverHealth() { return Object.fromEntries(this.healthStatus); } async getDetailedStats() { const stats = await this.getStats(); return { primary: this.config.storage.driver, fallback: this.config.storage.fallback, health: this.getDriverHealth(), stats }; } getPrimaryDriver() { return this.primaryDriver; } getFallbackDriver() { return this.fallbackDriver; } getAvailableDrivers() { return Array.from(this.drivers.keys()); } async switchPrimaryDriver(driverName) { const newDriver = this.drivers.get(driverName); if (!newDriver) { throw new Error(`Driver '${driverName}' not available`); } const isHealthy = await this.checkDriverHealth(newDriver); if (!isHealthy) { throw new Error(`Driver '${driverName}' is not healthy`); } this.primaryDriver = newDriver; this.logger.log(`Switched primary driver to: ${driverName}`); } async cleanup() { for (const [name, driver] of this.drivers) { try { if ('cleanup' in driver && typeof driver.cleanup === 'function') { await driver.cleanup(); this.logger.debug(`Cleaned up driver: ${name}`); } } catch (error) { this.logger.error(`Failed to cleanup driver '${name}':`, error); } } } }; exports.StorageManagerService = StorageManagerService; exports.StorageManagerService = StorageManagerService = StorageManagerService_1 = __decorate([ (0, common_1.Injectable)(), __param(0, (0, common_1.Inject)('TELESCOPE_CONFIG')), __metadata("design:paramtypes", [Object]) ], StorageManagerService); //# sourceMappingURL=storage-manager.service.js.map