Skip to content

Gmail: skip failed gets, throttle concurrent requests#2

Merged
kmatzen merged 1 commit intomainfrom
gmail-throttle-and-skip-failed-gets
Apr 27, 2026
Merged

Gmail: skip failed gets, throttle concurrent requests#2
kmatzen merged 1 commit intomainfrom
gmail-throttle-and-skip-failed-gets

Conversation

@kmatzen
Copy link
Copy Markdown
Owner

@kmatzen kmatzen commented Apr 27, 2026

Summary

  • Per-message messages.get failures (non-200 or decode error) no longer fail the whole Gmail fetch — they log the HTTP status + body (or named DecodingError case + body) and are skipped.
  • In-flight messages.get requests are capped at 8. Gmail returns HTTP 429 "Too many concurrent requests for user." well before any per-second quota kicks in; firing 35+ simultaneous gets reliably blew through the per-user concurrent limit.
  • Summary log line splits routine category filtering from real errors: kept N, filtered M, errored K.

Context

The user-visible symptom was "Partial: kmatzen@gmail.com · The data couldn't be read because it is missing." — the localized DecodingError.valueNotFound for id thrown when JSONDecoder was handed Google's error JSON. Two compounding bugs: no HTTP status check before decode, and withThrowingTaskGroup re-throwing the first failure aborted all 35+ in-flight gets. New diagnostic logs confirmed the underlying cause was a 429 rateLimitExceeded / RESOURCE_EXHAUSTED.

Test plan

  • swift build clean
  • make run and trigger a refresh — verified errored 0 (or near-zero) in the new summary line, full inbox visible
  • Soak: confirm no 429s appear in ~/Library/Application Support/Lede/lede.log over a normal day's refresh cycle

A single non-200 response or decode error from messages.get used to throw
out of the task group and surface as "Partial: kmatzen@gmail.com · The
data couldn't be read because it is missing." — the localized form of
DecodingError.valueNotFound when Google returned an error JSON with no
id field.

Per-message failures now log the HTTP status + truncated body (or named
DecodingError case + body) and return .errored, so one bad message no
longer tanks the inbox view. The summary line splits intentional category
filtering from real errors: "kept N, filtered M, errored K".

Cap concurrent in-flight gets at 8. Confirmed via the new logs that the
original failure was Gmail's "Too many concurrent requests for user."
429 — firing 35+ simultaneous gets blew through the per-user concurrent
quota.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kmatzen kmatzen merged commit b708b96 into main Apr 27, 2026
1 check 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.

1 participant