Skip to content

Hold replay batches until Retry-After has passed - #55

Merged
jserv merged 1 commit into
sysprog21:mainfrom
ColtenOuO:fix/replay-honor-retry-after
Sep 17, 2026
Merged

jserv merged 1 commit into
sysprog21:mainfrom
ColtenOuO:fix/replay-honor-retry-after

Conversation

@ColtenOuO

@ColtenOuO ColtenOuO commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

After a 429, the replay feed put the refused batch back at the front of the queue and recorded when the server's rate-limit window closes, but nothing read that value. The next flush was still scheduled a fixed second later, and sendQueuedBatch posted without checking the window, so a Retry-After: 30 was answered with a new request every second until the window passed.

Changes

  • Add scheduleFlush(), which waits for whichever is later: the usual one second or the end of the rate-limit window. Both fixed one-second setTimeout calls now go through it.
  • sendQueuedBatch no longer posts while the window is open; it reschedules the flush for the window's end.
  • Behaviour change: a flush awaited while the window is still open, such as the interview's last one, now returns without posting instead of drawing another 429.
  • Add tests/browser/replay-feed.test.js, which runs the feed against mocked timers and fetch. After a 429 with Retry-After: 30, nothing is posted for the next 29 seconds, and at 30 seconds the kept batch goes out together with the event queued behind it.

Summary by cubic

Holds replay batches until the server's Retry-After window has passed. Previously, after a 429 the feed scheduled the next flush a fixed second later and posted without checking the recorded window, so a Retry-After: 30 drew new requests every second.

Bug Fixes

  • Adds scheduleFlush(), which waits for the later of the usual one second or the end of the rate-limit window; both fixed one-second timers now use it.
  • sendQueuedBatch no longer posts while the window is open and reschedules the flush for the window's end.
  • A flush awaited while the window is still open now returns without posting instead of drawing another 429.
  • An interview's final "ended" event is lost if the tab closes before the window passes.
  • Adds tests/browser/replay-feed.test.js, which mocks timers and fetch to verify nothing posts for 29 seconds after a 429 and the kept batch goes out with the queued event at second 30.

Written for commit 0779fbd. Summary will update on new commits.

Review in cubic

cubic-dev-ai[bot]

This comment was marked as resolved.

@ColtenOuO
ColtenOuO force-pushed the fix/replay-honor-retry-after branch from 33a77ad to 90e8638 Compare September 17, 2026 05:04
Comment thread web/replay-feed.js
Comment thread tests/browser/replay-feed.test.js
After a 429 the replay feed put the batch back and recorded when the
server's window closed, then scheduled the next flush a fixed second
later, and sendQueuedBatch never looked at the window. The browser asked
again every second until it passed. Flushes inside the window now
reschedule to its end instead of posting.
@ColtenOuO
ColtenOuO force-pushed the fix/replay-honor-retry-after branch from 90e8638 to 0779fbd Compare September 17, 2026 09:48
@jserv
jserv merged commit d591c18 into sysprog21:main Sep 17, 2026
6 checks passed
@jserv

jserv commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Thank @ColtenOuO for contributing!

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