diff --git a/server/lib/cache.ts b/server/lib/cache.ts index 82c80280..4910d945 100644 --- a/server/lib/cache.ts +++ b/server/lib/cache.ts @@ -1,5 +1,20 @@ import NodeCache from "node-cache"; +import logger from "@server/logger"; -export const cache = new NodeCache({ stdTTL: 3600, checkperiod: 120 }); +// Create cache with maxKeys limit to prevent memory leaks +// With ~10k requests/day and 5min TTL, 10k keys should be more than sufficient +export const cache = new NodeCache({ + stdTTL: 3600, + checkperiod: 120, + maxKeys: 10000 +}); + +// Log cache statistics periodically for monitoring +setInterval(() => { + const stats = cache.getStats(); + logger.debug( + `Cache stats - Keys: ${stats.keys}, Hits: ${stats.hits}, Misses: ${stats.misses}, Hit rate: ${stats.hits > 0 ? ((stats.hits / (stats.hits + stats.misses)) * 100).toFixed(2) : 0}%` + ); +}, 300000); // Every 5 minutes export default cache; diff --git a/server/private/lib/logAccessAudit.ts b/server/private/lib/logAccessAudit.ts index 98eaa6ec..5c423c60 100644 --- a/server/private/lib/logAccessAudit.ts +++ b/server/private/lib/logAccessAudit.ts @@ -161,8 +161,11 @@ async function getCountryCodeFromIp(ip: string): Promise { if (!cachedCountryCode) { cachedCountryCode = await getCountryCodeForIp(ip); // do it locally - // Cache for longer since IP geolocation doesn't change frequently - cache.set(geoIpCacheKey, cachedCountryCode, 300); // 5 minutes + // Only cache successful lookups to avoid filling cache with undefined values + if (cachedCountryCode) { + // Cache for longer since IP geolocation doesn't change frequently + cache.set(geoIpCacheKey, cachedCountryCode, 300); // 5 minutes + } } return cachedCountryCode; diff --git a/server/routers/badger/verifySession.ts b/server/routers/badger/verifySession.ts index e209ee57..45f5f041 100644 --- a/server/routers/badger/verifySession.ts +++ b/server/routers/badger/verifySession.ts @@ -1206,8 +1206,11 @@ async function getCountryCodeFromIp(ip: string): Promise { if (!cachedCountryCode) { cachedCountryCode = await getCountryCodeForIp(ip); // do it locally - // Cache for longer since IP geolocation doesn't change frequently - cache.set(geoIpCacheKey, cachedCountryCode, 300); // 5 minutes + // Only cache successful lookups to avoid filling cache with undefined values + if (cachedCountryCode) { + // Cache for longer since IP geolocation doesn't change frequently + cache.set(geoIpCacheKey, cachedCountryCode, 300); // 5 minutes + } } return cachedCountryCode;