All checks were successful
CD Pipeline / deploy (push) Successful in 1m6s
openclaw_strategist_service.py: - generate_meta_analysis_report(): 從 ai_insights 抽取週統計 (高頻 SKU / relearn 事件 / 歸檔數) → Gemini 綜合分析 → 雙寫 KM + Telegram scheduler.py: - run_openclaw_meta_analysis_task() 排程包裝 run_scheduler.py: - 週日 02:00 掛入 run_openclaw_meta_analysis_task P1 三層 Agent 自主學習排程全部完成: 02:00 DB備份 / 03:00 去重 / 04:00 品質重算 週一 07:00 週報 / 週日 02:00 Meta-Analysis Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
151 lines
5.2 KiB
Python
151 lines
5.2 KiB
Python
#!/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,
|
||
run_dedup_batch_task,
|
||
run_quality_rescore_task,
|
||
run_openclaw_meta_analysis_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 跟進)")
|
||
|
||
schedule.every().day.at("03:00").do(run_dedup_batch_task)
|
||
logger.info("📅 已設定:每日 03:00 執行 ai_insights 去重批次")
|
||
|
||
schedule.every().day.at("04:00").do(run_quality_rescore_task)
|
||
logger.info("📅 已設定:每日 04:00 執行 ai_insights 品質分數時間衰減重算")
|
||
|
||
schedule.every().sunday.at("02:00").do(run_openclaw_meta_analysis_task)
|
||
logger.info("📅 已設定:每週日 02:00 執行 OpenClaw Meta-Analysis(AI 系統效能自審)")
|
||
|
||
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()
|