fix: attach rate limit details to gRPC error status for SDK retry - #87
Conversation
The SDK retry logic (retry.go) extracts RateLimitDescription from gRPC error status details, not from SyncOpResults annotations. Our previous fix only set annotations, which the retry logic ignored — resulting in linear backoff (1s, 2s, 3s...) instead of respecting the rate limit. Now WrapError attaches RateLimitDescription to the gRPC error status details via st.WithDetails(). The 60s override callers also re-wrap the error with WrapErrorWithRateLimitOverride so the SDK waits 60s instead of the Slack-reported 4s. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Claude finished @btipling's task in 1m 16s —— View job PR Review: Rate Limit gRPC Status Details
Overall: This looks correct and well-motivated. The core insight — that the SDK reads Specific Feedback1. In wrappedErr := client.WrapError(err, ..., &annos) // gRPC status with original retry-after
wrappedErr = client.WrapErrorWithRateLimitOverride(wrappedErr, &annos) // gRPC status with 60s
// New status is first so errors.As finds the override before the original.
return errors.Join(st.Err(), err)2. Silently discarding
st, _ = st.WithDetails(rlDesc)
3. Test is solid but could cover the override path too The new test validates that 4. Minor: This is fine since it's only called after Nits
Verdict: Approve. The approach is sound, the fix addresses the root cause, and the test validates the key behavior. The suggestions above are minor improvements, not blockers. |
Summary
RateLimitDescriptionto gRPC error status details (viast.WithDetails()) so the SDK's retry logic uses proper backoffWrapErrornow sets rate limit info on both the error (for retry) and annotations (for SyncOpResults)WrapErrorWithRateLimitOverridere-wraps errors with 60s on both the gRPC status and annotationsContext
Resolves CXH-1301
The SDK retry logic (
retry.go:87-111) extractsRateLimitDescriptionfromstatus.FromError(err).Details(), not fromSyncOpResultsannotations. Our previous fix only set annotations — the SDK ignored them and fell back to linear backoff (1s, 2s, 3s...), confirmed by Datadog logs showing"wait": 7,"wait": 8instead of 60.Test plan
go test ./pkg/connector/client/ -v"wait": 60on retry after 429🤖 Generated with Claude Code