Use regional cache for rate limiting

This commit is contained in:
Owen
2026-06-29 18:33:03 -04:00
parent ccabddc225
commit 7c2ea153c5
2 changed files with 55 additions and 18 deletions

View File

@@ -12,7 +12,7 @@
*/ */
import logger from "@server/logger"; import logger from "@server/logger";
import redisManager from "#private/lib/redis"; import { regionalRedisManager as redisManager } from "#private/lib/redis";
import { build } from "@server/build"; import { build } from "@server/build";
// Rate limiting configuration // Rate limiting configuration
@@ -152,10 +152,9 @@ export class RateLimitService {
); );
// Set TTL using the client directly - this prevents the key from persisting forever // Set TTL using the client directly - this prevents the key from persisting forever
if (redisManager.getClient()) { const writeClient = redisManager.getClient();
await redisManager if (writeClient) {
.getClient() await writeClient.expire(globalKey, RATE_LIMIT_WINDOW + 10);
.expire(globalKey, RATE_LIMIT_WINDOW + 10);
} }
// Update tracking // Update tracking
@@ -204,10 +203,12 @@ export class RateLimitService {
); );
// Set TTL using the client directly - this prevents the key from persisting forever // Set TTL using the client directly - this prevents the key from persisting forever
if (redisManager.getClient()) { const writeClient = redisManager.getClient();
await redisManager if (writeClient) {
.getClient() await writeClient.expire(
.expire(messageTypeKey, RATE_LIMIT_WINDOW + 10); messageTypeKey,
RATE_LIMIT_WINDOW + 10
);
} }
// Update tracking // Update tracking
@@ -487,16 +488,13 @@ export class RateLimitService {
await redisManager.del(globalKey); await redisManager.del(globalKey);
// Get all message type keys for this client and delete them // Get all message type keys for this client and delete them
const client = redisManager.getClient(); const messageTypeKeys = await redisManager.keys(
if (client) { `ratelimit:${clientId}:*`
const messageTypeKeys = await client.keys( );
`ratelimit:${clientId}:*` if (messageTypeKeys.length > 0) {
await Promise.all(
messageTypeKeys.map((key) => redisManager.del(key))
); );
if (messageTypeKeys.length > 0) {
await Promise.all(
messageTypeKeys.map((key) => redisManager.del(key))
);
}
} }
} }
} }

View File

@@ -1000,6 +1000,45 @@ class RegionalRedisManager {
} }
} }
public getClient(): Redis | null {
return this.writeClient;
}
public async hget(key: string, field: string): Promise<string | null> {
if (!this.isRedisEnabled() || !this.readClient) return null;
try {
return await this.readClient.hget(key, field);
} catch (error) {
logger.error("Regional Redis HGET error:", error);
return null;
}
}
public async hset(
key: string,
field: string,
value: string
): Promise<boolean> {
if (!this.isRedisEnabled() || !this.writeClient) return false;
try {
await this.writeClient.hset(key, field, value);
return true;
} catch (error) {
logger.error("Regional Redis HSET error:", error);
return false;
}
}
public async hgetall(key: string): Promise<Record<string, string>> {
if (!this.isRedisEnabled() || !this.readClient) return {};
try {
return await this.readClient.hgetall(key);
} catch (error) {
logger.error("Regional Redis HGETALL error:", error);
return {};
}
}
public async disconnect(): Promise<void> { public async disconnect(): Promise<void> {
try { try {
if (this.writeClient) { if (this.writeClient) {