Files
firecrawl/apps/api/src/lib/concurrency-limit.ts
T

80 lines
1.9 KiB
TypeScript
Raw Normal View History

2024-10-25 20:21:12 +02:00
import { getRateLimiterPoints } from "../services/rate-limiter";
import { redisConnection } from "../services/queue-service";
import { RateLimiterMode } from "../types";
import { JobsOptions } from "bullmq";
const constructKey = (team_id: string) => "concurrency-limiter:" + team_id;
2024-12-11 19:46:11 -03:00
const constructQueueKey = (team_id: string) =>
"concurrency-limit-queue:" + team_id;
2024-10-25 20:21:12 +02:00
const stalledJobTimeoutMs = 2 * 60 * 1000;
export function getConcurrencyLimitMax(plan: string): number {
2024-12-11 19:46:11 -03:00
return getRateLimiterPoints(RateLimiterMode.Scrape, undefined, plan);
2024-10-25 20:21:12 +02:00
}
2024-12-11 19:46:11 -03:00
export async function cleanOldConcurrencyLimitEntries(
team_id: string,
2024-12-11 19:51:08 -03:00
now: number = Date.now(),
2024-12-11 19:46:11 -03:00
) {
await redisConnection.zremrangebyscore(constructKey(team_id), -Infinity, now);
2024-10-25 20:21:12 +02:00
}
2024-12-11 19:46:11 -03:00
export async function getConcurrencyLimitActiveJobs(
team_id: string,
2024-12-11 19:51:08 -03:00
now: number = Date.now(),
2024-12-11 19:46:11 -03:00
): Promise<string[]> {
return await redisConnection.zrangebyscore(
constructKey(team_id),
now,
2024-12-11 19:51:08 -03:00
Infinity,
2024-12-11 19:46:11 -03:00
);
2024-10-25 20:21:12 +02:00
}
2024-12-11 19:46:11 -03:00
export async function pushConcurrencyLimitActiveJob(
team_id: string,
id: string,
2024-12-11 19:51:08 -03:00
now: number = Date.now(),
2024-12-11 19:46:11 -03:00
) {
await redisConnection.zadd(
constructKey(team_id),
now + stalledJobTimeoutMs,
2024-12-11 19:51:08 -03:00
id,
2024-12-11 19:46:11 -03:00
);
2024-10-25 20:21:12 +02:00
}
2024-12-11 19:46:11 -03:00
export async function removeConcurrencyLimitActiveJob(
team_id: string,
2024-12-11 19:51:08 -03:00
id: string,
2024-12-11 19:46:11 -03:00
) {
await redisConnection.zrem(constructKey(team_id), id);
2024-10-25 20:21:12 +02:00
}
export type ConcurrencyLimitedJob = {
2024-12-11 19:46:11 -03:00
id: string;
data: any;
opts: JobsOptions;
priority?: number;
};
2024-10-25 20:21:12 +02:00
2024-12-11 19:46:11 -03:00
export async function takeConcurrencyLimitedJob(
2024-12-11 19:51:08 -03:00
team_id: string,
2024-12-11 19:46:11 -03:00
): Promise<ConcurrencyLimitedJob | null> {
const res = await redisConnection.zmpop(1, constructQueueKey(team_id), "MIN");
if (res === null || res === undefined) {
return null;
}
2024-10-25 20:21:12 +02:00
2024-12-11 19:46:11 -03:00
return JSON.parse(res[1][0][0]);
2024-10-25 20:21:12 +02:00
}
2024-12-11 19:46:11 -03:00
export async function pushConcurrencyLimitedJob(
team_id: string,
2024-12-11 19:51:08 -03:00
job: ConcurrencyLimitedJob,
2024-12-11 19:46:11 -03:00
) {
await redisConnection.zadd(
constructQueueKey(team_id),
job.priority ?? 1,
2024-12-11 19:51:08 -03:00
JSON.stringify(job),
2024-12-11 19:46:11 -03:00
);
2024-10-25 20:21:12 +02:00
}