fix(api): give EMEX a realistic race window in the decode chain (3s -> 8s)

EMEX HTTP scrapes typically answer in ~4-5s, but the decode race capped EMEX at
3s (EMEX_RACE_MS) and fell back to PL24 — which doesn't cover EMEX-only brands.
Prod logs show the exact loss: "PL24 fallback triggered (EMEX: timeout)" at the
3s mark, immediately followed by "EMEX HTTP: found 334 categories". The win was
thrown away.

Raise the default cap to 8s and make it env-tunable (EMEX_RACE_MS), still well
inside the 25s decode budget. Only adds latency on the harder VINs where
PartsCatalogs didn't already resolve. Phase 3 of 4 on decode reliability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-25 00:10:41 +03:00
parent c331dca9fe
commit 9b13c4a21f

View File

@@ -511,8 +511,11 @@ export class VehiclesService {
const corgiKnown = false;
let brandName: string | null = null;
// ── Parallel: PartsCatalogs + EMEX (EMEX capped at 3s) ──────────────
const EMEX_RACE_MS = 3000;
// ── Parallel: PartsCatalogs + EMEX (EMEX capped by EMEX_RACE_MS) ──────────────
// EMEX HTTP scrapes typically answer in ~4-5s; the old 3s cap abandoned those
// wins and forced a PL24 fallback that doesn't cover EMEX-only brands. Give EMEX
// a realistic window (env-tunable), still well inside the 25s decode budget.
const EMEX_RACE_MS = Number(process.env.EMEX_RACE_MS) || 8000;
const pcatStart = Date.now();
let pcatResolved = false;
@@ -544,7 +547,7 @@ export class VehiclesService {
}
});
// Emex result capped at 3s — if it doesn't arrive in time, falls back to PL24
// Emex result capped by EMEX_RACE_MS — if it doesn't arrive in time, fall back to PL24
const emexTimedPromise = Promise.race([
emexBasePromise,
new Promise<null>((resolve) => setTimeout(() => resolve(null), EMEX_RACE_MS)),