From efbc7a5e78ebf5fc7b20352299406a86fe6724a3 Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:16:15 +0100 Subject: [PATCH 1/5] chore: add cache strategy --- src/services/cache.service.ts | 9 ++++- tests/src/services/cache.service.test.ts | 42 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/services/cache.service.ts b/src/services/cache.service.ts index 770b0ef0..0e465b9b 100644 --- a/src/services/cache.service.ts +++ b/src/services/cache.service.ts @@ -11,7 +11,14 @@ 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); + }, + maxRetriesPerRequest: 3, showFriendlyErrorStack: true, }); diff --git a/tests/src/services/cache.service.test.ts b/tests/src/services/cache.service.test.ts index 56a2db47..262f3646 100644 --- a/tests/src/services/cache.service.test.ts +++ b/tests/src/services/cache.service.test.ts @@ -33,6 +33,48 @@ 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 reach the maximum delay, then it caps at 30 seconds', () => { + const newCacheService = new CacheService(config); + const retryStrategy = (newCacheService as any).redis.options.retryStrategy; + + expect(retryStrategy(60)).toBeUndefined(); + expect(retryStrategy(100)).toBeUndefined(); + }); + + test('When reconnection attempts exceed 10, then it logs error and gives up', () => { + const loggerSpy = jest.spyOn(Logger, 'error'); + const newCacheService = new CacheService(config); + const retryStrategy = (newCacheService as any).redis.options.retryStrategy; + + const result = retryStrategy(11); + + expect(loggerSpy).toHaveBeenCalledWith('[CACHE SERVICE]: Max reconnection attempts reached. Giving up.'); + expect(result).toBeUndefined(); + + loggerSpy.mockRestore(); + }); + + test('When reconnection attempts are exactly 10, then it still retries', () => { + const newCacheService = new CacheService(config); + const retryStrategy = (newCacheService as any).redis.options.retryStrategy; + + const result = retryStrategy(10); + + expect(result).toBe(5000); + }); + }); + 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'); From 233aa55cb8b383002ef52f950c8ba0bc0ee1c50a Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:17:31 +0100 Subject: [PATCH 2/5] test: remove useless tests --- tests/src/services/cache.service.test.ts | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/tests/src/services/cache.service.test.ts b/tests/src/services/cache.service.test.ts index 262f3646..2c6d101d 100644 --- a/tests/src/services/cache.service.test.ts +++ b/tests/src/services/cache.service.test.ts @@ -44,34 +44,13 @@ describe('Cache Service', () => { expect(retryStrategy(10)).toBe(5000); }); - test('When reconnection attempts reach the maximum delay, then it caps at 30 seconds', () => { - const newCacheService = new CacheService(config); - const retryStrategy = (newCacheService as any).redis.options.retryStrategy; - - expect(retryStrategy(60)).toBeUndefined(); - expect(retryStrategy(100)).toBeUndefined(); - }); - - test('When reconnection attempts exceed 10, then it logs error and gives up', () => { - const loggerSpy = jest.spyOn(Logger, 'error'); + 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(loggerSpy).toHaveBeenCalledWith('[CACHE SERVICE]: Max reconnection attempts reached. Giving up.'); expect(result).toBeUndefined(); - - loggerSpy.mockRestore(); - }); - - test('When reconnection attempts are exactly 10, then it still retries', () => { - const newCacheService = new CacheService(config); - const retryStrategy = (newCacheService as any).redis.options.retryStrategy; - - const result = retryStrategy(10); - - expect(result).toBe(5000); }); }); From 2699942aa51e9435d65c40dfd68446d73de867a6 Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Tue, 10 Mar 2026 09:34:55 +0100 Subject: [PATCH 3/5] feat: add logs when closing and ending Redis connection --- src/services/cache.service.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/services/cache.service.ts b/src/services/cache.service.ts index 0e465b9b..91da020e 100644 --- a/src/services/cache.service.ts +++ b/src/services/cache.service.ts @@ -18,13 +18,16 @@ export default class CacheService { } return Math.min(times * 500, 30000); }, - maxRetriesPerRequest: 3, + keepAlive: 5000, + 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 { From ad6ea9d0a111dd06e6b63c335f8e39e22f2df65c Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Tue, 10 Mar 2026 10:02:50 +0100 Subject: [PATCH 4/5] fix: disable offline queue for pending cache requests --- src/services/cache.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/cache.service.ts b/src/services/cache.service.ts index 91da020e..6b21ed6a 100644 --- a/src/services/cache.service.ts +++ b/src/services/cache.service.ts @@ -18,6 +18,7 @@ export default class CacheService { } return Math.min(times * 500, 30000); }, + enableOfflineQueue: false, keepAlive: 5000, maxRetriesPerRequest: 5, showFriendlyErrorStack: true, From 818861c0184f37eb9517e90b17a5f37fada011b5 Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Tue, 10 Mar 2026 10:34:09 +0100 Subject: [PATCH 5/5] feat: upgrade keepAlive time to 10s --- src/services/cache.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/cache.service.ts b/src/services/cache.service.ts index 6b21ed6a..3bafb8f9 100644 --- a/src/services/cache.service.ts +++ b/src/services/cache.service.ts @@ -19,7 +19,7 @@ export default class CacheService { return Math.min(times * 500, 30000); }, enableOfflineQueue: false, - keepAlive: 5000, + keepAlive: 10000, maxRetriesPerRequest: 5, showFriendlyErrorStack: true, });