Add redis cache for cron triggers (#19306)
- WorkflowCronTriggerCronJob was querying every active workspace (~700) sequentially every minute to find cron triggers, causing regular CPU spikes to 100% on worker pods - Added a Redis hashset cache that stores cron triggers. On cache miss (TTL expired, cold start, or explicit invalidation), a full scan rebuilds the cache - Creating/deleting a new cron trigger updates the cache, only if exists
This commit is contained in:
+72
@@ -286,6 +286,78 @@ export class CacheStorageService {
|
||||
return newValue;
|
||||
}
|
||||
|
||||
async hashGetValues(key: string): Promise<string[]> {
|
||||
if (!this.isRedisCache()) {
|
||||
throw new Error('hashGetValues is only supported with Redis cache');
|
||||
}
|
||||
|
||||
const redisClient = (this.cache as RedisCache).store.client;
|
||||
|
||||
return redisClient.hVals(this.getKey(key));
|
||||
}
|
||||
|
||||
async hashSet({
|
||||
key,
|
||||
field,
|
||||
value,
|
||||
}: {
|
||||
key: string;
|
||||
field: string;
|
||||
value: string;
|
||||
}): Promise<number> {
|
||||
if (!this.isRedisCache()) {
|
||||
throw new Error('hashSet is only supported with Redis cache');
|
||||
}
|
||||
|
||||
const redisClient = (this.cache as RedisCache).store.client;
|
||||
|
||||
return redisClient.hSet(this.getKey(key), field, value);
|
||||
}
|
||||
|
||||
async hashSetIfExists({
|
||||
key,
|
||||
field,
|
||||
value,
|
||||
}: {
|
||||
key: string;
|
||||
field: string;
|
||||
value: string;
|
||||
}): Promise<number> {
|
||||
if (!this.isRedisCache()) {
|
||||
throw new Error('hashSetIfExists is only supported with Redis cache');
|
||||
}
|
||||
|
||||
const redisClient = (this.cache as RedisCache).store.client;
|
||||
|
||||
const script = `
|
||||
if redis.call('EXISTS', KEYS[1]) == 1 then
|
||||
return redis.call('HSET', KEYS[1], ARGV[1], ARGV[2])
|
||||
else
|
||||
return 0
|
||||
end`;
|
||||
|
||||
return redisClient.eval(script, {
|
||||
keys: [this.getKey(key)],
|
||||
arguments: [field, value],
|
||||
}) as Promise<number>;
|
||||
}
|
||||
|
||||
async hashDelete({
|
||||
key,
|
||||
field,
|
||||
}: {
|
||||
key: string;
|
||||
field: string;
|
||||
}): Promise<number> {
|
||||
if (!this.isRedisCache()) {
|
||||
throw new Error('hashDelete is only supported with Redis cache');
|
||||
}
|
||||
|
||||
const redisClient = (this.cache as RedisCache).store.client;
|
||||
|
||||
return redisClient.hDel(this.getKey(key), field);
|
||||
}
|
||||
|
||||
async expire(key: string, ttlMs: Milliseconds): Promise<boolean> {
|
||||
if (this.isRedisCache()) {
|
||||
return (this.cache as RedisCache).store.client.expire(
|
||||
|
||||
Reference in New Issue
Block a user