perf(vehicles): dedup, abort budget, circuit breaker for VIN decode
Production p99 was 18min for failed decodes and 15min for PL24 successes; same VIN could trigger N parallel 10+ min decodes. Three layered fixes: - In-flight dedup via Redis SETNX (vin🔒*); concurrent same-VIN requests poll the resolve cache instead of re-firing the upstream chain. - 24h positive cache (vin:resolve:*) and 6h negative cache (vin:resolve:neg:*); previously 5min positive / no negative. - 25s hard abort budget via AbortController; PCAT gets the signal natively (AbortSignal.any), PL24/EMEX wrapped with raceWithSignal at the boundary. Aborted decodes don't poison the negative cache. - PCAT/EMEX real race: first definitive single-result wins; the slower source is skipped (previously PCAT was always awaited first). - PL24 circuit breaker: 3 consecutive failures opens a 30s cooldown (pl24:cb:cooldown_until); successes reset the counter. - Stage-level timings in query_logs.timings (jsonb): pcat/emex/pl24/ lock_wait/cache_hit/aborted. Failed source now logged as "none" or "aborted" instead of misleading "corgi". Verified locally with 3 parallel decodes of a fresh VIN: 1 real decode (3.59s), 2 lock-waits (3.53s) sharing the result, 4th request 23ms cache hit. Previously this would have been 3 separate 10+ min PL24 decodes. Migration 0002 adds query_logs.timings jsonb (NULL default). Must be applied manually before deploy (deploy.sh does not run db:push). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,7 @@ interface QueryLogItem {
|
||||
success: boolean;
|
||||
errorMessage: string | null;
|
||||
responseTimeMs: number | null;
|
||||
timings: Record<string, number> | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
@@ -185,12 +186,20 @@ function AdminAnalyticsPage() {
|
||||
<div className="text-right">
|
||||
{log.responseTimeMs !== null ? (
|
||||
<span
|
||||
title={
|
||||
log.timings
|
||||
? Object.entries(log.timings)
|
||||
.map(([k, v]) => `${k}: ${v}ms`)
|
||||
.join("\n")
|
||||
: undefined
|
||||
}
|
||||
className={
|
||||
log.responseTimeMs > 5000
|
||||
(log.responseTimeMs > 5000
|
||||
? "text-red-500"
|
||||
: log.responseTimeMs > 2000
|
||||
? "text-amber-500"
|
||||
: "text-green-500"
|
||||
: "text-green-500") +
|
||||
(log.timings ? " cursor-help underline decoration-dotted" : "")
|
||||
}
|
||||
>
|
||||
{log.responseTimeMs}ms
|
||||
|
||||
Reference in New Issue
Block a user