mirror of
https://git.mirrors.martin98.com/https://github.com/mendableai/firecrawl
synced 2025-08-12 18:19:00 +08:00
Nick: bug fixes + acuc fixes + cache fixes
This commit is contained in:
parent
3604f2a3ae
commit
04916f17e2
@ -105,6 +105,7 @@ export async function getACUC(
|
|||||||
{ get: true },
|
{ get: true },
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -139,8 +140,17 @@ export async function getACUC(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function clearACUC(api_key: string): Promise<void> {
|
export async function clearACUC(api_key: string): Promise<void> {
|
||||||
const cacheKeyACUC = `acuc_${api_key}`;
|
// Delete cache for all rate limiter modes
|
||||||
await deleteKey(cacheKeyACUC);
|
const modes = Object.values(RateLimiterMode);
|
||||||
|
await Promise.all(
|
||||||
|
modes.map(async (mode) => {
|
||||||
|
const cacheKey = `acuc_${api_key}_${mode}`;
|
||||||
|
await deleteKey(cacheKey);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Also clear the base cache key
|
||||||
|
await deleteKey(`acuc_${api_key}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function authenticateUser(
|
export async function authenticateUser(
|
||||||
@ -188,7 +198,7 @@ export async function supaAuthenticateUser(
|
|||||||
let teamId: string | null = null;
|
let teamId: string | null = null;
|
||||||
let priceId: string | null = null;
|
let priceId: string | null = null;
|
||||||
let chunk: AuthCreditUsageChunk | null = null;
|
let chunk: AuthCreditUsageChunk | null = null;
|
||||||
|
let plan: PlanType = "free";
|
||||||
if (token == "this_is_just_a_preview_token") {
|
if (token == "this_is_just_a_preview_token") {
|
||||||
if (mode == RateLimiterMode.CrawlStatus) {
|
if (mode == RateLimiterMode.CrawlStatus) {
|
||||||
rateLimiter = getRateLimiter(RateLimiterMode.CrawlStatus, token);
|
rateLimiter = getRateLimiter(RateLimiterMode.CrawlStatus, token);
|
||||||
@ -198,6 +208,7 @@ export async function supaAuthenticateUser(
|
|||||||
rateLimiter = getRateLimiter(RateLimiterMode.Preview, token);
|
rateLimiter = getRateLimiter(RateLimiterMode.Preview, token);
|
||||||
}
|
}
|
||||||
teamId = "preview";
|
teamId = "preview";
|
||||||
|
plan = "free";
|
||||||
} else {
|
} else {
|
||||||
normalizedApi = parseApi(token);
|
normalizedApi = parseApi(token);
|
||||||
if (!normalizedApiIsUuid(normalizedApi)) {
|
if (!normalizedApiIsUuid(normalizedApi)) {
|
||||||
@ -221,7 +232,8 @@ export async function supaAuthenticateUser(
|
|||||||
teamId = chunk.team_id;
|
teamId = chunk.team_id;
|
||||||
priceId = chunk.price_id;
|
priceId = chunk.price_id;
|
||||||
|
|
||||||
const plan = getPlanByPriceId(priceId);
|
|
||||||
|
plan = getPlanByPriceId(priceId);
|
||||||
subscriptionData = {
|
subscriptionData = {
|
||||||
team_id: teamId,
|
team_id: teamId,
|
||||||
plan,
|
plan,
|
||||||
@ -322,7 +334,7 @@ export async function supaAuthenticateUser(
|
|||||||
mode === RateLimiterMode.Extract ||
|
mode === RateLimiterMode.Extract ||
|
||||||
mode === RateLimiterMode.Search)
|
mode === RateLimiterMode.Search)
|
||||||
) {
|
) {
|
||||||
return { success: true, team_id: "preview", chunk: null };
|
return { success: true, team_id: "preview", chunk: null, plan: "free" };
|
||||||
// check the origin of the request and make sure its from firecrawl.dev
|
// check the origin of the request and make sure its from firecrawl.dev
|
||||||
// const origin = req.headers.origin;
|
// const origin = req.headers.origin;
|
||||||
// if (origin && origin.includes("firecrawl.dev")){
|
// if (origin && origin.includes("firecrawl.dev")){
|
||||||
@ -369,6 +381,15 @@ function getPlanByPriceId(price_id: string | null): PlanType {
|
|||||||
case process.env.STRIPE_PRICE_ID_ETIER_SCALE_1_MONTHLY:
|
case process.env.STRIPE_PRICE_ID_ETIER_SCALE_1_MONTHLY:
|
||||||
case process.env.STRIPE_PRICE_ID_ETIER_SCALE_1_YEARLY:
|
case process.env.STRIPE_PRICE_ID_ETIER_SCALE_1_YEARLY:
|
||||||
return "etierscale1";
|
return "etierscale1";
|
||||||
|
case process.env.STRIPE_PRICE_ID_EXTRACT_STARTER_MONTHLY:
|
||||||
|
case process.env.STRIPE_PRICE_ID_EXTRACT_STARTER_YEARLY:
|
||||||
|
return "extract_starter";
|
||||||
|
case process.env.STRIPE_PRICE_ID_EXTRACT_EXPLORER_MONTHLY:
|
||||||
|
case process.env.STRIPE_PRICE_ID_EXTRACT_EXPLORER_YEARLY:
|
||||||
|
return "extract_explorer";
|
||||||
|
case process.env.STRIPE_PRICE_ID_EXTRACT_PRO_MONTHLY:
|
||||||
|
case process.env.STRIPE_PRICE_ID_EXTRACT_PRO_YEARLY:
|
||||||
|
return "extract_pro";
|
||||||
default:
|
default:
|
||||||
return "free";
|
return "free";
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import expressWs from "express-ws";
|
|||||||
import { ErrorResponse, ResponseWithSentry } from "./controllers/v1/types";
|
import { ErrorResponse, ResponseWithSentry } from "./controllers/v1/types";
|
||||||
import { ZodError } from "zod";
|
import { ZodError } from "zod";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import { RateLimiterMode } from "./types";
|
||||||
|
|
||||||
const { createBullBoard } = require("@bull-board/api");
|
const { createBullBoard } = require("@bull-board/api");
|
||||||
const { BullAdapter } = require("@bull-board/api/bullAdapter");
|
const { BullAdapter } = require("@bull-board/api/bullAdapter");
|
||||||
@ -249,7 +250,6 @@ app.use(
|
|||||||
);
|
);
|
||||||
|
|
||||||
logger.info(`Worker ${process.pid} started`);
|
logger.info(`Worker ${process.pid} started`);
|
||||||
|
|
||||||
// const sq = getScrapeQueue();
|
// const sq = getScrapeQueue();
|
||||||
|
|
||||||
// sq.on("waiting", j => ScrapeEvents.logJobEvent(j, "waiting"));
|
// sq.on("waiting", j => ScrapeEvents.logJobEvent(j, "waiting"));
|
||||||
|
@ -41,6 +41,11 @@ export type CacheEntry = {
|
|||||||
export async function saveEntryToCache(key: string, entry: CacheEntry) {
|
export async function saveEntryToCache(key: string, entry: CacheEntry) {
|
||||||
if (!cacheRedis) return;
|
if (!cacheRedis) return;
|
||||||
|
|
||||||
|
if (!entry.html || entry.html.length < 100) {
|
||||||
|
logger.warn("Skipping cache save for short HTML", { key, htmlLength: entry.html?.length });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await cacheRedis.set(key, JSON.stringify(entry), "EX", 3600); // 1 hour in seconds
|
await cacheRedis.set(key, JSON.stringify(entry), "EX", 3600); // 1 hour in seconds
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -10,6 +10,14 @@ export async function scrapeCache(meta: Meta): Promise<EngineScrapeResult> {
|
|||||||
const entry = await getEntryFromCache(key);
|
const entry = await getEntryFromCache(key);
|
||||||
if (entry === null) throw new EngineError("Cache missed");
|
if (entry === null) throw new EngineError("Cache missed");
|
||||||
|
|
||||||
|
if (!entry.html) {
|
||||||
|
throw new EngineError("Cache hit but HTML is missing");
|
||||||
|
}
|
||||||
|
if (entry.html.length < 100) {
|
||||||
|
throw new EngineError("Cache hit but HTML is too short to be useful");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set fromCache flag to indicate this document was retrieved from cache
|
// Set fromCache flag to indicate this document was retrieved from cache
|
||||||
meta.internalOptions.fromCache = true;
|
meta.internalOptions.fromCache = true;
|
||||||
|
|
||||||
|
@ -19,6 +19,10 @@ const RATE_LIMITS = {
|
|||||||
etier1a: 1000,
|
etier1a: 1000,
|
||||||
etier2a: 300,
|
etier2a: 300,
|
||||||
etierscale1: 150,
|
etierscale1: 150,
|
||||||
|
// extract ops
|
||||||
|
extract_starter: 20,
|
||||||
|
extract_explorer: 100,
|
||||||
|
extract_pro: 1000,
|
||||||
},
|
},
|
||||||
scrape: {
|
scrape: {
|
||||||
default: 20,
|
default: 20,
|
||||||
@ -36,6 +40,10 @@ const RATE_LIMITS = {
|
|||||||
etier1a: 1000,
|
etier1a: 1000,
|
||||||
etier2a: 2500,
|
etier2a: 2500,
|
||||||
etierscale1: 1500,
|
etierscale1: 1500,
|
||||||
|
// extract ops
|
||||||
|
extract_starter: 20,
|
||||||
|
extract_explorer: 100,
|
||||||
|
extract_pro: 1000,
|
||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
default: 20,
|
default: 20,
|
||||||
@ -53,6 +61,10 @@ const RATE_LIMITS = {
|
|||||||
etier1a: 1000,
|
etier1a: 1000,
|
||||||
etier2a: 2500,
|
etier2a: 2500,
|
||||||
etierscale1: 1500,
|
etierscale1: 1500,
|
||||||
|
// extract ops
|
||||||
|
extract_starter: 20,
|
||||||
|
extract_explorer: 100,
|
||||||
|
extract_pro: 1000,
|
||||||
},
|
},
|
||||||
map: {
|
map: {
|
||||||
default: 20,
|
default: 20,
|
||||||
@ -70,6 +82,10 @@ const RATE_LIMITS = {
|
|||||||
etier1a: 1000,
|
etier1a: 1000,
|
||||||
etier2a: 2500,
|
etier2a: 2500,
|
||||||
etierscale1: 1500,
|
etierscale1: 1500,
|
||||||
|
// extract ops
|
||||||
|
extract_starter: 20,
|
||||||
|
extract_explorer: 100,
|
||||||
|
extract_pro: 1000,
|
||||||
},
|
},
|
||||||
extract: {
|
extract: {
|
||||||
default: 20,
|
default: 20,
|
||||||
@ -87,6 +103,9 @@ const RATE_LIMITS = {
|
|||||||
etier1a: 1000,
|
etier1a: 1000,
|
||||||
etier2a: 1000,
|
etier2a: 1000,
|
||||||
etierscale1: 1000,
|
etierscale1: 1000,
|
||||||
|
extract_starter: 20,
|
||||||
|
extract_explorer: 100,
|
||||||
|
extract_pro: 1000,
|
||||||
},
|
},
|
||||||
preview: {
|
preview: {
|
||||||
free: 5,
|
free: 5,
|
||||||
|
@ -186,6 +186,9 @@ export type PlanType =
|
|||||||
| "etier1a"
|
| "etier1a"
|
||||||
| "etierscale1"
|
| "etierscale1"
|
||||||
| "free"
|
| "free"
|
||||||
|
| "extract_starter"
|
||||||
|
| "extract_explorer"
|
||||||
|
| "extract_pro"
|
||||||
| "";
|
| "";
|
||||||
|
|
||||||
export type WebhookEventType =
|
export type WebhookEventType =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user