Skip to content

fix: bound inbound email listener polling and add rate-limit retry#248

Open
bukinoshita wants to merge 5 commits intomainfrom
fix/bounded-poll-with-retry-f4b3
Open

fix: bound inbound email listener polling and add rate-limit retry#248
bukinoshita wants to merge 5 commits intomainfrom
fix/bounded-poll-with-retry-f4b3

Conversation

@bukinoshita
Copy link
Copy Markdown
Member

@bukinoshita bukinoshita commented Apr 9, 2026

Summary by cubic

Bound the inbound email listener’s pagination and added automatic 429 retry to prevent request storms and lost progress during inbox bursts.

  • Bug Fixes

    • Cap pages per poll to 5 to avoid unbounded receiving.list() requests.
    • Checkpoint seen IDs after each page to preserve progress on mid-poll errors.
    • Retry 429s with withRetry using retry-after or 1s/2s/4s backoff.
    • Display emails oldest first.
  • Refactors

    • Added src/lib/with-retry.ts reusable helper (retries up to 3 times).
    • Replaced the while-loop with a recursive fetchPages flow using const arrow functions.

Written for commit 3d64b3d. Summary will update on new commits.

cursoragent and others added 3 commits April 9, 2026 18:06
Extract retry logic for rate_limit_exceeded (429) errors into a
standalone utility. Retries up to 3 times using the retry-after
header when available, falling back to exponential backoff (1s, 2s, 4s).

Co-authored-by: Bu Kinoshita <bukinoshita@users.noreply.github.com>
- Cap pages fetched per poll to MAX_PAGES_PER_POLL (5) so large
  email backlogs don't cause unbounded API request storms.
- Checkpoint seenIds after each page fetch so mid-poll errors
  preserve progress instead of discarding already-fetched emails.
- Wrap receiving.list() calls with withRetry to handle 429
  rate-limit responses with automatic backoff.
- Convert to functional style with const arrow functions and
  recursive fetchPages replacing the imperative while loop.

Closes BU-638

Co-authored-by: Bu Kinoshita <bukinoshita@users.noreply.github.com>
- Add with-retry.test.ts covering success, non-retryable errors,
  rate-limit retries with backoff, max retry exhaustion, and
  retry-after header parsing.
- Add listen tests for multi-page pagination, page cap enforcement,
  incremental checkpointing on mid-poll errors, rate-limit retry
  integration, and chronological email display order.
- Switch from mockClear to mockReset with resetModules to prevent
  mock state leaking between tests.

Co-authored-by: Bu Kinoshita <bukinoshita@users.noreply.github.com>
@bukinoshita
Copy link
Copy Markdown
Member Author

@cubic-dev-ai review this PR?

@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai bot commented Apr 9, 2026

@cubic-dev-ai review this PR?

@bukinoshita I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/lib/with-retry.test.ts">

<violation number="1" location="tests/lib/with-retry.test.ts:33">
P2: Restore fake timers in a `finally` block (or shared cleanup). As written, a failure before `vi.useRealTimers()` will leak fake timers into later tests.</violation>
</file>

<file name="src/lib/with-retry.ts">

<violation number="1" location="src/lib/with-retry.ts:17">
P1: Handle HTTP-date `Retry-After` values as well as numeric seconds, or 429 retries can still fire earlier than the server allows.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread src/lib/with-retry.ts
Comment thread tests/lib/with-retry.test.ts
@bukinoshita bukinoshita marked this pull request as ready for review April 14, 2026 12:25
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