From 85aa323e848bc385c6a9344d3f23dab76cb7245f Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 8 Jun 2025 17:27:15 +0200 Subject: [PATCH] Feature/improve cache verification in health check endpoint (#4868) * Improve implementation of isHealthy() without using getKeys() * Update changelog --- CHANGELOG.md | 1 + .../app/redis-cache/redis-cache.service.ts | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 450ae6fa3..a6f98ee1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Renamed the asset profile icon component to entity logo component and moved to `@ghostfolio/ui` - Renamed `Account` to `accounts` in the `User` database schema +- Improved the cache verification in the health check endpoint (experimental) - Improved the language localization for Catalan (`ca`) - Improved the language localization for French (`fr`) - Improved the language localization for Polish (`pl`) diff --git a/apps/api/src/app/redis-cache/redis-cache.service.ts b/apps/api/src/app/redis-cache/redis-cache.service.ts index e6e98d622..ae4493e51 100644 --- a/apps/api/src/app/redis-cache/redis-cache.service.ts +++ b/apps/api/src/app/redis-cache/redis-cache.service.ts @@ -79,12 +79,22 @@ export class RedisCacheService { } public async isHealthy() { + const testKey = '__health_check__'; + const testValue = Date.now().toString(); + try { await Promise.race([ - this.getKeys(), + (async () => { + await this.set(testKey, testValue, ms('1 second')); + const result = await this.get(testKey); + + if (result !== testValue) { + throw new Error('Redis health check failed: value mismatch'); + } + })(), new Promise((_, reject) => setTimeout( - () => reject(new Error('Redis health check timeout')), + () => reject(new Error('Redis health check failed: timeout')), ms('2 seconds') ) ) @@ -92,7 +102,13 @@ export class RedisCacheService { return true; } catch (error) { + Logger.error(error?.message, 'RedisCacheService'); + return false; + } finally { + try { + await this.remove(testKey); + } catch {} } }