feat: 实现实时匿名会话
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { RedisService } from "../redis/redis.service.js";
|
||||
|
||||
@Injectable()
|
||||
export class ChatRateLimiter {
|
||||
constructor(@Inject(RedisService) private readonly redis: RedisService) {}
|
||||
async consume(accountId: string, sessionId: string): Promise<boolean> {
|
||||
await this.redis.ensureConnected();
|
||||
const prefix = process.env.REDIS_KEY_PREFIX ?? "drift:auth:";
|
||||
const max = Number(process.env.CHAT_MESSAGE_RATE_LIMIT ?? 30);
|
||||
const ttl = Number(process.env.CHAT_MESSAGE_RATE_WINDOW_SECONDS ?? 60);
|
||||
const keys = [
|
||||
`${prefix}chat:account:${accountId}`,
|
||||
`${prefix}chat:session:${sessionId}`,
|
||||
];
|
||||
const result = await this.redis.client.eval(
|
||||
`for _,k in ipairs(KEYS) do if tonumber(redis.call('GET',k) or '0')+1>tonumber(ARGV[1]) then return 0 end end; for _,k in ipairs(KEYS) do local n=redis.call('INCR',k); if n==1 then redis.call('EXPIRE',k,ARGV[2]) end end; return 1`,
|
||||
{ keys, arguments: [String(max), String(ttl)] },
|
||||
);
|
||||
return Number(result) === 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user