Drop abandoned requests from the upstream queue, and shed a deep one !32

merged merged by cmc on 2026-09-12 01:26 UTC · krz/skunky-art:fix/throttle-shed into main

Discussion

cmc

From the crawl on art.krz.sh: 733 upstream timeouts in ten minutes while the address stayed unbanned, because every queued request still took its interval turn after its client had timed out.

  • The throttle watches the request context while waiting for a slot and while waiting out the interval. A cancelled request returns at once and leaves the interval clock untouched.
  • Load shedding: when the queue implies a wait over 20 seconds (devianter gives up at 30), a new request is refused immediately with errUpstreamBusy and never reaches upstream. The error page maps it to a 503 with Retry-After: 5; the API cache serves a stale entry instead when it holds one.

Four tests: shedding is immediate with no upstream call, a cancelled request waiting for a slot returns at once, a request cancelled during the interval does not advance the clock or go upstream, and the 503 mapping.