MCPcopy Create free account
hub / github.com/NVIDIA/SkillSpector / ApiKeyPool

Class ApiKeyPool

contrib/multilingual/api_pool.py:131–389  ·  view source on GitHub ↗

Thread-safe pool of API keys with per-key concurrency slots. Each key has *max_concurrent* slots (default 5). :meth:`acquire` picks the least-loaded available key — multiple callers can share the same key as long as slots remain. Only rate-limited keys (HTTP 429) are taken out of

Source from the content-addressed store, hash-verified

129
130
131class ApiKeyPool:
132 """Thread-safe pool of API keys with per-key concurrency slots.
133
134 Each key has *max_concurrent* slots (default 5). :meth:`acquire` picks
135 the least-loaded available key — multiple callers can share the same key
136 as long as slots remain. Only rate-limited keys (HTTP 429) are taken
137 out of rotation; the pool only blocks when every non-rate-limited key
138 is at capacity.
139
140 Usage::
141
142 pool = ApiKeyPool([ApiKey("sk-a", ...), ApiKey("sk-b", ...)])
143 key = pool.acquire() # blocks only if all keys full
144 try:
145 llm_call(key)
146 pool.release(key, success=True)
147 except RateLimitError:
148 pool.release(key, success=False)
149 key = pool.acquire()
150 """
151
152 def __init__(self, keys: list[ApiKey]) -> None:
153 if not keys:
154 raise ValueError("ApiKeyPool requires at least one key")
155 self._keys = list(keys)
156 self._lock = threading.Lock()
157 self._condition = threading.Condition(self._lock)
158 self._rate_limits_hit: int = 0
159 self._retry_successes: int = 0
160 self._total_requests_served: int = 0
161 self._peak_active_requests: int = 0
162
163 # -- Public API -----------------------------------------------------------
164
165 def acquire(self, timeout: float | None = None) -> ApiKey:
166 """Acquire a slot on the least-loaded available key.
167
168 Scheduling priority:
169
170 1. **Recovered keys** — rate-limited keys whose backoff has expired
171 become available again.
172 2. **Least-loaded key** — among available keys, pick the one with
173 the fewest ``active_requests``.
174 3. **Block** — if every non-rate-limited key is at capacity, wait
175 for a slot to free up or a rate-limited key to recover.
176
177 Parameters
178 ----------
179 timeout :
180 Maximum seconds to wait. ``None`` means wait indefinitely.
181
182 Returns
183 -------
184 ApiKey
185 A key with at least one available slot.
186
187 Raises
188 ------

Callers 3

_make_poolFunction · 0.90

Calls

no outgoing calls

Tested by 2

_make_poolFunction · 0.72