mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
**refactor(executor): simplify Gemini CLI execution and remove internal retry logic**
- Removed nested retry handling for 429 rate limit errors. - Simplified request/response handling by cleaning redundant retry-related code. - Eliminated `parseRetryDelay` function and max retry configuration logic.
This commit is contained in:
@@ -62,6 +62,8 @@ type Result struct {
|
||||
Model string
|
||||
// Success marks whether the execution succeeded.
|
||||
Success bool
|
||||
// RetryAfter carries a provider supplied retry hint (e.g. 429 retryDelay).
|
||||
RetryAfter *time.Duration
|
||||
// Error describes the failure when Success is false.
|
||||
Error *Error
|
||||
}
|
||||
@@ -325,6 +327,9 @@ func (m *Manager) executeWithProvider(ctx context.Context, provider string, req
|
||||
if errors.As(errExec, &se) && se != nil {
|
||||
result.Error.HTTPStatus = se.StatusCode()
|
||||
}
|
||||
if ra := retryAfterFromError(errExec); ra != nil {
|
||||
result.RetryAfter = ra
|
||||
}
|
||||
m.MarkResult(execCtx, result)
|
||||
lastErr = errExec
|
||||
continue
|
||||
@@ -370,6 +375,9 @@ func (m *Manager) executeCountWithProvider(ctx context.Context, provider string,
|
||||
if errors.As(errExec, &se) && se != nil {
|
||||
result.Error.HTTPStatus = se.StatusCode()
|
||||
}
|
||||
if ra := retryAfterFromError(errExec); ra != nil {
|
||||
result.RetryAfter = ra
|
||||
}
|
||||
m.MarkResult(execCtx, result)
|
||||
lastErr = errExec
|
||||
continue
|
||||
@@ -415,6 +423,7 @@ func (m *Manager) executeStreamWithProvider(ctx context.Context, provider string
|
||||
rerr.HTTPStatus = se.StatusCode()
|
||||
}
|
||||
result := Result{AuthID: auth.ID, Provider: provider, Model: req.Model, Success: false, Error: rerr}
|
||||
result.RetryAfter = retryAfterFromError(errStream)
|
||||
m.MarkResult(execCtx, result)
|
||||
lastErr = errStream
|
||||
continue
|
||||
@@ -556,17 +565,23 @@ func (m *Manager) MarkResult(ctx context.Context, result Result) {
|
||||
suspendReason = "payment_required"
|
||||
shouldSuspendModel = true
|
||||
case 429:
|
||||
cooldown, nextLevel := nextQuotaCooldown(state.Quota.BackoffLevel)
|
||||
var next time.Time
|
||||
if cooldown > 0 {
|
||||
next = now.Add(cooldown)
|
||||
backoffLevel := state.Quota.BackoffLevel
|
||||
if result.RetryAfter != nil {
|
||||
next = now.Add(*result.RetryAfter)
|
||||
} else {
|
||||
cooldown, nextLevel := nextQuotaCooldown(backoffLevel)
|
||||
if cooldown > 0 {
|
||||
next = now.Add(cooldown)
|
||||
}
|
||||
backoffLevel = nextLevel
|
||||
}
|
||||
state.NextRetryAfter = next
|
||||
state.Quota = QuotaState{
|
||||
Exceeded: true,
|
||||
Reason: "quota",
|
||||
NextRecoverAt: next,
|
||||
BackoffLevel: nextLevel,
|
||||
BackoffLevel: backoffLevel,
|
||||
}
|
||||
suspendReason = "quota"
|
||||
shouldSuspendModel = true
|
||||
@@ -582,7 +597,7 @@ func (m *Manager) MarkResult(ctx context.Context, result Result) {
|
||||
auth.UpdatedAt = now
|
||||
updateAggregatedAvailability(auth, now)
|
||||
} else {
|
||||
applyAuthFailureState(auth, result.Error, now)
|
||||
applyAuthFailureState(auth, result.Error, result.RetryAfter, now)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -742,6 +757,25 @@ func cloneError(err *Error) *Error {
|
||||
}
|
||||
}
|
||||
|
||||
func retryAfterFromError(err error) *time.Duration {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
type retryAfterProvider interface {
|
||||
RetryAfter() *time.Duration
|
||||
}
|
||||
rap, ok := err.(retryAfterProvider)
|
||||
if !ok || rap == nil {
|
||||
return nil
|
||||
}
|
||||
retryAfter := rap.RetryAfter()
|
||||
if retryAfter == nil {
|
||||
return nil
|
||||
}
|
||||
val := *retryAfter
|
||||
return &val
|
||||
}
|
||||
|
||||
func statusCodeFromResult(err *Error) int {
|
||||
if err == nil {
|
||||
return 0
|
||||
@@ -749,7 +783,7 @@ func statusCodeFromResult(err *Error) int {
|
||||
return err.StatusCode()
|
||||
}
|
||||
|
||||
func applyAuthFailureState(auth *Auth, resultErr *Error, now time.Time) {
|
||||
func applyAuthFailureState(auth *Auth, resultErr *Error, retryAfter *time.Duration, now time.Time) {
|
||||
if auth == nil {
|
||||
return
|
||||
}
|
||||
@@ -774,13 +808,17 @@ func applyAuthFailureState(auth *Auth, resultErr *Error, now time.Time) {
|
||||
auth.StatusMessage = "quota exhausted"
|
||||
auth.Quota.Exceeded = true
|
||||
auth.Quota.Reason = "quota"
|
||||
cooldown, nextLevel := nextQuotaCooldown(auth.Quota.BackoffLevel)
|
||||
var next time.Time
|
||||
if cooldown > 0 {
|
||||
next = now.Add(cooldown)
|
||||
if retryAfter != nil {
|
||||
next = now.Add(*retryAfter)
|
||||
} else {
|
||||
cooldown, nextLevel := nextQuotaCooldown(auth.Quota.BackoffLevel)
|
||||
if cooldown > 0 {
|
||||
next = now.Add(cooldown)
|
||||
}
|
||||
auth.Quota.BackoffLevel = nextLevel
|
||||
}
|
||||
auth.Quota.NextRecoverAt = next
|
||||
auth.Quota.BackoffLevel = nextLevel
|
||||
auth.NextRetryAfter = next
|
||||
case 408, 500, 502, 503, 504:
|
||||
auth.StatusMessage = "transient upstream error"
|
||||
|
||||
Reference in New Issue
Block a user