fix(routes): keep the 12 s budget from arrival and name the outage to voice

Starting the upstream timeout after the outbound queue let a request run
up to about 19 s, past the Directions layer's 15 s; the budget again runs
from arrival, queue wait included, and a budget spent before the request
leaves the queue answers 429 "routing busy" rather than an outage.

plan_route threw "Routing HTTP 502" for an outage, and voice passes only
the message on; it now throws "Routing service unavailable (HTTP 502)".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
quanticsoul4772andClaude Opus 5.5 committed 2026-11-02 09:21:08 -08:00
1 parent 536f371dde
commit 1bff1961b4
6 files changed
+53 -25

No files matched your search

+7 -5
View File
@@ -178,14 +178,16 @@ async function fetchRoute({
`${base.replace(/\/$/, '')}/route/v1/${osrmProfile}/${coords}` +
`?overview=full&geometries=geojson&alternatives=false&steps=${withSteps ? 'true' : 'false'}`;
const controller = new AbortController();
let timer;
// One 12 s budget from arrival, queue wait included, so callers sized to it
// (the Directions layer gives up at 15 s) hear back in time.
const timer = setTimeout(() => controller.abort(), 12000);
let osrm;
try {
const upstreamRes = await throughUpstreamGate(async () => {
// The 12 s budget starts when the request leaves, not while it waits
// for an outbound slot, so a wait in our own queue is never reported
// as the routing service being unavailable.
timer = setTimeout(() => controller.abort(), 12000);
// A budget spent waiting in our own queue is our backlog, not the
// routing service failing.
if (controller.signal.aborted)
throw new RouteBusyError(_upstreamIntervalMs);
try {
return await fetchImpl(upstream, {
signal: controller.signal,