From 0e8cf51f64d85bd4695bb8c1fda18915b30f9af5 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Sun, 7 Jun 2026 21:50:36 +0800 Subject: [PATCH] update --- AGENTS.md | 1 + app/db/scheduler_db.py | 68 ++++++++++++++++++++++++++++----- static/paper_trading.html | 44 ++++++++++----------- tests/test_scheduler_control.py | 28 ++++++++++++++ 4 files changed, 109 insertions(+), 32 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 2027e00..13a42c0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -140,6 +140,7 @@ AlphaX 是一个以 `Python + FastAPI + PostgreSQL + Docker + 静态 HTML` 组 - 链上功能当前已下线,不再有 `onchain` CLI、调度任务、Web 页面、API route、NodeReal/Alchemy client 或链上因子评分。 - 历史 PostgreSQL migration 中的 `onchain_*` 表可暂时保留,避免破坏已部署库的迁移链;当前业务代码不应读取或写入这些表。 +- 下线运行模块时不能只删 CLI/route/service,还必须在 `app/db/scheduler_db.py#RETIRED_JOBS` 登记退役任务,初始化时自动禁用旧 `scheduler_job_config`、跳过旧手动触发,并从 scheduler/API/运行大屏过滤,避免线上数据库残留任务继续执行已删除命令。 - 后续如需重启链上方向,必须先重新设计数据源、可读事件模型、映射机制、策略接入边界和复盘评价,不能直接恢复旧实现。 ### 4.2 Web/API diff --git a/app/db/scheduler_db.py b/app/db/scheduler_db.py index 2c21b3f..05df4cc 100644 --- a/app/db/scheduler_db.py +++ b/app/db/scheduler_db.py @@ -7,6 +7,9 @@ from app.db import altcoin_db from app.db.postgres_connection import connect as pg_connect, ensure_migrations_once _SCHEDULER_INIT_DONE = False +RETIRED_JOBS = { + "onchain": "链上采集/API 模块已下线,当前系统聚焦 CEX 机会捕捉", +} def get_scheduler_conn(): @@ -165,6 +168,43 @@ def _seed_scheduler_tables(conn): """, (job["job_name"], now), ) + _retire_scheduler_jobs(conn, now) + + +def _retire_scheduler_jobs(conn, now: str | None = None): + now = now or _now() + for job_name, reason in RETIRED_JOBS.items(): + conn.execute( + """ + UPDATE scheduler_job_config + SET enabled=0, + description=%s, + updated_at=%s + WHERE job_name=%s + """, + (f"已下线:{reason}", now, job_name), + ) + conn.execute( + """ + INSERT INTO scheduler_runtime_status (job_name, status, last_error, updated_at) + VALUES (%s, 'disabled', %s, %s) + ON CONFLICT(job_name) DO UPDATE SET + status='disabled', + last_error=excluded.last_error, + updated_at=excluded.updated_at + """, + (job_name, reason, now), + ) + conn.execute( + """ + UPDATE scheduler_manual_trigger + SET status='skipped', + finished_at=%s, + error_message=%s + WHERE job_name=%s AND status IN ('queued','pending','running') + """, + (now, reason, job_name), + ) def init_scheduler_tables(): @@ -183,7 +223,7 @@ def init_scheduler_tables(): def get_job_configs(): init_scheduler_tables() conn = get_scheduler_conn() - rows = conn.execute("SELECT * FROM scheduler_job_config ORDER BY sort_order ASC, job_name ASC").fetchall() + rows = conn.execute("SELECT * FROM scheduler_job_config WHERE job_name <> ALL(%s) ORDER BY sort_order ASC, job_name ASC", (list(RETIRED_JOBS.keys()),)).fetchall() conn.close() jobs = [] for row in rows: @@ -201,6 +241,8 @@ def get_job_config(job_name): conn.close() if not row: return None + if row["job_name"] in RETIRED_JOBS: + return None item = dict(row) item["args"] = _load(item.pop("args_json", "[]"), []) item["enabled"] = bool(item.get("enabled")) @@ -211,10 +253,13 @@ def set_job_enabled(job_name, enabled): init_scheduler_tables() now = _now() conn = get_scheduler_conn() - cur = conn.execute( - "UPDATE scheduler_job_config SET enabled=%s, updated_at=%s WHERE job_name=%s", - (1 if enabled else 0, now, job_name), - ) + if job_name in RETIRED_JOBS: + cur = conn.execute("UPDATE scheduler_job_config SET enabled=0, updated_at=%s WHERE job_name=%s", (now, job_name)) + else: + cur = conn.execute( + "UPDATE scheduler_job_config SET enabled=%s, updated_at=%s WHERE job_name=%s", + (1 if enabled else 0, now, job_name), + ) conn.commit() conn.close() return cur.rowcount > 0 @@ -225,10 +270,13 @@ def set_job_interval(job_name, every_seconds): init_scheduler_tables() now = _now() conn = get_scheduler_conn() - cur = conn.execute( - "UPDATE scheduler_job_config SET every_seconds=%s, updated_at=%s WHERE job_name=%s", - (seconds, now, job_name), - ) + if job_name in RETIRED_JOBS: + cur = conn.execute("UPDATE scheduler_job_config SET enabled=0, updated_at=%s WHERE job_name=%s", (now, job_name)) + else: + cur = conn.execute( + "UPDATE scheduler_job_config SET every_seconds=%s, updated_at=%s WHERE job_name=%s", + (seconds, now, job_name), + ) conn.commit() conn.close() return cur.rowcount > 0 @@ -335,7 +383,7 @@ def list_manual_triggers(limit=30): def get_scheduler_overview(): init_scheduler_tables() conn = get_scheduler_conn() - configs = conn.execute("SELECT * FROM scheduler_job_config ORDER BY sort_order ASC, job_name ASC").fetchall() + configs = conn.execute("SELECT * FROM scheduler_job_config WHERE job_name <> ALL(%s) ORDER BY sort_order ASC, job_name ASC", (list(RETIRED_JOBS.keys()),)).fetchall() runtime_rows = conn.execute("SELECT * FROM scheduler_runtime_status").fetchall() conn.close() try: diff --git a/static/paper_trading.html b/static/paper_trading.html index fcd244f..0a1dfe9 100644 --- a/static/paper_trading.html +++ b/static/paper_trading.html @@ -47,29 +47,7 @@