# -*- coding: utf-8 -*- """ Обработчик здоровья системы: периодическая очистка временных файлов, проверка подключения к PostgreSQL и Qdrant. Используется только на стороне клиентов (ботов) для локальной очистки. """ import asyncio import logging import os from datetime import datetime logger = logging.getLogger(__name__) class HealthHandler: """ Периодические задачи: - Очистка временной директории (temp_dir) и upload_dir. - Очистка постоянных пользовательских файлов (data/user_*). - Healthcheck подключения к PostgreSQL и Qdrant (раз в час). """ def __init__(self, bot): self.bot = bot # ------------------------------------------------------------------ # Цикл очистки файлов # ------------------------------------------------------------------ async def cleanup_loop(self): """ Бесконечный цикл очистки временных файлов. Интервал и сроки хранения берутся из конфига (cleanup.interval_seconds, temp_cleanup_days, upload_cleanup_days, user_data_cleanup_days). """ while True: await asyncio.sleep(self.bot.config.cleanup_interval) try: def sync_cleanup(): # Очистка временной папки (temp_dir) self.bot.files.cleanup_old_files(days=self.bot.config.temp_cleanup_days) # Очистка папки upload_dir upload_dir = self.bot.config.upload_dir if upload_dir.exists(): now = datetime.now().timestamp() for root, dirs, files in os.walk(upload_dir, topdown=False): for name in files: file_path = os.path.join(root, name) try: if os.path.getmtime(file_path) < now - self.bot.config.upload_cleanup_days * 86400: os.remove(file_path) except Exception: pass for name in dirs: dir_path = os.path.join(root, name) try: if not os.listdir(dir_path): os.rmdir(dir_path) except Exception: pass # Очистка постоянных пользовательских файлов в data/ data_dir = self.bot.config.data_dir if data_dir.exists(): now = datetime.now().timestamp() days = getattr(self.bot.config, 'user_data_cleanup_days', 30) for file_path in data_dir.iterdir(): if file_path.is_file() and file_path.name.startswith('user_'): if now - file_path.stat().st_mtime > days * 86400: file_path.unlink() logger.debug(f"Удалён старый пользовательский файл: {file_path.name}") await asyncio.to_thread(sync_cleanup) logger.info("Очистка временных файлов выполнена") except Exception as e: logger.error(f"Ошибка в цикле очистки: {e}") # ------------------------------------------------------------------ # Мониторинг состояния БД и Qdrant # ------------------------------------------------------------------ async def database_health_logger(self): """ Бесконечный цикл: раз в час проверяет соединение с PostgreSQL и Qdrant, логирует результат (OK или FAILED). """ while True: await asyncio.sleep(3600) # --- Проверка PostgreSQL (через RAG-сервер, бот не имеет прямой БД) --- # В новой архитектуре бот не имеет прямого доступа к БД, # поэтому healthcheck перенесён на RAG-сервер. # Здесь мы просто логируем, что проверка пропущена. logger.debug("Healthcheck БД выполняется на RAG-сервере")