Skip to content

Space requests after the rate limiter has been idle, and update the modules - #76

Merged
djthorpe merged 3 commits into
mainfrom
djt/1025/ratelimit-idle
Oct 25, 2026
Merged

djthorpe merged 3 commits into
mainfrom
djt/1025/ratelimit-idle

Conversation

@djthorpe

@djthorpe djthorpe commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

Fixes the rate limiter letting a burst of requests through at once after the client has been idle, and updates the modules.

The bug

RateLimitTransport gave each request the slot one interval after the last reservation. After the client had been idle, that slot was in the past, so concurrent requests each reserved a slot one interval after the last, all of which had passed, and all were sent at once. omodie's indexing hit this with AcoustID, which allows three requests a second: several lookups arriving together after a quiet spell were rejected with 429 rate limit (4.000000 requests per second) exceeded.

The fix

A request's slot is the next one after the last reservation, or now, when that's passed. The first request, and one after an idle spell, are still sent straight away, and the rest of a burst is spaced by the interval.

Tests

TestRateLimit_ConcurrentRequestsAfterIdleAreThrottled sends a request, waits longer than a burst would take, and then sends four concurrent requests, which must be about an interval apart. Without the fix, they were sent within 50µs of each other. pkg/transport passes with -race.

Module updates

  • go-server v1.6.24 → v1.7.16, OpenTelemetry v1.43.0 → v1.47.0, golang.org/x (crypto, sync, term, net, sys, text), gRPC v1.80.0 → v1.84.0, kong v1.15.0 → v1.16.1, testify v1.11.1 → v1.12.1, and the indirect modules.
  • The root package's tests used client.ContentTypeAny, ContentTypeJson and ContentTypeJsonStream, which no longer exist, so didn't build: they use go-server's types.ContentTypeAny, ContentTypeJSON and ContentTypeJSONStream.
  • example/streaming didn't build against go-server v1.7: its handler is now a JSONStreamHandlerFunc, which receives with stream.Recv() and sends with stream.Send().
  • go vet ./... is clean, and everything passes except pkg/homeassistant, whose tests need a Home Assistant server on the network.

…idle

A request's slot was one interval after the last reservation, which, after
the client had been idle, was in the past, so a burst of concurrent
requests all took slots which had passed, and were sent at once, exceeding
the rate, such as AcoustID's three each second. A slot is now the next one,
or now, when that's passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 25, 2026 14:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused fix preserves synchronized reservations and adds regression coverage for the reported failure, with no unresolved issues identified.

No open issues 🎉

What changed in this PR

This PR fixes idle-period bursts in RateLimitTransport by preventing requests from reserving slots in the past.

Changes:

  • Reserve the later of the current time or the next scheduled slot, preserving immediate dispatch after idle while spacing subsequent requests.
  • Add regression coverage for concurrent requests arriving after an idle period.
File Description
pkg/​transport/​ratelimit.go Clamp reservations to the current time to prevent idle-burst dispatch.
pkg/​transport/​ratelimit_test.go Verify request spacing for a concurrent burst after idle.

Review effort: Balanced

@djthorpe djthorpe self-assigned this Oct 25, 2026
…v1.7

The modules are updated, including go-server v1.6.24 to v1.7.16, OpenTelemetry
v1.43.0 to v1.47.0, and golang.org/x, gRPC and kong. The tests use
go-server's types.ContentTypeAny, ContentTypeJSON and ContentTypeJSONStream,
which replaced the client's own, and the streaming example's handler is a
JSONStreamHandlerFunc, which receives and sends with a JSONStream.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@djthorpe djthorpe changed the title Space requests which arrive together after the rate limiter has been idle Space requests after the rate limiter has been idle, and update the modules Oct 25, 2026
…tions

go-server v1.7.16 needs Go 1.27, so the tests run, and the image is built,
with Go 1.27, rather than 1.25 and 1.26, and the workflows use checkout v5
and setup-go v6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@djthorpe
djthorpe merged commit 871d3c6 into main Oct 25, 2026
4 checks passed
@djthorpe
djthorpe deleted the djt/1025/ratelimit-idle branch October 25, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants