refactor(auth): Move candidate sorting to RoundRobinSelector

This commit is contained in:
hkfires
2025-09-26 10:50:15 +08:00
parent e836b4ac10
commit 9b80820b17
2 changed files with 5 additions and 7 deletions

View File

@@ -15,7 +15,6 @@ import (
"github.com/router-for-me/CLIProxyAPI/v6/internal/util" "github.com/router-for-me/CLIProxyAPI/v6/internal/util"
cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"sort"
) )
// ProviderExecutor defines the contract required by Manager to execute provider calls. // ProviderExecutor defines the contract required by Manager to execute provider calls.
@@ -797,12 +796,6 @@ func (m *Manager) pickNext(ctx context.Context, provider, model string, opts cli
} }
candidates = append(candidates, auth.Clone()) candidates = append(candidates, auth.Clone())
} }
// Ensure stable iteration order across requests to make round-robin deterministic.
// Go map iteration order is randomized; without sorting, the selector's index-based
// rotation may appear non-round-robin.
if len(candidates) > 1 {
sort.Slice(candidates, func(i, j int) bool { return candidates[i].ID < candidates[j].ID })
}
m.mu.RUnlock() m.mu.RUnlock()
if len(candidates) == 0 { if len(candidates) == 0 {
return nil, nil, &Error{Code: "auth_not_found", Message: "no auth available"} return nil, nil, &Error{Code: "auth_not_found", Message: "no auth available"}

View File

@@ -2,6 +2,7 @@ package auth
import ( import (
"context" "context"
"sort"
"sync" "sync"
"time" "time"
@@ -36,6 +37,10 @@ func (s *RoundRobinSelector) Pick(ctx context.Context, provider, model string, o
if len(available) == 0 { if len(available) == 0 {
return nil, &Error{Code: "auth_unavailable", Message: "no auth available"} return nil, &Error{Code: "auth_unavailable", Message: "no auth available"}
} }
// Make round-robin deterministic even if caller's candidate order is unstable.
if len(available) > 1 {
sort.Slice(available, func(i, j int) bool { return available[i].ID < available[j].ID })
}
key := provider + ":" + model key := provider + ":" + model
s.mu.Lock() s.mu.Lock()
index := s.cursors[key] index := s.cursors[key]