package merrors import ( "errors" "strings" "time" ) // ThrottleDetails describes a temporary request limit without coupling callers // to a transport-specific response format. type ThrottleDetails struct { ScopeKind string RetryAfter time.Duration } type throttleDetailsError struct { base error msg string details ThrottleDetails } func (e throttleDetailsError) Error() string { return Wrap(e.base, e.msg).Error() } func (e throttleDetailsError) Unwrap() error { return e.base } // WithThrottle annotates an error with retry information while preserving its // classification for errors.Is and errors.As. func WithThrottle(base error, scopeKind string, retryAfter time.Duration, msg string) error { return throttleDetailsError{ base: base, msg: msg, details: ThrottleDetails{ ScopeKind: strings.TrimSpace(scopeKind), RetryAfter: retryAfter, }, } } // ThrottleDetailsFrom returns retry information attached by WithThrottle. func ThrottleDetailsFrom(err error) (ThrottleDetails, bool) { var throttled throttleDetailsError if !errors.As(err, &throttled) { return ThrottleDetails{}, false } return throttled.details, true }