diff --git a/packages/twenty-server/src/engine/workspace-cache/services/workspace-cache.service.ts b/packages/twenty-server/src/engine/workspace-cache/services/workspace-cache.service.ts index f3610494ed..c5703ce674 100644 --- a/packages/twenty-server/src/engine/workspace-cache/services/workspace-cache.service.ts +++ b/packages/twenty-server/src/engine/workspace-cache/services/workspace-cache.service.ts @@ -33,6 +33,8 @@ const LOCAL_ENTRY_TTL_MS = 30 * 60 * 1000; // 30 minutes const MEMOIZER_TTL_MS = 10_000; // 10 seconds const STALE_VERSION_TTL_MS = 5_000; // 5 seconds const MAX_LOCAL_STALE_VERSIONS = 5; // 5 stale versions +const MAX_LOCAL_CACHE_ENTRIES = 1_000; +const MIN_EVICT_KEYS = 100; type CacheDataType = WorkspaceCacheDataMap[WorkspaceCacheKeyName]; @@ -391,6 +393,28 @@ export class WorkspaceCacheService implements OnModuleInit { entry.versions.set(hash, { data, lastReadAt: Date.now() }); entry.latestHash = hash; entry.lastHashCheckedAt = Date.now(); + + this.cleanupStaleVersions(entry); + this.evictLRUEntriesIfNeeded(); + } + + private evictLRUEntriesIfNeeded(): void { + if (this.localCache.size <= MAX_LOCAL_CACHE_ENTRIES) { + return; + } + + const entries = [...this.localCache.entries()].sort( + (a, b) => a[1].lastHashCheckedAt - b[1].lastHashCheckedAt, + ); + + const toEvict = entries.slice( + 0, + Math.max(MIN_EVICT_KEYS, this.localCache.size - MAX_LOCAL_CACHE_ENTRIES), + ); + + for (const [key] of toEvict) { + this.localCache.delete(key); + } } private cleanupStaleVersions(