Skip to content

Commit 4bbcad9

Browse files
authored
fix(api): forward all highlight shadow requests (firecrawl#4036)
1 parent bb9175f commit 4bbcad9

6 files changed

Lines changed: 22 additions & 45 deletions

File tree

apps/api/src/config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ const configSchema = z.object({
164164
HIGHLIGHT_MODEL_URL: z.string().optional(),
165165
HIGHLIGHT_MODEL_TOKEN: z.string().optional(),
166166
HIGHLIGHT_SHADOW_RATE: z.coerce.number().min(0).max(1).default(0),
167-
HIGHLIGHT_SHADOW_MAX_INFLIGHT: z.coerce.number().int().positive().default(8),
168167

169168
// Fire Engine
170169
FIRE_ENGINE_BETA_URL: z.string().optional(),

apps/api/src/search/highlight-model.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ interface HighlightBatchOptions {
160160
logPayload?: boolean;
161161
allowLegacyFallback?: boolean;
162162
requestId?: string;
163+
timeoutMs?: number | null;
163164
onFailure?: (reason: HighlightFailureReason) => void;
164165
}
165166

@@ -175,7 +176,12 @@ async function generateHighlightsBatchRequest(
175176
}
176177

177178
const controller = new AbortController();
178-
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
179+
const timeoutMs =
180+
opts.timeoutMs === undefined ? REQUEST_TIMEOUT_MS : opts.timeoutMs;
181+
const timer =
182+
timeoutMs === null
183+
? undefined
184+
: setTimeout(() => controller.abort(), timeoutMs);
179185
const start = Date.now();
180186
try {
181187
const baseUrl = config.HIGHLIGHT_MODEL_URL!.replace(/\/$/, "");
@@ -260,7 +266,9 @@ async function generateHighlightsBatchRequest(
260266
});
261267
return null;
262268
} finally {
263-
clearTimeout(timer);
269+
if (timer !== undefined) {
270+
clearTimeout(timer);
271+
}
264272
}
265273
}
266274

apps/api/src/search/highlights-shadow.test.ts

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
vi.mock("../config", () => ({
22
config: {
33
HIGHLIGHT_SHADOW_RATE: 1,
4-
HIGHLIGHT_SHADOW_MAX_INFLIGHT: 1,
54
},
65
}));
76

@@ -29,7 +28,6 @@ let runSearchHighlightsShadow = createSearchHighlightsShadowRunner(logger);
2928
afterEach(() => {
3029
vi.clearAllMocks();
3130
config.HIGHLIGHT_SHADOW_RATE = 1;
32-
config.HIGHLIGHT_SHADOW_MAX_INFLIGHT = 1;
3331
vi.mocked(highlightsEnvReady).mockReturnValue(true);
3432
runSearchHighlightsShadow = createSearchHighlightsShadowRunner(logger);
3533
});
@@ -77,18 +75,13 @@ describe("runSearchHighlightsShadow", () => {
7775
expect(fields).not.toHaveProperty("highlights");
7876
});
7977

80-
it("drops excess work instead of creating a backlog", async () => {
81-
let finish!: (value: {
82-
attempted: number;
83-
indexHits: number;
84-
replaced: number;
85-
succeeded: boolean;
86-
}) => void;
87-
vi.mocked(runIndexedSearchHighlightsShadow).mockReturnValue(
88-
new Promise(resolve => {
89-
finish = resolve;
90-
}),
91-
);
78+
it("forwards concurrent shadow work without admission drops", async () => {
79+
vi.mocked(runIndexedSearchHighlightsShadow).mockResolvedValue({
80+
attempted: 1,
81+
indexHits: 1,
82+
replaced: 1,
83+
succeeded: true,
84+
});
9285

9386
const input = {
9487
response: {} as any,
@@ -101,18 +94,9 @@ describe("runSearchHighlightsShadow", () => {
10194
).toBe("started");
10295
expect(
10396
runSearchHighlightsShadow({ ...input, requestId: "request-2" }),
104-
).toBe("dropped");
105-
expect(logger.info).toHaveBeenCalledWith(
106-
"Search highlights shadow dropped",
107-
expect.objectContaining({
108-
canonicalLog: "search/highlights-shadow",
109-
outcome: "dropped",
110-
reason: "max_inflight",
111-
}),
112-
);
113-
114-
finish({ attempted: 1, indexHits: 1, replaced: 1, succeeded: true });
97+
).toBe("started");
11598
await new Promise(resolve => setImmediate(resolve));
99+
expect(runIndexedSearchHighlightsShadow).toHaveBeenCalledTimes(2);
116100
});
117101

118102
it("emits the content-free failure category", async () => {

apps/api/src/search/highlights-shadow.ts

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function createSearchHighlightsShadowRunner(
3131
requestId: string;
3232
teamId: string;
3333
zeroDataRetention: boolean;
34-
}) => "skipped" | "dropped" | "started" {
34+
}) => "skipped" | "started" {
3535
let inFlight = 0;
3636

3737
return options => {
@@ -43,20 +43,6 @@ export function createSearchHighlightsShadowRunner(
4343
return "skipped";
4444
}
4545

46-
if (inFlight >= config.HIGHLIGHT_SHADOW_MAX_INFLIGHT) {
47-
canonicalLogger.info("Search highlights shadow dropped", {
48-
canonicalLog: CANONICAL_LOG,
49-
outcome: "dropped",
50-
reason: "max_inflight",
51-
requestId: options.requestId,
52-
teamId: options.teamId,
53-
inFlight,
54-
maxInFlight: config.HIGHLIGHT_SHADOW_MAX_INFLIGHT,
55-
sampleRate: config.HIGHLIGHT_SHADOW_RATE,
56-
});
57-
return "dropped";
58-
}
59-
6046
const urls = searchHighlightURLs(options.response);
6147
const { query, requestId, teamId } = options;
6248
inFlight++;
@@ -74,7 +60,6 @@ export function createSearchHighlightsShadowRunner(
7460
failureReason: result.failureReason,
7561
timeTakenMs: Date.now() - startedAt,
7662
inFlight,
77-
maxInFlight: config.HIGHLIGHT_SHADOW_MAX_INFLIGHT,
7863
sampleRate: config.HIGHLIGHT_SHADOW_RATE,
7964
});
8065
})
@@ -87,7 +72,6 @@ export function createSearchHighlightsShadowRunner(
8772
errorType: error instanceof Error ? error.name : "unknown",
8873
timeTakenMs: Date.now() - startedAt,
8974
inFlight,
90-
maxInFlight: config.HIGHLIGHT_SHADOW_MAX_INFLIGHT,
9175
sampleRate: config.HIGHLIGHT_SHADOW_RATE,
9276
});
9377
})

apps/api/src/search/highlights.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ describe("runIndexedSearchHighlightsShadow", () => {
101101
logger,
102102
logPayload: false,
103103
requestId: "request-1",
104+
timeoutMs: null,
104105
onFailure: expect.any(Function),
105106
},
106107
);

apps/api/src/search/highlights.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ export async function runIndexedSearchHighlightsShadow(
186186
logger,
187187
logPayload: false,
188188
requestId,
189+
timeoutMs: null,
189190
onFailure: reason => {
190191
failureReason = reason;
191192
},

0 commit comments

Comments
 (0)