fix(retry): handle Retry-After date and align review nits

This commit is contained in:
pikaxinge 2026-02-27 10:45:18 +00:00
parent e171d77353
commit 07e3f16ca8
3 changed files with 17 additions and 14 deletions

View file

@ -139,8 +139,10 @@ func TestClassifyError_TimeoutPatterns(t *testing.T) {
"connection timed out", "connection timed out",
"deadline exceeded", "deadline exceeded",
"context deadline exceeded", "context deadline exceeded",
"connection reset",
"connection reset by peer", "connection reset by peer",
"tls handshake timeout", "tls handshake timeout",
"EOF",
} }
for _, msg := range patterns { for _, msg := range patterns {

View file

@ -43,7 +43,7 @@ type RetryPolicy struct {
Jitter RetryJitterFunc Jitter RetryJitterFunc
} }
var retryAfterPattern = regexp.MustCompile(`(?i)retry[- ]after[:=]?\s*([^\s\r\n]+)`) var retryAfterPattern = regexp.MustCompile(`(?i)retry[- ]after[:=]?\s*([^\r\n]+)`)
// DefaultLLMRetryPolicy returns the default retry behavior for LLM calls. // DefaultLLMRetryPolicy returns the default retry behavior for LLM calls.
func DefaultLLMRetryPolicy() RetryPolicy { func DefaultLLMRetryPolicy() RetryPolicy {
@ -101,7 +101,7 @@ func DoWithRetry[T any](ctx context.Context, policy RetryPolicy, fn func(context
sleepFn := policy.Sleep sleepFn := policy.Sleep
if sleepFn == nil { if sleepFn == nil {
sleepFn = sleepWithContext sleepFn = sleepWithCtx
} }
jitterFn := policy.Jitter jitterFn := policy.Jitter
if jitterFn == nil { if jitterFn == nil {
@ -232,18 +232,6 @@ func boundedAttemptTimeout(ctx context.Context, configured time.Duration) (time.
return configured, true return configured, true
} }
func sleepWithContext(ctx context.Context, d time.Duration) error {
timer := time.NewTimer(d)
defer timer.Stop()
select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
return nil
}
}
func defaultJitter(max time.Duration) time.Duration { func defaultJitter(max time.Duration) time.Duration {
if max <= 0 { if max <= 0 {
return 0 return 0

View file

@ -150,3 +150,16 @@ func TestLLMRetry_DoWithRetry_UsesRetryAfterFor429(t *testing.T) {
t.Fatalf("slept = %v, want 3s", slept) t.Fatalf("slept = %v, want 3s", slept)
} }
} }
func TestLLMRetry_ExtractRetryAfter_HTTPDate(t *testing.T) {
now := time.Date(2015, 10, 21, 7, 27, 0, 0, time.UTC)
err := errors.New("API request failed:\n Status: 429\n Retry-After: Wed, 21 Oct 2015 07:28:00 GMT")
delay, ok := extractRetryAfter(err, now)
if !ok {
t.Fatal("expected retry-after date to parse")
}
if delay != time.Minute {
t.Fatalf("delay = %v, want 1m", delay)
}
}