fix: attach rate limit details to gRPC errors for proper SDK retry backoff - #84
Conversation
…ckoff When Slack rate limits the connector, WrapError was mapping errors to codes.Unavailable but not attaching RateLimitDescription to the gRPC status details. Without this, the SDK's retry logic falls back to linear backoff (1s, 2s, 3s...) instead of respecting Slack's Retry-After timing, causing cascading 429s. Now both rate limit paths attach RateLimitDescription with proper timing: - HTTP 429: uses the exact Retry-After duration from the response header - HTTP 200 ok:false "ratelimited": uses a 30s default since no header exists Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Claude finished @btipling's task in 1m 24s —— View job PR Review
Overall: Good change that addresses a real problem — the SDK's retry loop at Bug: Overly broad
|
…try backoff When Slack rate limits the connector, WrapError was mapping errors to codes.Unavailable but not providing RateLimitDescription annotations on SyncOpResults. Without this, the SDK's retry logic has no rate limit timing info and falls back to linear backoff (1s, 2s, 3s...) instead of respecting Slack's Retry-After timing, causing cascading 429s. WrapError now accepts an optional *annotations.Annotations parameter. When non-nil and a rate limit error is detected, it appends RateLimitDescription to the annotations so callers can include it in SyncOpResults. Both rate limit paths are handled: - HTTP 429: uses the exact Retry-After duration from the response header - HTTP 200 ok:false "ratelimited": uses a 30s default since no header exists All call sites are updated. Sites that already attach rate limit data from businessPlusClient pass nil to avoid stomping existing annotations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Claude finished @btipling's task in 1m 7s —— View job PR Review
Overall: Good change that solves a real problem — without Bug: Overly broad
|
Summary
RateLimitDescriptionto gRPC status details when Slack rate limits the connector, so the SDK's retry logic uses correct backoff timing instead of linear 1s/2s/3s defaultsRetry-Afterfrom header) and HTTP 200ok:falsewith"ratelimited"(uses 30s default)Context
Resolves CXH-1301
The connector was hitting cascading 429s during usergroup grant listing because
WrapErrormapped rate limit errors tocodes.Unavailable(triggering SDK retry) but didn't embed theRetry-Aftertiming in the gRPC status details. The SDK's retry loop extractsRateLimitDescriptionfrom status details to determine wait time — without it, it guesses with linear backoff starting at 1s, which is too aggressive.Test plan
🤖 Generated with Claude Code