UNPKG

bb-inspired

Version:

Core library for BB-inspired NestJS backend

181 lines 7.02 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 RedisCacheService_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.RedisCacheService = void 0; const common_1 = require("@nestjs/common"); const redis_1 = require("redis"); const logger_1 = require("../../utils/logger"); let RedisCacheService = RedisCacheService_1 = class RedisCacheService { constructor(options) { var _a, _b; this.options = options; this.logger = new logger_1.AppLogger(RedisCacheService_1.name); this.isConnected = false; this.defaultTtl = ((_a = options.redis) === null || _a === void 0 ? void 0 : _a.ttl) || 3600; this.keyPrefix = ((_b = options.redis) === null || _b === void 0 ? void 0 : _b.keyPrefix) || 'app:'; } async onModuleInit() { if (this.options.provider !== 'redis') { return; } try { this.client = (0, redis_1.createClient)({ url: `redis://${this.options.redis.host}:${this.options.redis.port}`, password: this.options.redis.password, database: this.options.redis.db || 0, }); this.client.on('error', (err) => { this.logger.error(`Redis client error: ${err.message}`, err.stack); this.isConnected = false; }); this.client.on('connect', () => { this.logger.log('Connected to Redis server'); this.isConnected = true; }); await this.client.connect(); } catch (error) { this.logger.error(`Failed to connect to Redis: ${error.message}`, error.stack); } } async onModuleDestroy() { if (this.client && this.isConnected) { await this.client.disconnect(); this.logger.log('Disconnected from Redis server'); this.isConnected = false; } } async get(key) { try { const fullKey = this.getFullKey(key); const data = await this.client.get(fullKey); if (!data) { return null; } const entry = JSON.parse(data); if (entry.expiresAt && entry.expiresAt < Date.now()) { await this.delete(key); return null; } return entry.value; } catch (error) { this.logger.error(`Error getting cache key ${key}: ${error.message}`); return null; } } async set(key, value, options = {}) { var _a; try { const fullKey = this.getFullKey(key); const ttl = (_a = options.ttl) !== null && _a !== void 0 ? _a : this.defaultTtl; const entry = { value, expiresAt: ttl > 0 ? Date.now() + ttl * 1000 : undefined, tags: options.tags, }; const serialized = JSON.stringify(entry); if (ttl > 0) { await this.client.setEx(fullKey, ttl, serialized); } else { await this.client.set(fullKey, serialized); } if (options.tags && options.tags.length > 0) { for (const tag of options.tags) { const tagKey = this.getTagKey(tag); await this.client.sAdd(tagKey, fullKey); } } } catch (error) { this.logger.error(`Error setting cache key ${key}: ${error.message}`); } } async delete(key) { try { const fullKey = this.getFullKey(key); const data = await this.client.get(fullKey); if (data) { try { const entry = JSON.parse(data); if (entry.tags && entry.tags.length > 0) { for (const tag of entry.tags) { const tagKey = this.getTagKey(tag); await this.client.sRem(tagKey, fullKey); } } } catch (parseError) { } } const result = await this.client.del(fullKey); return result > 0; } catch (error) { this.logger.error(`Error deleting cache key ${key}: ${error.message}`); return false; } } async clear() { try { const keys = await this.client.keys(`${this.keyPrefix}*`); if (keys.length > 0) { await this.client.del(keys); this.logger.log(`Cleared ${keys.length} cache entries`); } } catch (error) { this.logger.error(`Error clearing cache: ${error.message}`); } } async has(key) { try { const fullKey = this.getFullKey(key); return await this.client.exists(fullKey) > 0; } catch (error) { this.logger.error(`Error checking cache key ${key}: ${error.message}`); return false; } } async invalidateByTag(tag) { try { const tagKey = this.getTagKey(tag); const keys = await this.client.sMembers(tagKey); if (keys.length > 0) { await this.client.del(keys); await this.client.del(tagKey); this.logger.log(`Invalidated ${keys.length} cache entries with tag ${tag}`); } } catch (error) { this.logger.error(`Error invalidating cache by tag ${tag}: ${error.message}`); } } getFullKey(key) { return `${this.keyPrefix}${key}`; } getTagKey(tag) { return `${this.keyPrefix}tag:${tag}`; } }; exports.RedisCacheService = RedisCacheService; exports.RedisCacheService = RedisCacheService = RedisCacheService_1 = __decorate([ (0, common_1.Injectable)(), __param(0, (0, common_1.Inject)('CACHE_OPTIONS')), __metadata("design:paramtypes", [Object]) ], RedisCacheService); //# sourceMappingURL=redis-cache.service.js.map