"""CLI 入口:手动触发 / 状态查询。""" from __future__ import annotations import argparse import json import sys from pathlib import Path _PROJECT_ROOT = Path(__file__).resolve().parent.parent if str(_PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(_PROJECT_ROOT)) def main(): parser = argparse.ArgumentParser( description="market_data_sync CLI", ) sub = parser.add_subparsers(dest="cmd", required=True) # sync p_sync = sub.add_parser("sync", help="手动执行一次同步任务") p_sync.add_argument("task_id", help="dataset_id, 例如 kline_daily") p_sync.add_argument("--codes", help="指定股票代码,逗号分隔", default=None) p_sync.add_argument("--start", help="起始日期 YYYY-MM-DD", default=None) p_sync.add_argument("--end", help="结束日期 YYYY-MM-DD", default=None) p_sync.add_argument("--workers", type=int, default=10, help="并发数") sub.add_parser("list", help="列出所有同步任务") sub.add_parser("status", help="查看整体状态(调度器 / 数据源 / 同步任务)") sub.add_parser("datasources", help="查看数据源健康度") sub.add_parser("schedule", help="查看计划任务") sub.add_parser("reseed", help="重新 seed 默认计划任务到 config 表") args = parser.parse_args() if args.cmd == "sync": from app.core.utils.logging import setup_logging setup_logging() from app.tasks import get_task from app.core.datasource.registry import build_default_registry from app.core.sync.registry import seed_sync_registry build_default_registry() seed_sync_registry() # 确保 dataset_registry 有这条任务定义 try: task = get_task(args.task_id) except KeyError as e: print(f"错误: {e}") sys.exit(1) kwargs = {} if args.codes: kwargs["codes"] = [c.strip() for c in args.codes.split(",") if c.strip()] if args.start: kwargs["start"] = args.start if args.end: kwargs["end"] = args.end if args.workers: kwargs["max_workers"] = args.workers result = task.run(trigger_source="cli", **kwargs) print(json.dumps(result, ensure_ascii=False, indent=2)) sys.exit(0 if result.get("status") in ("ok", "warning") else 2) if args.cmd == "list": from app.tasks import TASKS print("可用同步任务:") for tid, cls in TASKS.items(): doc = (cls.__doc__ or cls.__name__).split("\n")[0] print(f" {tid:25s} {doc}") return if args.cmd == "status": from app.core.utils.logging import setup_logging setup_logging() from app.core.scheduler import get_scheduler_status from app.core.datasource.registry import build_default_registry, get_health_status from app.core.sync import get_registry_status build_default_registry() print("\n=== 调度器 ===") s = get_scheduler_status() print(json.dumps(s, ensure_ascii=False, indent=2, default=str)) print("\n=== 数据源健康度 ===") for r in get_health_status(): mark = "✓" if r.get("success") else "✗" print(f" {mark} {r.get('name', r.get('key')):30s} {r.get('message', '')}") print("\n=== 同步任务状态 ===") for r in get_registry_status(): print(f" {r['dataset_id']:25s} status={r.get('status'):10s} " f"lastRun={r.get('last_success_at') or r.get('last_failure_at') or '-':20s} " f"msg={r.get('message', '')[:60]}") return if args.cmd == "datasources": from app.core.utils.logging import setup_logging setup_logging() from app.core.datasource.registry import build_default_registry, get_health_status, run_health_check build_default_registry() print("正在跑连通性测试...") run_health_check() for r in get_health_status(): mark = "✓" if r.get("success") else "✗" print(f" {mark} {r.get('name', r.get('key')):30s} provides={r.get('provides', [])} {r.get('message', '')}") return if args.cmd == "schedule": from app.core.utils.logging import setup_logging setup_logging() from app.core.scheduler import get_scheduler_status, seed_schedule_configs seed_schedule_configs() s = get_scheduler_status() print(f"调度器运行中: {s['running']}") for j in s["jobs"]: enabled = "✓" if j.get("enabled") else "✗" trigger = j.get("time") or f"every {j.get('intervalSeconds')}s" print(f" {enabled} {j.get('name', j['key']):30s} {trigger:15s} " f"condition={j.get('condition', 'always'):12s} " f"last={j.get('lastStatus', '-')}") return if args.cmd == "reseed": from app.core.utils.logging import setup_logging setup_logging() from app.core.scheduler.scheduler import seed_schedule_configs from app.core.sync.registry import seed_sync_registry from app.core.datasource.registry import seed_datasource_configs seed_datasource_configs() seed_sync_registry() seed_schedule_configs() print("已重新 seed:datasources + sync_registry + schedules") return if __name__ == "__main__": main()