fix(auth): make provider rotation atomic

This commit is contained in:
hkfires
2025-12-27 12:56:48 +08:00
parent 72274099aa
commit 8be06255f7

View File

@@ -263,7 +263,6 @@ func (m *Manager) Execute(ctx context.Context, providers []string, req cliproxye
return cliproxyexecutor.Response{}, &Error{Code: "provider_not_found", Message: "no provider supplied"} return cliproxyexecutor.Response{}, &Error{Code: "provider_not_found", Message: "no provider supplied"}
} }
rotated := m.rotateProviders(req.Model, normalized) rotated := m.rotateProviders(req.Model, normalized)
defer m.advanceProviderCursor(req.Model, normalized)
retryTimes, maxWait := m.retrySettings() retryTimes, maxWait := m.retrySettings()
attempts := retryTimes + 1 attempts := retryTimes + 1
@@ -302,7 +301,6 @@ func (m *Manager) ExecuteCount(ctx context.Context, providers []string, req clip
return cliproxyexecutor.Response{}, &Error{Code: "provider_not_found", Message: "no provider supplied"} return cliproxyexecutor.Response{}, &Error{Code: "provider_not_found", Message: "no provider supplied"}
} }
rotated := m.rotateProviders(req.Model, normalized) rotated := m.rotateProviders(req.Model, normalized)
defer m.advanceProviderCursor(req.Model, normalized)
retryTimes, maxWait := m.retrySettings() retryTimes, maxWait := m.retrySettings()
attempts := retryTimes + 1 attempts := retryTimes + 1
@@ -341,7 +339,6 @@ func (m *Manager) ExecuteStream(ctx context.Context, providers []string, req cli
return nil, &Error{Code: "provider_not_found", Message: "no provider supplied"} return nil, &Error{Code: "provider_not_found", Message: "no provider supplied"}
} }
rotated := m.rotateProviders(req.Model, normalized) rotated := m.rotateProviders(req.Model, normalized)
defer m.advanceProviderCursor(req.Model, normalized)
retryTimes, maxWait := m.retrySettings() retryTimes, maxWait := m.retrySettings()
attempts := retryTimes + 1 attempts := retryTimes + 1
@@ -640,13 +637,20 @@ func (m *Manager) normalizeProviders(providers []string) []string {
return result return result
} }
// rotateProviders returns a rotated view of the providers list starting from the
// current offset for the model, and atomically increments the offset for the next call.
// This ensures concurrent requests get different starting providers.
func (m *Manager) rotateProviders(model string, providers []string) []string { func (m *Manager) rotateProviders(model string, providers []string) []string {
if len(providers) == 0 { if len(providers) == 0 {
return nil return nil
} }
m.mu.RLock()
// Atomic read-and-increment: get current offset and advance cursor in one lock
m.mu.Lock()
offset := m.providerOffsets[model] offset := m.providerOffsets[model]
m.mu.RUnlock() m.providerOffsets[model] = (offset + 1) % len(providers)
m.mu.Unlock()
if len(providers) > 0 { if len(providers) > 0 {
offset %= len(providers) offset %= len(providers)
} }
@@ -662,19 +666,6 @@ func (m *Manager) rotateProviders(model string, providers []string) []string {
return rotated return rotated
} }
func (m *Manager) advanceProviderCursor(model string, providers []string) {
if len(providers) == 0 {
m.mu.Lock()
delete(m.providerOffsets, model)
m.mu.Unlock()
return
}
m.mu.Lock()
current := m.providerOffsets[model]
m.providerOffsets[model] = (current + 1) % len(providers)
m.mu.Unlock()
}
func (m *Manager) retrySettings() (int, time.Duration) { func (m *Manager) retrySettings() (int, time.Duration) {
if m == nil { if m == nil {
return 0, 0 return 0, 0