diff --git a/packages/twenty-server/src/engine/core-modules/cache-storage/commands/flush-cache.command.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/commands/flush-cache.command.ts index c07565936..0a4d51357 100644 --- a/packages/twenty-server/src/engine/core-modules/cache-storage/commands/flush-cache.command.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/commands/flush-cache.command.ts @@ -1,15 +1,14 @@ import { Logger } from '@nestjs/common'; -import { Command, CommandRunner } from 'nest-commander'; +import { Command, CommandRunner, Option } from 'nest-commander'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -// TODO: implement dry-run @Command({ name: 'cache:flush', - description: 'Completely flush cache', + description: 'Flush cache for specific keys matching the pattern', }) export class FlushCacheCommand extends CommandRunner { private readonly logger = new Logger(FlushCacheCommand.name); @@ -21,9 +20,28 @@ export class FlushCacheCommand extends CommandRunner { super(); } - async run(): Promise { - this.logger.log('Flushing cache...'); - await this.cacheStorage.flush(); + async run( + passedParams: string[], + options?: Record, + ): Promise { + const pattern = options?.pattern || '*'; + + this.logger.log(`Flushing cache for pattern: ${pattern}...`); + + if (pattern === '*') { + await this.cacheStorage.flush(); + } else { + await this.cacheStorage.flushByPattern(pattern); + } + this.logger.log('Cache flushed'); } + + @Option({ + flags: '-p, --pattern ', + description: 'Pattern to flush specific cache keys (e.g., engine:*)', + }) + parsePattern(val: string): string { + return val; + } } diff --git a/packages/twenty-server/src/engine/core-modules/cache-storage/services/cache-storage.service.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/services/cache-storage.service.ts index e5195c18a..7b132c7fb 100644 --- a/packages/twenty-server/src/engine/core-modules/cache-storage/services/cache-storage.service.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/services/cache-storage.service.ts @@ -1,5 +1,5 @@ -import { Inject, Injectable } from '@nestjs/common'; import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager'; +import { Inject, Injectable } from '@nestjs/common'; import { RedisCache } from 'cache-manager-redis-yet'; @@ -67,6 +67,31 @@ export class CacheStorageService { return this.cache.reset(); } + async flushByPattern(scanPattern: string): Promise { + if (!this.isRedisCache()) { + throw new Error('flushByPattern is only supported with Redis cache'); + } + + const redisClient = (this.cache as RedisCache).store.client; + let cursor = 0; + + do { + const result = await redisClient.scan(cursor, { + MATCH: scanPattern, + COUNT: 100, + }); + + const nextCursor = result.cursor; + const keys = result.keys; + + if (keys.length > 0) { + await redisClient.del(keys); + } + + cursor = nextCursor; + } while (cursor !== 0); + } + private isRedisCache() { return (this.cache.store as any)?.name === 'redis'; }