FRE-4521 Implement Redis integration for rate limiting and deduplication

- Add ioredis dependency for Redis connection pooling
- Create RedisService singleton with connection management
- Add Redis config (url, dedupWindowSeconds) to notification.config.ts
- Implement NotificationService.checkRateLimit using Redis INCR+EXPIRE
- Implement NotificationService.deduplicateNotification using Redis SET/NX
- Add configurable rate limit windows and thresholds via env vars
- Add 29 unit tests covering Redis operations, rate limiting, and dedup
- All tests pass, TypeScript compiles cleanly for new files
This commit is contained in:
Senior Engineer
2026-05-01 16:13:17 -04:00
committed by Michael Freno
parent 7aed2d8b2b
commit 574bcf2264
9 changed files with 598 additions and 3 deletions

View File

@@ -25,6 +25,11 @@ export const NotificationConfigSchema = z.object({
emailPerMinute: z.number().default(60),
smsPerMinute: z.number().default(30),
pushPerMinute: z.number().default(100),
windowSeconds: z.number().default(60),
}),
redis: z.object({
url: z.string().default('redis://localhost:6379'),
dedupWindowSeconds: z.number().default(300),
}),
});
@@ -55,5 +60,10 @@ export const loadNotificationConfig = (): NotificationConfig => ({
emailPerMinute: parseInt(process.env.EMAIL_RATE_LIMIT || '60', 10),
smsPerMinute: parseInt(process.env.SMS_RATE_LIMIT || '30', 10),
pushPerMinute: parseInt(process.env.PUSH_RATE_LIMIT || '100', 10),
windowSeconds: parseInt(process.env.RATE_LIMIT_WINDOW_SECONDS || '60', 10),
},
redis: {
url: process.env.REDIS_URL || 'redis://localhost:6379',
dedupWindowSeconds: parseInt(process.env.DEDUP_WINDOW_SECONDS || '300', 10),
},
});