Repository navigation
feat(gmail): add --ids-only to searches; outlast per-minute rate limits - #1257
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: blocked before merge. What this changesThis PR adds ID-only Gmail searches and increases the shared Google API rate-limit retry budget from three to six retries. Example: Search a Gmail account with 2,172 messages matching list:substack.com using --all --max 500.
Review scores
ProductKind: Feature · Worth it: Needs a maintainer decision · Fix scope: Complete Merge readiness⛔ Blocked before merge - 1 item remains Keep open: this PR provides useful behavior absent from current main, resolves the earlier changelog finding, and supplies the requested upgrade evidence; the new flag and shared retry default still need an owner direction decision. Priority: P2 Decision needed
Before merge
FindingsNone. Agent review detailsHow this fits togetherGmail search commands turn queries into paginated Google API requests and format results as JSON or tables; the shared RetryTransport handles rate-limit recovery for Google API clients. flowchart TD
A[Gmail search command] --> B[Paginated Gmail list requests]
B --> C[ID only projection]
B --> D[Label and detail requests]
C --> E[JSON or table output]
D --> E
B --> F[Shared retry transport]
D --> F
Technical reviewBest possible solution: Approve the ID-only search interface and six-retry shared budget if the owner accepts the longer rate-limit recovery window. Do we have a high-confidence way to reproduce the issue? Current-main source unconditionally fetches search details and permits only three rate-limit retries, matching the contributor's real-account failure trace; no target code was executed during this review. Is this the best way to solve the issue? The patch uses existing search and transport owners, preserves normal search output, and directly removes unnecessary detail requests; broadening the shared retry default remains an owner policy choice. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against f9052a583e87. Provenance checked
TestingProof path: shipped entry point. SecurityNone. EvidenceWhat I checked:
Likely related people:
Review metrics
LabelsLabel changes:
Label justifications:
Rating scale6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior. WorkflowClawSweeper edits this one comment on every review. Comment HistoryReview history (1 earlier review cycle)
Reviewed October 23, 2026, 6:31 AM ET / 10:31 UTC (Revision 2). |
|
Added upgrade (v0.46.0 → head) and fresh-install proof to the PR body, and the #1257 reference plus contributor credit to both CHANGELOG entries. @clawsweeper re-review |
|
🦞👀 Re-review progress:
|
1176226 to
4261e05
Compare
Three backoffs (1s, 2s, 4s plus up to 50% jitter, 7-10.5s in total) end long before Gmail's 'Units per minute per user' quota refills, so bulk Gmail searches still failed with 403 rateLimitExceeded. Six backoffs wait 63-94s in total and cover a full minute window.
Both searches fetch each result's headers and labels with one call per result. --ids-only returns the IDs the list call already holds, so bulk jobs feeding gmail batch modify make one call per page (up to 500 IDs).
State the retry wait as 63s to just under 94.5s, show a batch modify pipeline that passes bare IDs, drop the per-page call count from the help text, and test that gmail search rejects --ids-only with --oldest.
…eased 0.47.0 added --headers to message search, which needs the per-message fetch that --ids-only skips.
4261e05 to
ef2eb93
Compare
steipete
left a comment
There was a problem hiding this comment.
Accepting both the opt-in ID-only search and the longer rate-limit retry budget. The new flag avoids unnecessary detail requests while preserving paging and output envelopes; the retry change keeps cancellation and Retry-After handling intact.
Reproduced the missing flag and short retry window on main, then passed the focused ID-only/RetryTransport tests and full make ci on the proposed revision. govulncheck ./... found no reachable vulnerabilities, and independent review found no actionable P0–P2 issues.
|
Landed as 6ad392f. Thank you @jatinbansal1998 for the implementation and live-account evidence. Verified the missing flag and sub-minute retry budget on the previous main, then passed |
|
Thank you @steipete |
Why
Bulk-labelling a few thousand Gmail messages (search, then pipe the IDs into
gmail batch modify) kept failing with:Two causes:
gmail messages searchandgmail searchfetch headers and labels for every result: one extra API call per result. A job that only needs IDs pays for 2,000+ detail calls.--selecttrims the output after the fetch, so it does not help.What changed
--ids-onlyongmail messages search(id,threadId) andgmail search(threadid). It returns what the list call already holds and skips the label lookup and the per-result fetch. Works with--all,--max,--page,--count,--json,--plain. It rejects the content flags it cannot serve (--include-body,--full,--include-attachments,--include-recipients,--headers,--sanitize-content,--oldest).MaxRateLimitRetriesgoes from 3 to 6. Six backoffs wait 63s to just under 94.5s in total, which covers one minute window. This is in the sharedRetryTransport, so every Google API command gets it. The backoff code (jitter,Retry-Afterhandling, the 403-reason check) is unchanged.docs/gmail-workflows.md(bulk-ID recipe),docs/automation.md(retry budget), regenerateddocs/commands/*, CHANGELOG.Before and after
Input:
gog --readonly gmail messages search 'list:substack.com' --all --max 500 --json, run against a real Gmail account with 2,172 matches. HTTP attempts were counted with a throwaway counter hooked intoRetryTransport.RoundTrip. It was only in the measurement builds, not in this PR.Before (upstream
mainf9052a5), run twice, both failed:After, same command (retry budget 6): finishes, slowly, because the quota caps it:
After, with
--ids-only:The
--ids-onlyrun returned the same 2,172id+threadIdpairs as the full run (sorted diff empty).Upgrade and fresh-install proof
Same machine, same existing config and file keyring: installed v0.46.0, then this PR's build. Then this PR's build with
GOG_HOMEpointed at an empty temp directory and no keyring password. Settings and the stored account are unchanged across the upgrade. The fresh install starts cleanly, reports no accounts, fails with the usual missing-credentials error (exit 10) instead of crashing, and rejects bad--ids-onlycombinations with a usage error (exit 2). Account email redacted.Output
Rebased on 0.47.1
Rebased onto
b8298ae6(after the 0.47.1 release); the CHANGELOG entries are under0.47.2 - Unreleased. 0.47.0 added--headerstogmail messages search(#1249). That flag needs the per-message fetch, so--ids-onlynow rejects it, with a test. Live re-check on the rebased build (--readonly):make cipasses on the rebased head.Testing
make cipasses (fmt-check, golangci-lint, deadcode,go test, docs-check).TestExecute_GmailMessagesSearch_IDsOnlySkipsMessageFetches:--all --ids-onlyover two pages makes only list calls and returns IDs without metadata.TestExecute_GmailMessagesSearch_IDsOnlyPlainPrintsIDColumns: plain output is exactlyID\tTHREADrows.TestExecute_GmailMessagesSearch_IDsOnlyRejectsContentFlags:--ids-only --include-bodyis a usage error.TestExecute_GmailSearch_IDsOnlySkipsThreadFetches: same check for thread search.TestRetryTransport_RateLimit403_DefaultBudgetOutlastsPerMinuteQuota: with the default budget, six 403rateLimitExceededresponses in a row still succeed, and the total backoff is at least 1 minute. With the old value 3 it fails:total backoff = 8.12s over 3 retries, want at least 1m.--readonly. The documented pipeline was also checked live, as a dry run with no changes made:gmail messages search ... --ids-only --json --results-only | jq -r '.[].id' | xargs -n 1000 gog --dry-run gmail batch modify --add-label Newslettersprinted agmail.batch.modifydry-run request with the 3 IDs.--ids-onlywith--oldest.