Skip to content

feat: expose RetryOption for middleware read access (#475) - #515

Merged
imroc merged 1 commit into
imroc:masterfrom
ManuelReschke:feat_475
Jul 30, 2026
Merged

feat: expose RetryOption for middleware read access (#475)#515
imroc merged 1 commit into
imroc:masterfrom
ManuelReschke:feat_475

Conversation

@ManuelReschke

Copy link
Copy Markdown
Contributor

Expose RetryOption for middleware read access

Fixes #475.

Summary

This change makes the request retry configuration readable from middleware and other external code, matching the existing public Request.RetryAttempt field.

  • Export RetryOption (formerly unexported retryOption) with MaxRetries, interval, conditions, and hooks.
  • Add Request.GetRetryOption() that returns the live retry config, or nil when retry is not configured.
  • Document the common middleware pattern for reporting exceptions only after the retry budget is exhausted, including transport failures and the limitation that RetryAttempt >= MaxRetries does not cover early stops from RetryCondition.

Motivation

RetryAttempt was already readable from middleware, but MaxRetries lived on an unexported retryOption. Callers that want to notify on failure only after all retries are exhausted had no public way to read the configured limit.

API

// nil when retry was never configured on client or request
ro := resp.Request.GetRetryOption()
if ro != nil {
    failed := resp.IsErrorState() || resp.Err != nil
    if failed && ro.MaxRetries >= 0 &&
        resp.Request.RetryAttempt >= ro.MaxRetries {
        // report once after final failure
    }
}

Notes:

  • The returned *RetryOption is the live option for this request; treat it as read-only unless you intentionally mutate retry behavior.
  • RetryAttempt >= MaxRetries detects budget exhaustion only. Retries may also stop earlier when a RetryCondition returns false.
  • Request-level SetRetry* and client-level SetCommonRetry* continue to clone options onto each request as before.
  • GetRetryOption does not create a default option; only the existing setters do.

@imroc imroc left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Clean PR. Exports RetryOption and adds Request.GetRetryOption() for middleware read access, addressing #475.

Verified locally: go build ./..., go vet ./..., go test ./... all pass (22 packages). CI is green.

Review notes:

  • Type rename retryOptionRetryOption is safe (was unexported, no external consumers).
  • GetRetryOption() returns the live pointer (not a clone) — documented clearly with the read-only caveat. Reasonable design choice that also allows middleware to adjust retry behavior if needed.
  • Returns nil when retry is not configured (correct — doesn't create a default like the internal getRetryOption() does).
  • 7 new test cases cover nil, request-level, client-level, override, middleware use case, transport errors, and no-report-on-success. Thorough coverage.
  • Does not touch internal/http3/ or internal/http2/.

No blockers. Merging.

@imroc
imroc merged commit dcfff8b into imroc:master Jul 30, 2026
2 checks 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.

[Feature] 中间件中开放读取 retryOption 权限

2 participants