Enhance bot functionality and refactor database interactions
- Added `ca-certificates` installation to Dockerfile for improved network security. - Updated health check command in Dockerfile to include better timeout handling. - Refactored `run_helper.py` to implement proper signal handling and logging during shutdown. - Transitioned database operations to an asynchronous model in `async_db.py`, improving performance and responsiveness. - Updated database schema to support new foreign key relationships and optimized indexing for better query performance. - Enhanced various bot handlers to utilize async database methods, improving overall efficiency and user experience. - Removed obsolete database and fix scripts to streamline the project structure.
This commit is contained in:
@@ -3,6 +3,8 @@ from aiogram.client.default import DefaultBotProperties
|
||||
from aiogram.fsm.storage.memory import MemoryStorage
|
||||
from aiogram.fsm.strategy import FSMStrategy
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import Optional
|
||||
|
||||
from helper_bot.handlers.admin import admin_router
|
||||
from helper_bot.handlers.callback import callback_router
|
||||
@@ -15,12 +17,36 @@ from helper_bot.middlewares.metrics_middleware import MetricsMiddleware, ErrorMe
|
||||
from helper_bot.server_prometheus import start_metrics_server, stop_metrics_server
|
||||
|
||||
|
||||
async def start_bot_with_retry(bot: Bot, dp: Dispatcher, max_retries: int = 5, base_delay: float = 1.0):
|
||||
"""Запуск бота с автоматическим перезапуском при сетевых ошибках"""
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
logging.info(f"Запуск бота (попытка {attempt + 1}/{max_retries})")
|
||||
await dp.start_polling(bot, skip_updates=True)
|
||||
break
|
||||
except Exception as e:
|
||||
error_msg = str(e).lower()
|
||||
if any(keyword in error_msg for keyword in ['network', 'disconnected', 'timeout', 'connection']):
|
||||
if attempt < max_retries - 1:
|
||||
delay = base_delay * (2 ** attempt) # Exponential backoff
|
||||
logging.warning(f"Сетевая ошибка при запуске бота: {e}. Повтор через {delay:.1f}с (попытка {attempt + 1}/{max_retries})")
|
||||
await asyncio.sleep(delay)
|
||||
continue
|
||||
else:
|
||||
logging.error(f"Превышено максимальное количество попыток запуска бота: {e}")
|
||||
raise
|
||||
else:
|
||||
logging.error(f"Критическая ошибка при запуске бота: {e}")
|
||||
raise
|
||||
|
||||
|
||||
async def start_bot(bdf):
|
||||
token = bdf.settings['Telegram']['bot_token']
|
||||
bot = Bot(token=token, default=DefaultBotProperties(
|
||||
parse_mode='HTML',
|
||||
link_preview_is_disabled=bdf.settings['Telegram']['preview_link']
|
||||
), timeout=30.0)
|
||||
), timeout=60.0) # Увеличиваем timeout для стабильности
|
||||
|
||||
dp = Dispatcher(storage=MemoryStorage(), fsm_strategy=FSMStrategy.GLOBAL_USER)
|
||||
|
||||
# ✅ Оптимизированная регистрация middleware
|
||||
@@ -32,13 +58,19 @@ async def start_bot(bdf):
|
||||
voice_handlers = VoiceHandlers(bdf, bdf.settings)
|
||||
voice_router = voice_handlers.router
|
||||
|
||||
# Добавляем middleware напрямую к роутерам для тестирования
|
||||
admin_router.message.middleware(MetricsMiddleware())
|
||||
private_router.message.middleware(MetricsMiddleware())
|
||||
callback_router.callback_query.middleware(MetricsMiddleware())
|
||||
group_router.message.middleware(MetricsMiddleware())
|
||||
voice_router.message.middleware(MetricsMiddleware())
|
||||
# Middleware уже добавлены на уровне dispatcher
|
||||
dp.include_routers(admin_router, private_router, callback_router, group_router, voice_router)
|
||||
|
||||
# Добавляем обработчик завершения для корректного закрытия
|
||||
@dp.shutdown()
|
||||
async def on_shutdown():
|
||||
logging.info("Bot shutdown initiated, cleaning up resources...")
|
||||
try:
|
||||
await bot.session.close()
|
||||
logging.info("Bot session closed successfully")
|
||||
except Exception as e:
|
||||
logging.error(f"Error closing bot session during shutdown: {e}")
|
||||
|
||||
await bot.delete_webhook(drop_pending_updates=True)
|
||||
|
||||
# Запускаем HTTP сервер для метрик параллельно с ботом
|
||||
@@ -49,12 +81,23 @@ async def start_bot(bdf):
|
||||
# Запускаем метрики сервер
|
||||
await start_metrics_server(metrics_host, metrics_port)
|
||||
|
||||
# Запускаем бота
|
||||
await dp.start_polling(bot, skip_updates=True)
|
||||
# Запускаем бота с retry логикой
|
||||
await start_bot_with_retry(bot, dp)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error in bot startup: {e}")
|
||||
raise
|
||||
finally:
|
||||
# Останавливаем метрики сервер при завершении
|
||||
await stop_metrics_server()
|
||||
try:
|
||||
await stop_metrics_server()
|
||||
except Exception as e:
|
||||
logging.error(f"Error stopping metrics server: {e}")
|
||||
|
||||
# Закрываем сессию бота
|
||||
try:
|
||||
await bot.session.close()
|
||||
except Exception as e:
|
||||
logging.error(f"Error closing bot session: {e}")
|
||||
|
||||
return bot
|
||||
|
||||
Reference in New Issue
Block a user