Skip to content

Commit 01100da

Browse files
committed
Update client.py
1 parent 2f99f9b commit 01100da

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

optillm/plugins/proxy/client.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ def __init__(self, config: Dict):
2727
self.last_error = None
2828
self.latencies = [] # Track recent latencies
2929

30+
# Per-provider concurrency control
31+
self.max_concurrent = config.get('max_concurrent', None) # None means no limit
32+
if self.max_concurrent is not None:
33+
self._semaphore = threading.Semaphore(self.max_concurrent)
34+
logger.info(f"Provider {self.name} limited to {self.max_concurrent} concurrent requests")
35+
else:
36+
self._semaphore = None
37+
3038
@property
3139
def client(self):
3240
"""Lazy initialization of OpenAI client"""
@@ -63,6 +71,28 @@ def avg_latency(self) -> float:
6371
if not self.latencies:
6472
return 0
6573
return sum(self.latencies) / len(self.latencies)
74+
75+
def acquire_slot(self, timeout: Optional[float] = None) -> bool:
76+
"""
77+
Try to acquire a slot for this provider.
78+
Returns True if acquired, False if timeout or no limit.
79+
"""
80+
if self._semaphore is None:
81+
return True # No limit, always available
82+
83+
return self._semaphore.acquire(blocking=True, timeout=timeout)
84+
85+
def release_slot(self):
86+
"""Release a slot for this provider."""
87+
if self._semaphore is not None:
88+
self._semaphore.release()
89+
90+
def available_slots(self) -> Optional[int]:
91+
"""Get number of available slots, None if unlimited."""
92+
if self._semaphore is None:
93+
return None
94+
# Note: _value is internal but there's no public method to check availability
95+
return self._semaphore._value
6696

6797
class ProxyClient:
6898
"""OpenAI-compatible client that proxies to multiple providers"""

0 commit comments

Comments
 (0)