fix: Add DNS retry logic to Telegram bot

Problem: Python urllib3 throwing 'Failed to resolve trading-bot-v4' errors
Root cause: Transient DNS resolution failures (similar to Node.js DNS issue)

Solution: Added retry_request() wrapper with exponential backoff:
- Retries DNS/connection errors up to 3 times
- 2s → 4s → 8s delays between attempts
- Same pattern as Node.js retryOperation() in drift/client.ts

Applied to:
- /status command (position fetching)
- Manual trade execution (most critical)

User request: Configure bot to handle DNS problems better
Result: Telegram bot now self-recovers from transient DNS failures
This commit is contained in:
mindesbunister
2025-11-16 00:57:16 +01:00
parent b1ca454a6f
commit bdf1be1571

View File

@@ -4,10 +4,37 @@ Telegram Trade Bot - SECURE Command-based
Only responds to YOUR commands in YOUR chat
"""
import os
import time
import requests
from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
def retry_request(func, max_retries=3, initial_delay=2):
"""
Retry wrapper for DNS/connection failures
Similar to Node.js retryOperation() logic
"""
for attempt in range(max_retries):
try:
return func()
except (requests.exceptions.ConnectionError,
requests.exceptions.Timeout,
Exception) as e:
error_msg = str(e).lower()
# Check for transient DNS/connection errors
if 'name or service not known' in error_msg or \
'failed to resolve' in error_msg or \
'connection' in error_msg:
if attempt < max_retries - 1:
delay = initial_delay * (2 ** attempt)
print(f"⏳ DNS/connection error (attempt {attempt + 1}/{max_retries}): {e}", flush=True)
print(f" Retrying in {delay}s...", flush=True)
time.sleep(delay)
continue
# Non-transient error or max retries reached
raise
raise Exception(f"Max retries ({max_retries}) exceeded")
# Configuration
TELEGRAM_BOT_TOKEN = os.getenv('TELEGRAM_BOT_TOKEN')
N8N_WEBHOOK_URL = os.getenv('N8N_WEBHOOK_URL')
@@ -58,12 +85,12 @@ async def status_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
print(f"📊 /status command received", flush=True)
try:
# Fetch positions from trading bot API
response = requests.get(
# Fetch positions from trading bot API with retry logic
response = retry_request(lambda: requests.get(
f"{TRADING_BOT_URL}/api/trading/positions",
headers={'Authorization': f'Bearer {API_SECRET_KEY}'},
timeout=10
)
))
print(f"📥 API Response: {response.status_code}", flush=True)
@@ -646,12 +673,12 @@ async def manual_trade_handler(update: Update, context: ContextTypes.DEFAULT_TYP
try:
print(f"🚀 Manual trade: {direction.upper()} {symbol_info['label']}{' (FORCED)' if force_trade else ''}", flush=True)
response = requests.post(
response = retry_request(lambda: requests.post(
f"{TRADING_BOT_URL}/api/trading/execute",
headers={'Authorization': f'Bearer {API_SECRET_KEY}'},
json=payload,
timeout=60,
)
))
print(f"📥 Manual trade response: {response.status_code}", flush=True)