Documentation
¶
Index ¶
- Constants
- Variables
- func IsTransientCommandFailure(ctx context.Context, response CommandResponse) bool
- func NextPageEndpoint(headers map[string]string) string
- func Read(ctx context.Context, dir string, args ...string) ([]byte, error)
- func WithProgress(ctx context.Context, reporter progress.Reporter) context.Context
- func WithReader(ctx context.Context, reader Reader) context.Context
- func WithRetryTelemetry(ctx context.Context, telemetry *RetryTelemetry) context.Context
- type CommandResponse
- type GetRequest
- type Observer
- func (o *Observer) Execute(ctx context.Context, dir string, args ...string) CommandResponse
- func (o *Observer) Get(ctx context.Context, request GetRequest) (response Response, err error)
- func (o *Observer) GetPages(ctx context.Context, request GetRequest, maxPages int) ([]Response, error)
- func (o *Observer) Read(ctx context.Context, dir string, args ...string) ([]byte, error)
- type Reader
- type Response
- type RetryTelemetry
Constants ¶
const DefaultMaxPages = 100
DefaultMaxPages bounds a paginated read. GitHub's own maximum page size is 100, so this is 10 000 items — far past anything WB reads — and exists only so a malformed or looping `link` header cannot make a verb run forever.
Variables ¶
var ErrTransientMutationOutcomeUnknown = errors.New("github transient mutation outcome unknown")
ErrTransientMutationOutcomeUnknown marks a GitHub write whose command failed for a transient transport/provider reason. WB must not blindly retry the mutation: GitHub may have accepted it before the response was lost. Callers first re-read authoritative state, then leave the operation resumable when that read cannot prove the write landed.
var ErrTransientRetriesExhausted = errors.New("github transient read retries exhausted")
ErrTransientRetriesExhausted marks an error returned after every in-process retry attempt for a transient GitHub read failure was exhausted (attempt cap or elapsed budget). Callers that can name a resumable command (for example `wb pr land` or `wb ci wait`) should check for it with errors.Is and append that guidance; the observer package has no such context.
Functions ¶
func IsTransientCommandFailure ¶ added in v0.150.2
func IsTransientCommandFailure(ctx context.Context, response CommandResponse) bool
IsTransientCommandFailure applies the observer's existing transient transport/provider classification to a single non-read command result. It classifies only; it never retries a mutation whose outcome may be unknown.
func NextPageEndpoint ¶ added in v0.89.0
NextPageEndpoint extracts the rel="next" URL from a GitHub link header. It returns "" when there is no next page, which is the ordinary end of a walk.
func WithProgress ¶ added in v0.96.6
WithProgress attaches one transport-neutral progress sink to GitHub reads made below ctx. An explicit GetRequest.Progress takes precedence.
func WithReader ¶ added in v0.175.0
WithReader makes every Get, GetPages and Execute below ctx go to reader.
func WithRetryTelemetry ¶ added in v0.120.0
func WithRetryTelemetry(ctx context.Context, telemetry *RetryTelemetry) context.Context
WithRetryTelemetry attaches a RetryTelemetry accumulator to ctx. Every retried GitHub read (Get/apiGet and Read) made below the returned context increments it, so a caller can report `github_read_retries` on its own receipt after the call returns, whether the call ultimately succeeded or failed.
Types ¶
type CommandResponse ¶
type GetRequest ¶
type Observer ¶
type Observer struct {
StateDir string
Now func() time.Time
Sleep func(context.Context, time.Duration) error
RandomIntn func(int64) int64
Run func(context.Context, string, ...string) commandResult
MaxAttempts int
BaseBackoff time.Duration
MaxBackoff time.Duration
// MinAPIAttemptTimeout floors the per-attempt exec timeout for `gh api`
// and `gh pr view` commands. Defaults to defaultMinAPIAttemptTimeout (30s)
// when unset; never applied when the caller's own context already carries
// an explicit deadline, which remains authoritative.
MinAPIAttemptTimeout time.Duration
// MaxRetryElapsed caps the total wall-clock time spent retrying a single
// GitHub read across all attempts. Defaults to defaultMaxRetryElapsed
// (45s) when unset.
MaxRetryElapsed time.Duration
}
type Reader ¶ added in v0.175.0
type Reader struct {
Get func(ctx context.Context, request GetRequest) (Response, error)
Read func(ctx context.Context, dir string, args ...string) ([]byte, error)
Execute func(ctx context.Context, dir string, args ...string) CommandResponse
}
Reader replaces the GitHub reads made below one context: Get answers Get and GetPages, Read answers Read, Execute answers Execute; a nil function leaves that call to the real observer. It is the seam a unit test uses to count and answer every read of a caller without a `gh` binary, a process or the network.
type Response ¶
type Response struct {
Body []byte
StatusCode int
Headers map[string]string
Cached bool
ObservedAt time.Time
CacheKey string
RequestHash string
}
func GetPages ¶ added in v0.89.0
GetPages performs a paginated GET and returns one response per page, in order.
It follows GitHub's own `link: <…>; rel="next"` header rather than asking the CLI to paginate. That matters because `gh api --paginate --slurp` — the obvious way to get one JSON document per page — needs a `gh` newer than the 2.45 installed on this fleet, and a land verb that breaks on the installed client sends operators back to raw `gh pr merge`, which is precisely how the cleanup that should have run at landing stopped running.
Every page goes through the ordinary observer, so each is conditionally requested, cached, and throttle-aware exactly like a single-page read.
type RetryTelemetry ¶ added in v0.120.0
RetryTelemetry accumulates the in-process GitHub read retries performed while it is attached to a context via WithRetryTelemetry. Count is the number of retries attempted (not the number of calls), and LastReason records the most recent retry's classified cause.