|
safety + persist auto-reduce notice
Bug 1 (overshoot): acquire() fast-path now queues while a recycle-poll is in
flight (gatePolling), and the recycle defers its inFlight decrement until the
usage poll resolves — holding inFlight inflated through the poll window so a
concurrent caller cannot sneak through before upstream confirms room. The gated
path admits exactly one waiter per fresh poll (grantOne), robust against stale
upstream counts. Common-case throughput preserved: the fast-path still grants
immediately when no poll is in flight.
Bug 2 (unhandled rejection): fetchUsage is wrapped in safeFetchUsage — a
throwing getUsage() is caught, treated as undefined (cooldown-only fallback),
and reported via the new onUsagePollError opt (warn-level). No unhandled
promise rejection can crash the process.
Bug 3 (lost notice): loadLimits now calls restoreLimit (a new lower-level
state-seeding method that does NOT clear autoReduced) instead of setLimit
(which is a manual user action that clears the notice). The auto-reduce marker
(autoReducedFrom) is persisted under auto-reduce:<providerId> and restored on
activate via loadAutoReduce, so the frontend banner survives a restart.
+6 tests covering each bug.
|