Release a slot on *key* back to the pool. Parameters ---------- key : The key previously obtained from :meth:`acquire`. success : ``True`` if the API call succeeded; ``False`` if it failed with a rate-limit error (HTTP 429). On fa
(self, key: ApiKey, *, success: bool = True)
| 258 | return key |
| 259 | |
| 260 | def release(self, key: ApiKey, *, success: bool = True) -> None: |
| 261 | """Release a slot on *key* back to the pool. |
| 262 | |
| 263 | Parameters |
| 264 | ---------- |
| 265 | key : |
| 266 | The key previously obtained from :meth:`acquire`. |
| 267 | success : |
| 268 | ``True`` if the API call succeeded; ``False`` if it failed with |
| 269 | a rate-limit error (HTTP 429). On failure the key is marked |
| 270 | rate-limited with exponential backoff. |
| 271 | """ |
| 272 | with self._condition: |
| 273 | key.active_requests = max(0, key.active_requests - 1) |
| 274 | |
| 275 | if success: |
| 276 | key.consecutive_429 = 0 |
| 277 | logger.debug( |
| 278 | "Pool: released slot on key …%s (%d/%d active)", |
| 279 | key.key[-8:], |
| 280 | key.active_requests, |
| 281 | key.max_concurrent, |
| 282 | ) |
| 283 | else: |
| 284 | key.consecutive_429 += 1 |
| 285 | backoff = min( |
| 286 | _BACKOFF_BASE_S * (2 ** (key.consecutive_429 - 1)), |
| 287 | _BACKOFF_CAP_S, |
| 288 | ) |
| 289 | key.rate_limited_until = time.monotonic() + backoff |
| 290 | key.rate_limited = True |
| 291 | self._rate_limits_hit += 1 |
| 292 | logger.warning( |
| 293 | "Pool: key …%s rate-limited for %.0fs " |
| 294 | "(consecutive=%d)", |
| 295 | key.key[-8:], |
| 296 | backoff, |
| 297 | key.consecutive_429, |
| 298 | ) |
| 299 | |
| 300 | self._condition.notify_all() |
| 301 | |
| 302 | def record_retry_success(self) -> None: |
| 303 | """Increment the retry-success counter for reporting. |
no outgoing calls