#!/usr/bin/env python3 """ MOMO Pro System - 獨立排程服務 此腳本用於 K8s scheduler 部署,獨立運行排程任務 避免 Gunicorn 多 worker 重複執行的問題 """ import os import sys import time import logging import schedule from datetime import datetime # 設定日誌 logging.basicConfig( level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s', handlers=[ logging.StreamHandler(sys.stdout) ] ) logger = logging.getLogger(__name__) # 確保能夠導入專案模組 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, BASE_DIR) # 設定環境變數(如果未設定) if not os.environ.get('DATABASE_URL'): os.environ['DATABASE_URL'] = 'sqlite:///data/momo_database.db' def main(): """主函數:初始化並運行排程""" logger.info("=" * 60) logger.info("🚀 MOMO Pro Scheduler 啟動中...") logger.info("=" * 60) # 導入排程任務 try: from scheduler import ( run_momo_task, run_edm_task, run_festival_task, run_auto_import_task, run_whitepage_check, run_competitor_price_feeder_task, run_icaim_analysis_task, run_weekly_strategy_task, run_db_backup_task, run_backup_monitor_task, ) logger.info("✅ 排程任務模組載入成功") except ImportError as e: logger.error(f"❌ 無法載入排程模組: {e}") sys.exit(1) # 檢查是否停用自動匯入 disable_auto_import = os.environ.get('DISABLE_AUTO_IMPORT', 'false').lower() == 'true' # 設定排程 schedule.every(1).hours.do(run_momo_task) logger.info("📅 已設定:每小時執行主站爬蟲任務") schedule.every(1).hours.do(run_edm_task) logger.info("📅 已設定:每小時執行 EDM 爬蟲任務") schedule.every(1).hours.do(run_festival_task) logger.info("📅 已設定:每 6 小時執行購物節爬蟲任務") if not disable_auto_import: schedule.every(30).minutes.do(run_auto_import_task) logger.info("📅 已設定:每 30 分鐘執行 Google Drive 自動匯入任務") else: logger.info("⚠️ 自動匯入已停用 (DISABLE_AUTO_IMPORT=true)") schedule.every(30).minutes.do(run_whitepage_check) logger.info("📅 已設定:每 30 分鐘執行網頁白頁監控任務") schedule.every(4).hours.do(run_competitor_price_feeder_task) logger.info("📅 已設定:每 4 小時執行 PChome 競品價格抓取任務") schedule.every(6).hours.do(run_icaim_analysis_task) logger.info("📅 已設定:每 6 小時執行 ICAIM 競價情報分析(Hermes→NemoTron→Telegram)") schedule.every().monday.at("07:00").do(run_weekly_strategy_task) logger.info("📅 已設定:每週一 07:00 執行 Gemini 策略師週報任務") schedule.every().day.at("02:00").do(run_db_backup_task) logger.info("📅 已設定:每日 02:00 執行 PostgreSQL 資料庫備份") schedule.every(6).hours.do(run_backup_monitor_task) logger.info("📅 已設定:每 6 小時執行備份健康監控(AI Agent 跟進)") logger.info("=" * 60) logger.info("✅ 排程器已啟動,等待任務執行...") logger.info("=" * 60) # 啟動時立即執行一次自動匯入(如果未停用) if not disable_auto_import: logger.info("🔄 啟動時執行一次自動匯入...") try: run_auto_import_task() except Exception as e: logger.error(f"❌ 啟動時自動匯入失敗: {e}") # 啟動時立即執行一次爬蟲任務 logger.info("🔄 啟動時執行一次 MOMO 商品爬蟲...") try: run_momo_task() except Exception as e: logger.error(f"❌ 啟動時 MOMO 爬蟲失敗: {e}") logger.info("🔄 啟動時執行一次 EDM 活動爬蟲...") try: run_edm_task() except Exception as e: logger.error(f"❌ 啟動時 EDM 爬蟲失敗: {e}") logger.info("🔄 啟動時執行一次購物節爬蟲...") try: run_festival_task() except Exception as e: logger.error(f"❌ 啟動時購物節爬蟲失敗: {e}") # 運行排程循環 while True: try: schedule.run_pending() time.sleep(1) except KeyboardInterrupt: logger.info("🛑 收到中斷信號,排程器停止") break except Exception as e: logger.error(f"❌ 排程執行錯誤: {e}") time.sleep(5) # 發生錯誤時等待 5 秒後繼續 if __name__ == "__main__": main()