Skip to content

test(adapters/linear): fix TestRateLimitDeadlineReturnsTypedRateLimited flake under -race load - #110

Merged
ThomasK33 merged 1 commit into
mainfrom
fix/109-linear-ratelimit-flake
Oct 13, 2026
Merged

ThomasK33 merged 1 commit into
mainfrom
fix/109-linear-ratelimit-flake

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

Fixes #109

Cause

TestRateLimitDeadlineReturnsTypedRateLimited gave PostThought a 50 ms real-clock context. That one context was both the transport context and the reference deadline for the no-sleep check. PostThought makes two localhost roundtrips inside that window: the OAuth client-credentials token fetch, then the GraphQL POST that receives the 429. Under -race with CPU load, either roundtrip can take longer than 50 ms. The client then returns a plain context deadline exceeded before the rate-limit path runs. The failure logs show both forms: Post ".../graphql": context deadline exceeded and fetch client credentials token: Post ".../oauth/token": context deadline exceeded.

The production code is correct. If the deadline expires before the 429 arrives, returning the transport's context error is the right result.

Fix (test only)

This PR uses the same fix as the Slack flake in #39 (PR #41):

  • The deadline is now 10 s. The deadline branch in doJSONWithRetry fires whenever now + delay (one hour here) passes the caller deadline. Any deadline far below one hour exercises that branch the same way. 10 s is about 3 orders of magnitude above a loaded roundtrip and about 3 below the one-hour sleep the test guards against.
  • A 5 s completion bound replaces the 1 s elapsed check and the 2 s select timeout. A correct adapter returns after two roundtrips. A broken one blocks until the 10 s deadline or the one-hour backoff.

The assertion is unchanged: the error must be *linear.RateLimited.

Red check: I disabled the deadline branch in retry.go (false && ok && ...). The test then fails with PostThought slept past its caller deadline: a long backoff was not deadline-bounded.

Failure rates

The parallel repro is 48 parallel instances of the -race test binary, each with -count=50 -cpu=1, plus 32 busy-loop CPU spinners, on a 32-CPU host:

Run Before After
Parallel repro, 3 rounds 316 / 7200 (4.4%) 0 / 7200
go test -race -count=200 -cpu=1 -run TestRateLimitDeadlineReturnsTypedRateLimited ./adapters/linear/ under the 32 spinners 8 / 200 (4%) 0 / 200

Validation

  • mise run vet and mise run test pass with Go 1.27.1.
  • gofmt -l is clean.

Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

…ed flake under -race load

The test used one 50ms real-clock context as both the transport context
and the reference deadline for the no-sleep invariant. PostThought makes
two localhost roundtrips inside that window (the OAuth client-credentials
token fetch, then the GraphQL POST that gets the 429). Under -race CPU
load either roundtrip can exceed 50ms, so the client returned a plain
"context deadline exceeded" before the rate-limit path ran.

The deadline branch in doJSONWithRetry fires whenever now+delay (one hour
here) overshoots the caller deadline, so any deadline far below an hour
exercises it identically. Widen the deadline to 10s and let a 5s
completion bound separate "returned promptly" from "slept until the
deadline or backoff". Same fix as the Slack flake in #39.

No production change: returning the transport context error when the
deadline expires before the 429 arrives is correct. Red check: disabling
the deadline branch in retry.go makes the test fail with "slept past its
caller deadline".

Loaded repro (48 parallel -race -count=50 -cpu=1 instances plus 32 CPU
spinners, 3 rounds): 316/7200 failures before, 0/7200 after.

Fixes #109
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T20:20:10.621952Z a410ff5 Manual request
🔒 Security Review ✅ Completed 2026-10-13T20:20:26.339946Z a410ff5 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: a410ff50c5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: a410ff50c5

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33
ThomasK33 merged commit 570ecb4 into main Oct 13, 2026
2 checks passed
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.

adapters/linear: TestRateLimitDeadlineReturnsTypedRateLimited flakes under -race

1 participant