Spaces:
Paused
Paused
Mirrowel commited on
Commit ·
bf79e30
1
Parent(s): 2683513
feat: Enhance error handling in UsageManager to extract retry delay from multiple error message formats
Browse files
src/rotator_library/client.py
CHANGED
|
@@ -19,7 +19,7 @@ if not lib_logger.handlers:
|
|
| 19 |
|
| 20 |
from .usage_manager import UsageManager
|
| 21 |
from .failure_logger import log_failure
|
| 22 |
-
from .error_handler import is_server_error, is_unrecoverable_error
|
| 23 |
from .providers import PROVIDER_PLUGINS
|
| 24 |
|
| 25 |
class RotatingClient:
|
|
@@ -136,8 +136,8 @@ class RotatingClient:
|
|
| 136 |
)
|
| 137 |
|
| 138 |
# For any retriable server error, we just continue the attempt loop
|
| 139 |
-
if is_server_error(e) and attempt < self.max_retries - 1:
|
| 140 |
-
print(f"Key ...{current_key[-4:]} failed with server error. Retrying...")
|
| 141 |
await asyncio.sleep(1 * (attempt + 1))
|
| 142 |
continue
|
| 143 |
|
|
|
|
| 19 |
|
| 20 |
from .usage_manager import UsageManager
|
| 21 |
from .failure_logger import log_failure
|
| 22 |
+
from .error_handler import is_rate_limit_error, is_server_error, is_unrecoverable_error
|
| 23 |
from .providers import PROVIDER_PLUGINS
|
| 24 |
|
| 25 |
class RotatingClient:
|
|
|
|
| 136 |
)
|
| 137 |
|
| 138 |
# For any retriable server error, we just continue the attempt loop
|
| 139 |
+
if is_server_error(e) or is_rate_limit_error(e) and attempt < self.max_retries - 1:
|
| 140 |
+
print(f"Key ...{current_key[-4:]} failed with server error or rate limit error. Retrying...")
|
| 141 |
await asyncio.sleep(1 * (attempt + 1))
|
| 142 |
continue
|
| 143 |
|
src/rotator_library/usage_manager.py
CHANGED
|
@@ -6,6 +6,7 @@ from datetime import date, datetime
|
|
| 6 |
from typing import Dict, List, Optional, Any
|
| 7 |
from filelock import FileLock
|
| 8 |
import litellm
|
|
|
|
| 9 |
|
| 10 |
lib_logger = logging.getLogger('rotator_library')
|
| 11 |
lib_logger.propagate = False # Ensure this logger doesn't propagate to root
|
|
@@ -128,7 +129,44 @@ class UsageManager:
|
|
| 128 |
error_str = str(error).lower()
|
| 129 |
if "retry_delay" in error_str:
|
| 130 |
try:
|
| 131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
cooldown_seconds = int(delay_str)
|
| 133 |
except (IndexError, ValueError):
|
| 134 |
pass
|
|
|
|
| 6 |
from typing import Dict, List, Optional, Any
|
| 7 |
from filelock import FileLock
|
| 8 |
import litellm
|
| 9 |
+
import re
|
| 10 |
|
| 11 |
lib_logger = logging.getLogger('rotator_library')
|
| 12 |
lib_logger.propagate = False # Ensure this logger doesn't propagate to root
|
|
|
|
| 129 |
error_str = str(error).lower()
|
| 130 |
if "retry_delay" in error_str:
|
| 131 |
try:
|
| 132 |
+
# Try multiple patterns to extract delay from error message
|
| 133 |
+
delay_str = None
|
| 134 |
+
|
| 135 |
+
# Pattern 1: retry_delay...seconds format
|
| 136 |
+
if "retry_delay" in error_str and "seconds:" in error_str:
|
| 137 |
+
try:
|
| 138 |
+
delay_str = error_str.split("retry_delay")[1].split("seconds:")[1].strip().split("}")[0]
|
| 139 |
+
except (IndexError, AttributeError):
|
| 140 |
+
pass
|
| 141 |
+
|
| 142 |
+
# Pattern 2: retryDelay with 's' suffix (Gemini format)
|
| 143 |
+
if not delay_str and "retrydelay" in error_str:
|
| 144 |
+
try:
|
| 145 |
+
match = re.search(r'"retrydelay":\s*"(\d+)s"', error_str)
|
| 146 |
+
if match:
|
| 147 |
+
delay_str = match.group(1)
|
| 148 |
+
except Exception:
|
| 149 |
+
pass
|
| 150 |
+
|
| 151 |
+
# Pattern 3: Generic numeric extraction for retry/delay contexts
|
| 152 |
+
if not delay_str:
|
| 153 |
+
try:
|
| 154 |
+
# Look for numbers followed by 's' or 'seconds' in retry/delay context
|
| 155 |
+
patterns = [
|
| 156 |
+
r'retry.*?(\d+)s',
|
| 157 |
+
r'delay.*?(\d+)s',
|
| 158 |
+
r'wait.*?(\d+)\s*seconds?'
|
| 159 |
+
]
|
| 160 |
+
for pattern in patterns:
|
| 161 |
+
match = re.search(pattern, error_str, re.IGNORECASE)
|
| 162 |
+
if match:
|
| 163 |
+
delay_str = match.group(1)
|
| 164 |
+
break
|
| 165 |
+
except Exception:
|
| 166 |
+
pass
|
| 167 |
+
|
| 168 |
+
if delay_str:
|
| 169 |
+
cooldown_seconds = int(delay_str)
|
| 170 |
cooldown_seconds = int(delay_str)
|
| 171 |
except (IndexError, ValueError):
|
| 172 |
pass
|