From 9b049d8d5bc9a3cb38f458ed8fad865d8935df87 Mon Sep 17 00:00:00 2001 From: e11sy <130844513+e11sy@users.noreply.github.com> Date: Wed, 2 Apr 2025 21:49:38 +0300 Subject: [PATCH 1/2] imp(notifier): add ttl for redis records --- workers/notifier/src/redisHelper.ts | 9 +++++- workers/notifier/tests/redisHelper.test.ts | 32 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/workers/notifier/src/redisHelper.ts b/workers/notifier/src/redisHelper.ts index 56923b75..5d4638f9 100644 --- a/workers/notifier/src/redisHelper.ts +++ b/workers/notifier/src/redisHelper.ts @@ -57,12 +57,14 @@ export default class RedisHelper { local key = KEYS[1] local currentTimestamp = tonumber(ARGV[1]) local thresholdPeriod = tonumber(ARGV[2]) + local ttl = tonumber(ARGV[3]) local startPeriodTimestamp = tonumber(redis.call("HGET", key, "timestamp")) if ((startPeriodTimestamp == nil) or (currentTimestamp >= startPeriodTimestamp + thresholdPeriod)) then redis.call("HSET", key, "timestamp", currentTimestamp) redis.call("HSET", key, "eventsCount", 0) + redis.call("EXPIRE", key, ttl) end local newCounter = redis.call("HINCRBY", key, "eventsCount", 1) @@ -71,11 +73,16 @@ export default class RedisHelper { const key = `${projectId}:${ruleId}:${groupHash}:${thresholdPeriod}:times`; + /** + * Treshold period is in milliseconds, but redis expects ttl in seconds + */ + const ttl = Math.floor(thresholdPeriod / 1000); + const currentTimestamp = Date.now(); const currentEventCount = await this.redisClient.eval(script, { keys: [ key ], - arguments: [currentTimestamp.toString(), thresholdPeriod.toString()], + arguments: [currentTimestamp.toString(), thresholdPeriod.toString(), ttl.toString()], }) as number; return (currentEventCount !== null) ? currentEventCount : 0; diff --git a/workers/notifier/tests/redisHelper.test.ts b/workers/notifier/tests/redisHelper.test.ts index 580663ae..5dac298b 100644 --- a/workers/notifier/tests/redisHelper.test.ts +++ b/workers/notifier/tests/redisHelper.test.ts @@ -94,5 +94,37 @@ describe('RedisHelper', () => { expect(currentEventCount).toBe(1); expect(currentlyStoredTimestamp).toBe(Date.now().toString()); }); + + describe('key expiration period', () => { + it('should expire key after ttl period', async () => { + const ruleId = 'ruleId'; + const groupHash = 'groupHash'; + const projectId = 'projectId'; + const thresholdPeriod = 2000; // 2 seconds in milliseconds + const key = `${projectId}:${ruleId}:${groupHash}:${thresholdPeriod}:times`; + + /** + * Call computeEventCountForPeriod to set the key + */ + await redisHelper.computeEventCountForPeriod(projectId, ruleId, groupHash, thresholdPeriod); + + /** + * Verify, that key exists + */ + let value = await redisClient.hGet(key, 'eventsCount'); + expect(value).not.toBeNull(); + + /** + * Wait for the TTL to expire (slightly longer than threshold period) + */ + await new Promise(resolve => setTimeout(resolve, thresholdPeriod + 500)); + + /** + * Verify, that key has expired and removed from the redis storage + */ + value = await redisClient.hGet(key, 'eventsCount'); + expect(value).toBeNull(); + }); + }); }); }); From 529c344ff3256fce6ad30dba9175047b2115250f Mon Sep 17 00:00:00 2001 From: e11sy <130844513+e11sy@users.noreply.github.com> Date: Thu, 3 Apr 2025 20:21:55 +0300 Subject: [PATCH 2/2] imp(notifier): replace hardcoded value with util const --- workers/notifier/src/redisHelper.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/workers/notifier/src/redisHelper.ts b/workers/notifier/src/redisHelper.ts index 5d4638f9..02f01f02 100644 --- a/workers/notifier/src/redisHelper.ts +++ b/workers/notifier/src/redisHelper.ts @@ -1,6 +1,7 @@ import { createClient, RedisClientType } from 'redis'; import { Rule } from '../types/rule'; import { NotifierEvent } from '../types/notifier-task'; +import { MS_IN_SEC } from '../../../lib/utils/consts'; /** * Class with helper functions for working with Redis @@ -76,7 +77,7 @@ export default class RedisHelper { /** * Treshold period is in milliseconds, but redis expects ttl in seconds */ - const ttl = Math.floor(thresholdPeriod / 1000); + const ttl = Math.floor(thresholdPeriod / MS_IN_SEC); const currentTimestamp = Date.now();