e7738de6d2
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
import { Ratelimit } from "@upstash/ratelimit";
|
|
import { Redis } from "@upstash/redis";
|
|
|
|
let minuteRateLimit: Ratelimit | null = null;
|
|
let dailyRateLimit: Ratelimit | null = null;
|
|
|
|
export function isDocsChatRateLimitConfigured() {
|
|
return Boolean(process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN);
|
|
}
|
|
|
|
function getRedis() {
|
|
const url = process.env.KV_REST_API_URL;
|
|
const token = process.env.KV_REST_API_TOKEN;
|
|
|
|
if (!url || !token) {
|
|
throw new Error("Docs chat rate limiting requires KV_REST_API_URL and KV_REST_API_TOKEN");
|
|
}
|
|
|
|
return new Redis({ url, token });
|
|
}
|
|
|
|
function readPositiveInt(name: string, fallback: number): number {
|
|
const value = Number(process.env[name]);
|
|
return Number.isInteger(value) && value > 0 ? value : fallback;
|
|
}
|
|
|
|
const MINUTE_LIMIT = readPositiveInt("RATE_LIMIT_PER_MINUTE", 10);
|
|
const DAILY_LIMIT = readPositiveInt("RATE_LIMIT_PER_DAY", 100);
|
|
|
|
export const docsChatMinuteRateLimit = {
|
|
limit: async (identifier: string) => {
|
|
if (!minuteRateLimit) {
|
|
const redis = getRedis();
|
|
minuteRateLimit = new Ratelimit({
|
|
redis,
|
|
limiter: Ratelimit.slidingWindow(MINUTE_LIMIT, "1 m"),
|
|
prefix: "ratelimit:docs-chat:minute",
|
|
});
|
|
}
|
|
return minuteRateLimit.limit(identifier);
|
|
},
|
|
};
|
|
|
|
export const docsChatDailyRateLimit = {
|
|
limit: async (identifier: string) => {
|
|
if (!dailyRateLimit) {
|
|
const redis = getRedis();
|
|
dailyRateLimit = new Ratelimit({
|
|
redis,
|
|
limiter: Ratelimit.fixedWindow(DAILY_LIMIT, "1 d"),
|
|
prefix: "ratelimit:docs-chat:daily",
|
|
});
|
|
}
|
|
return dailyRateLimit.limit(identifier);
|
|
},
|
|
};
|