feat: add retry logic with exponential backoff for transient errors
Retry connection/timeout errors with backoff, skip retry for rate limits
This commit is contained in:
parent
2e4cba0094
commit
d64c3d6758
|
|
@ -1,4 +1,5 @@
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
import time
|
||||||
|
|
||||||
# Import from vendor-specific modules
|
# Import from vendor-specific modules
|
||||||
from .local import get_YFin_data, get_finnhub_news, get_finnhub_company_insider_sentiment, get_finnhub_company_insider_transactions, get_simfin_balance_sheet, get_simfin_cashflow, get_simfin_income_statements, get_reddit_global_news, get_reddit_company_news
|
from .local import get_YFin_data, get_finnhub_news, get_finnhub_company_insider_sentiment, get_finnhub_company_insider_transactions, get_simfin_balance_sheet, get_simfin_cashflow, get_simfin_income_statements, get_reddit_global_news, get_reddit_company_news
|
||||||
|
|
@ -16,6 +17,7 @@ from .alpha_vantage import (
|
||||||
get_news as get_alpha_vantage_news
|
get_news as get_alpha_vantage_news
|
||||||
)
|
)
|
||||||
from .alpha_vantage_common import AlphaVantageRateLimitError
|
from .alpha_vantage_common import AlphaVantageRateLimitError
|
||||||
|
from openai import APIConnectionError, APITimeoutError, RateLimitError
|
||||||
|
|
||||||
# Configuration and routing logic
|
# Configuration and routing logic
|
||||||
from .config import get_config
|
from .config import get_config
|
||||||
|
|
@ -194,25 +196,58 @@ def route_to_vendor(method: str, *args, **kwargs):
|
||||||
else:
|
else:
|
||||||
vendor_methods = [(vendor_impl, vendor)]
|
vendor_methods = [(vendor_impl, vendor)]
|
||||||
|
|
||||||
# Run methods for this vendor
|
# Run methods for this vendor with retry logic
|
||||||
vendor_results = []
|
vendor_results = []
|
||||||
for impl_func, vendor_name in vendor_methods:
|
for impl_func, vendor_name in vendor_methods:
|
||||||
try:
|
max_retries = 3
|
||||||
print(f"DEBUG: Calling {impl_func.__name__} from vendor '{vendor_name}'...")
|
base_delay = 1.0
|
||||||
result = impl_func(*args, **kwargs)
|
last_error = None
|
||||||
vendor_results.append(result)
|
|
||||||
print(f"SUCCESS: {impl_func.__name__} from vendor '{vendor_name}' completed successfully")
|
for retry_attempt in range(max_retries):
|
||||||
|
try:
|
||||||
except AlphaVantageRateLimitError as e:
|
if retry_attempt > 0:
|
||||||
if vendor == "alpha_vantage":
|
print(f"RETRY: Attempt {retry_attempt + 1}/{max_retries} "
|
||||||
print(f"RATE_LIMIT: Alpha Vantage rate limit exceeded, falling back to next available vendor")
|
f"for {impl_func.__name__}")
|
||||||
|
else:
|
||||||
|
print(f"DEBUG: Calling {impl_func.__name__} "
|
||||||
|
f"from vendor '{vendor_name}'...")
|
||||||
|
|
||||||
|
result = impl_func(*args, **kwargs)
|
||||||
|
vendor_results.append(result)
|
||||||
|
print(f"SUCCESS: {impl_func.__name__} from vendor "
|
||||||
|
f"'{vendor_name}' completed successfully")
|
||||||
|
last_error = None
|
||||||
|
break # Success, exit retry loop
|
||||||
|
|
||||||
|
except AlphaVantageRateLimitError as e:
|
||||||
|
print(f"RATE_LIMIT: Alpha Vantage rate limit exceeded")
|
||||||
print(f"DEBUG: Rate limit details: {e}")
|
print(f"DEBUG: Rate limit details: {e}")
|
||||||
# Continue to next vendor for fallback
|
last_error = e
|
||||||
continue
|
break # Don't retry rate limits, move to next vendor
|
||||||
except Exception as e:
|
|
||||||
# Log error but continue with other implementations
|
except (ConnectionError, TimeoutError, OSError,
|
||||||
print(f"FAILED: {impl_func.__name__} from vendor '{vendor_name}' failed: {e}")
|
APIConnectionError, APITimeoutError, RateLimitError) as e:
|
||||||
continue
|
# Transient errors - retry with backoff
|
||||||
|
last_error = e
|
||||||
|
if retry_attempt < max_retries - 1:
|
||||||
|
delay = base_delay * (2 ** retry_attempt)
|
||||||
|
print(f"TRANSIENT_ERROR: {type(e).__name__} - {e}")
|
||||||
|
print(f"RETRY: Waiting {delay}s before retry...")
|
||||||
|
time.sleep(delay)
|
||||||
|
else:
|
||||||
|
print(f"FAILED: {impl_func.__name__} from vendor "
|
||||||
|
f"'{vendor_name}' failed after {max_retries} "
|
||||||
|
f"attempts: {e}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# Non-transient errors - don't retry
|
||||||
|
last_error = e
|
||||||
|
print(f"FAILED: {impl_func.__name__} from vendor "
|
||||||
|
f"'{vendor_name}' failed: {type(e).__name__}: {e}")
|
||||||
|
break
|
||||||
|
|
||||||
|
if last_error is not None:
|
||||||
|
continue # Move to next implementation
|
||||||
|
|
||||||
# Add this vendor's results
|
# Add this vendor's results
|
||||||
if vendor_results:
|
if vendor_results:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue