mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-09-08 17:11:19 +08:00
Both built-in rotation strategies lost their position whenever the candidate set shrank, which happens on every retry that excludes an already tried credential and on every cooldown transition. Smooth weighted round-robin reset every accumulated credit as soon as the weight vector differed from the previous call. A transient subset is not a configuration change, so the reset fired constantly. With all credits back at zero and equal weights, the strict `>` comparison always resolves ties to the first entry in slice order, and candidates are sorted by auth ID, so every retry restarted the cascade at the alphabetically first credential. Credits are now reset only when a credential's configured weight actually changes, and the accumulator is bounded so permanently removed credentials cannot leak entries. Plain round-robin indexed a monotonic counter into the filtered slice via `available[index%len(available)]`. Once the slice shrank, the modulo re-seated the rotation instead of resuming it. Rotation now continues from the identity of the previous pick, resolved with a binary search over the sorted ring. Measured over 9 equally weighted credentials with a realistic mix of long sessions, new sessions and retries, the busiest-to-quietest ratio drops from 11331x to 1.1x. Distribution is exact for equal weights, matches configured ratios for unequal weights, and tracks the theoretical optimum within 3% under random credential unavailability.