From bdf1be1571e41eafe94212506045181d589aa308 Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Sun, 16 Nov 2025 00:57:16 +0100 Subject: [PATCH] fix: Add DNS retry logic to Telegram bot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- telegram_command_bot.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/telegram_command_bot.py b/telegram_command_bot.py index dd07a20..3887a19 100644 --- a/telegram_command_bot.py +++ b/telegram_command_bot.py @@ -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)