from datetime import datetime, timedelta, timezone import asyncio import os import logging from app.services.material_consumption_queue import sync_all_advertisers_consumption LOG_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "logs") os.makedirs(LOG_DIR, exist_ok=True) logger = logging.getLogger("material_consumption_task") logger.setLevel(logging.INFO) class DailyRotatingFileHandler(logging.FileHandler): def __init__(self, directory, encoding=None): self.directory = directory filename = self._get_log_filename() super().__init__(filename, encoding=encoding) def _get_log_filename(self): return os.path.join(self.directory, f"material_consumption_task-{datetime.now(timezone.utc).strftime('%Y-%m-%d')}.log") def emit(self, record): current_filename = self._get_log_filename() if self.baseFilename != current_filename: self.close() self.baseFilename = current_filename self.stream = self._open() super().emit(record) if not logger.handlers: handler = DailyRotatingFileHandler(LOG_DIR, encoding="utf-8") handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s", "%Y-%m-%d %H:%M:%S")) logger.addHandler(handler) async def schedule_daily_sync(): """每天9点自动同步素材消耗数据""" logger.info("Daily material consumption sync task started") while True: try: now = datetime.now(timezone.utc) target_time = now.replace(hour=9, minute=0, second=0, microsecond=0) if now >= target_time: target_time += timedelta(days=1) wait_seconds = (target_time - now).total_seconds() logger.info(f"Waiting {wait_seconds/3600:.1f} hours until next sync at {target_time}") await asyncio.sleep(wait_seconds) logger.info("Starting daily material consumption sync...") try: result = await sync_all_advertisers_consumption() logger.info(f"Daily sync completed: {result['message']}") except Exception as e: logger.error(f"Daily sync failed: {e}") except asyncio.CancelledError: logger.info("Daily sync task cancelled") break except Exception as e: logger.error(f"Error in schedule_daily_sync: {e}") await asyncio.sleep(60)