@@ -263,7 +263,6 @@ func (m *Manager) Execute(ctx context.Context, providers []string, req cliproxye
263263 return cliproxyexecutor.Response {}, & Error {Code : "provider_not_found" , Message : "no provider supplied" }
264264 }
265265 rotated := m .rotateProviders (req .Model , normalized )
266- defer m .advanceProviderCursor (req .Model , normalized )
267266
268267 retryTimes , maxWait := m .retrySettings ()
269268 attempts := retryTimes + 1
@@ -302,7 +301,6 @@ func (m *Manager) ExecuteCount(ctx context.Context, providers []string, req clip
302301 return cliproxyexecutor.Response {}, & Error {Code : "provider_not_found" , Message : "no provider supplied" }
303302 }
304303 rotated := m .rotateProviders (req .Model , normalized )
305- defer m .advanceProviderCursor (req .Model , normalized )
306304
307305 retryTimes , maxWait := m .retrySettings ()
308306 attempts := retryTimes + 1
@@ -341,7 +339,6 @@ func (m *Manager) ExecuteStream(ctx context.Context, providers []string, req cli
341339 return nil , & Error {Code : "provider_not_found" , Message : "no provider supplied" }
342340 }
343341 rotated := m .rotateProviders (req .Model , normalized )
344- defer m .advanceProviderCursor (req .Model , normalized )
345342
346343 retryTimes , maxWait := m .retrySettings ()
347344 attempts := retryTimes + 1
@@ -640,13 +637,20 @@ func (m *Manager) normalizeProviders(providers []string) []string {
640637 return result
641638}
642639
640+ // rotateProviders returns a rotated view of the providers list starting from the
641+ // current offset for the model, and atomically increments the offset for the next call.
642+ // This ensures concurrent requests get different starting providers.
643643func (m * Manager ) rotateProviders (model string , providers []string ) []string {
644644 if len (providers ) == 0 {
645645 return nil
646646 }
647- m .mu .RLock ()
647+
648+ // Atomic read-and-increment: get current offset and advance cursor in one lock
649+ m .mu .Lock ()
648650 offset := m .providerOffsets [model ]
649- m .mu .RUnlock ()
651+ m .providerOffsets [model ] = (offset + 1 ) % len (providers )
652+ m .mu .Unlock ()
653+
650654 if len (providers ) > 0 {
651655 offset %= len (providers )
652656 }
@@ -662,19 +666,6 @@ func (m *Manager) rotateProviders(model string, providers []string) []string {
662666 return rotated
663667}
664668
665- func (m * Manager ) advanceProviderCursor (model string , providers []string ) {
666- if len (providers ) == 0 {
667- m .mu .Lock ()
668- delete (m .providerOffsets , model )
669- m .mu .Unlock ()
670- return
671- }
672- m .mu .Lock ()
673- current := m .providerOffsets [model ]
674- m .providerOffsets [model ] = (current + 1 ) % len (providers )
675- m .mu .Unlock ()
676- }
677-
678669func (m * Manager ) retrySettings () (int , time.Duration ) {
679670 if m == nil {
680671 return 0 , 0
0 commit comments