dot-lookup: add 12s hard deadline + reduce FMCSA timeout to 5s

If FMCSA live API is slow (can take 2x 10s = 20s when down), the route would
hang until nginx proxy killed the connection -> 'Failed to fetch'. Now:
- fmcsaFetch timeout: 10s -> 5s (two calls max 10s total)
- SOS entity-status timeout: already reduced to 5s
- 12s hard deadline: if any live API hangs past 12s, immediately return
  census-only data with a 'partial=true' flag so the user gets something

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
justin 2026-05-31 10:34:04 -05:00
parent e7afc3002e
commit cebc432af8

View file

@ -23,7 +23,7 @@ async function fmcsaFetch(path: string): Promise<any> {
try {
const url = `${FMCSA_BASE}/${path}${path.includes("?") ? "&" : "?"}webKey=${FMCSA_API_KEY}`;
const resp = await fetch(url, {
signal: AbortSignal.timeout(10000),
signal: AbortSignal.timeout(5000),
headers: { "Accept": "application/json" },
});
if (!resp.ok) return null;
@ -58,6 +58,12 @@ router.get("/api/v1/dot/lookup", async (req, res) => {
return;
}
// Hard 12s deadline — if FMCSA/SOS APIs are slow, return local census data
// rather than hanging until nginx proxy timeout kills the connection.
const deadline = new Promise<"timeout">((resolve) =>
setTimeout(() => resolve("timeout"), 12000)
);
try {
// 1. Local census data
const local = await pool.query(
@ -66,6 +72,32 @@ router.get("/api/v1/dot/lookup", async (req, res) => {
);
const census = local.rows[0] || null;
// Race the deadline — if live APIs are too slow, return census-only data now
deadline.then((t) => {
if (t === "timeout" && !res.headersSent) {
const name = census?.legal_name || "Unknown";
console.warn("[dot-lookup] Deadline hit for DOT %s — returning census data only", rawDot);
res.json({
dot_number: rawDot,
legal_name: name,
dba_name: census?.dba_name || null,
phy_city: census?.phy_city || null,
phy_state: census?.phy_state || null,
telephone: census?.telephone || null,
email: census?.email_address || null,
fleet: { power_units: census?.nbr_power_unit ?? null, drivers: census?.driver_total ?? null },
mcs150_date: census?.mcs150_parsed || null,
carrier_type: census?.carrier_operation || null,
for_hire: census?.authorized_for_hire || false,
checks: [{ id: "data_partial", label: "Compliance Check", status: "unknown",
detail: "Live FMCSA data is temporarily slow. Showing local records only — try again in a moment for full results." }],
summary: { red: 0, yellow: 0, green: 0, total: 1 },
checked_at: new Date().toISOString(),
partial: true,
});
}
});
// 2. Live FMCSA API (returns null on any failure — already non-throwing)
const snapshot = await fmcsaFetch(rawDot);
const carrier = snapshot?.content?.carrier || null;
@ -587,8 +619,10 @@ router.get("/api/v1/dot/lookup", async (req, res) => {
});
} catch (err) {
console.error("[dot-lookup] Error:", err);
res.status(500).json({ error: "DOT lookup failed." });
if (!res.headersSent) res.status(500).json({ error: "DOT lookup failed." });
}
// Clear the deadline timer to avoid Node keeping the event loop alive
deadline.then(() => {}).catch(() => {});
});
// ── Name Search ─────────────────────────────────────────────────────