package com.vincent.rsf.server.ai.store;
|
|
import com.vincent.rsf.server.ai.config.AiDefaults;
|
import com.vincent.rsf.server.ai.store.support.AiRedisExecutor;
|
import com.vincent.rsf.server.ai.store.support.AiRedisKeys;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Component;
|
|
import java.time.Instant;
|
import java.util.UUID;
|
|
@Component
|
@RequiredArgsConstructor
|
public class AiChatRateLimiter {
|
|
private final AiRedisExecutor aiRedisExecutor;
|
private final AiRedisKeys aiRedisKeys;
|
|
public boolean allowChatRequest(Long tenantId, Long userId, String promptCode) {
|
String key = aiRedisKeys.buildRateLimitKey(tenantId, userId, promptCode);
|
long now = Instant.now().toEpochMilli();
|
long windowStart = now - (AiDefaults.CHAT_RATE_LIMIT_WINDOW_SECONDS * 1000L);
|
Boolean allowed = aiRedisExecutor.execute(jedis -> {
|
jedis.zremrangeByScore(key, 0, windowStart);
|
long count = jedis.zcard(key);
|
if (count >= AiDefaults.CHAT_RATE_LIMIT_MAX_REQUESTS) {
|
jedis.expire(key, AiDefaults.CHAT_RATE_LIMIT_WINDOW_SECONDS);
|
return Boolean.FALSE;
|
}
|
jedis.zadd(key, now, now + ":" + UUID.randomUUID());
|
jedis.expire(key, AiDefaults.CHAT_RATE_LIMIT_WINDOW_SECONDS);
|
return Boolean.TRUE;
|
});
|
return Boolean.TRUE.equals(allowed);
|
}
|
}
|