Problem
ContainerManager.getOrCreateContainer chains listContainers → optional cleanupOneOrphan (DELETE) → createContainer. Each call runs through HttpClient with timeout: 30000 and maxRetries: 3 (exponential backoff 1+2+4 s). Worst-case math:
listContainers: 4 attempts × 30 s + ~7 s backoff ≈ 2 min
cleanupOneOrphan: ~2 min
createContainer: ~2 min
- Total: up to ~6 min of silent BMW retries
In v1.0.25 we move container setup out of the pairing path and into the first poll cycle (lazy), so this no longer breaks pairing. But it still means the first poll after pairing can hang the polling timer for minutes if BMW's container endpoint is degraded.
Proposal
Wrap the entire getOrCreateContainer flow in Promise.race with a hard deadline (suggest 60–90 s). On timeout, throw a typed error (ContainerSetupTimeoutError or similar) carrying which sub-step we were on.
Caller (polling cycle in Vehicle.startApiPolling) catches the timeout error, logs it, and tries again on the next scheduled poll. No exponential UI degradation, just "we'll try again next cycle".
Acceptance
- New unit test:
getOrCreateContainer rejects with ContainerSetupTimeoutError after deadline elapses, even if underlying HTTP calls are still pending.
- Existing happy-path test unaffected.
- Polling code in
drivers/Vehicle.ts swallows the timeout (logs warn) and schedules next poll normally.
Related
Deferred from v1.0.25 root-cause analysis. Companion to the lazy-container refactor.
Problem
ContainerManager.getOrCreateContainerchainslistContainers→ optionalcleanupOneOrphan(DELETE) →createContainer. Each call runs throughHttpClientwithtimeout: 30000andmaxRetries: 3(exponential backoff 1+2+4 s). Worst-case math:listContainers: 4 attempts × 30 s + ~7 s backoff ≈ 2 mincleanupOneOrphan: ~2 mincreateContainer: ~2 minIn v1.0.25 we move container setup out of the pairing path and into the first poll cycle (lazy), so this no longer breaks pairing. But it still means the first poll after pairing can hang the polling timer for minutes if BMW's container endpoint is degraded.
Proposal
Wrap the entire
getOrCreateContainerflow inPromise.racewith a hard deadline (suggest 60–90 s). On timeout, throw a typed error (ContainerSetupTimeoutErroror similar) carrying which sub-step we were on.Caller (polling cycle in
Vehicle.startApiPolling) catches the timeout error, logs it, and tries again on the next scheduled poll. No exponential UI degradation, just "we'll try again next cycle".Acceptance
getOrCreateContainerrejects withContainerSetupTimeoutErrorafter deadline elapses, even if underlying HTTP calls are still pending.drivers/Vehicle.tsswallows the timeout (logs warn) and schedules next poll normally.Related
Deferred from v1.0.25 root-cause analysis. Companion to the lazy-container refactor.