diff --git a/src/services/cache.service.ts b/src/services/cache.service.ts index 770b0ef0..3bafb8f9 100644 --- a/src/services/cache.service.ts +++ b/src/services/cache.service.ts @@ -11,13 +11,24 @@ export default class CacheService { private readonly redis: Redis; constructor(config: AppConfig) { this.redis = new Redis(config.REDIS_HOST, { - retryStrategy: () => undefined, + retryStrategy: (times) => { + if (times > 10) { + Logger.error('[CACHE SERVICE]: Max reconnection attempts reached. Giving up.'); + return undefined; + } + return Math.min(times * 500, 30000); + }, + enableOfflineQueue: false, + keepAlive: 10000, + maxRetriesPerRequest: 5, showFriendlyErrorStack: true, }); this.redis.on('error', (error) => { Logger.error(`[CACHE SERVICE]: Redis error: ${error.message}`); }); + this.redis.on('close', () => Logger.warn('[CACHE SERVICE]: Connection closed')); + this.redis.on('end', () => Logger.error('[CACHE SERVICE]: Connection ended, no more retries')); } private buildSubscriptionKey(customerId: string, userType: UserType = UserType.Individual): string { diff --git a/tests/src/services/cache.service.test.ts b/tests/src/services/cache.service.test.ts index 56a2db47..2c6d101d 100644 --- a/tests/src/services/cache.service.test.ts +++ b/tests/src/services/cache.service.test.ts @@ -33,6 +33,27 @@ describe('Cache Service', () => { }); }); + describe('Retry Strategy', () => { + test('When reconnection attempts are less than 10, then it returns increasing delays', () => { + const newCacheService = new CacheService(config); + const retryStrategy = (newCacheService as any).redis.options.retryStrategy; + + expect(retryStrategy(1)).toBe(500); + expect(retryStrategy(2)).toBe(1000); + expect(retryStrategy(5)).toBe(2500); + expect(retryStrategy(10)).toBe(5000); + }); + + test('When reconnection attempts exceed 10, then it gives up', () => { + const newCacheService = new CacheService(config); + const retryStrategy = (newCacheService as any).redis.options.retryStrategy; + + const result = retryStrategy(11); + + expect(result).toBeUndefined(); + }); + }); + describe('Safe await error handling', () => { test('When a Redis operation fails, then the error is logged and null is returned', async () => { const loggerSpy = jest.spyOn(Logger, 'error');