| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- # -*- coding: utf-8 -*-
- r"""运维动作(重算/清产物)的**当前状态**读取口(单一实现)。
- 为什么需要它: 2026-09-19 用户报"重算后页面没有输出"。实况是——门户里点了「清除产物 → 执行重算」,
- 产物被清掉后重算要跑很久(本次 ④b 振动侧摄入要处理 150 GB 的 CMS 导出), 期间各页面只能显示
- "无产物"。但那句话现在只说"要么还没放数据, 要么刚清过产物", **没说"重算正在跑"** ——
- 于是同一现象被读成"系统坏了"。
- 状态真源: `scripts/_ops_run.py` 写的 `run/ops_job.json`(每 15 s 心跳更新 mtime)。
- 判定"在跑"= `status == 'running'` **且** 文件 mtime 在 `fresh_s` 秒内(只看 pid 会被复用骗过)。
- """
- from __future__ import annotations
- try:
- from ._root import install_root as _install_root
- except ImportError: # 直接当脚本跑(python <本文件>)时没有包上下文
- from _root import install_root as _install_root
- import json
- import pathlib
- import time
- ROOT = _install_root(__file__)
- JOB = ROOT / 'run' / 'ops_job.json'
- def current(fresh_s: int = 90) -> dict:
- """→ dict(running=bool, kind=, cmd=, started=, elapsed_s=, age_s=, stale=bool, note=)。读不到就 running=False。"""
- out = dict(running=False, kind=None, cmd=None, started=None, elapsed_s=None, age_s=None,
- stale=False, note=None, job_file=str(JOB))
- if not JOB.is_file():
- return out
- try:
- j = json.loads(JOB.read_text(encoding='utf-8'))
- except Exception as e:
- return {**out, 'note': f'任务文件读不出 ({type(e).__name__})'}
- age = time.time() - JOB.stat().st_mtime
- out.update(kind=j.get('kind'), cmd=j.get('cmd'), started=j.get('started'), age_s=round(age),
- status=j.get('status'), rc=j.get('rc'))
- running = (j.get('status') == 'running') and age < fresh_s
- out['running'] = bool(running)
- out['stale'] = (j.get('status') == 'running') and age >= fresh_s
- if out.get('started'):
- try:
- t0 = time.mktime(time.strptime(out['started'], '%Y-%m-%d %H:%M:%S'))
- out['elapsed_s'] = round(time.time() - t0)
- except Exception:
- pass
- if out['stale']:
- out['note'] = (f"任务文件写着 running 但已 {round(age / 60, 1)} 分钟没心跳 —— 可能是被强杀, "
- f"不是正在跑")
- return out
- def running_text() -> str:
- """给人看的一句话(页面/接口用): 在跑就写明"起点 + 已跑多久", 否则空串。"""
- s = current()
- if not s['running']:
- return ''
- mins = (s['elapsed_s'] or 0) / 60
- return (f"⚠ 检测到**重算正在进行中**({s['kind']},起于 {s['started']},已跑 {mins:.0f} 分钟)—— "
- f"产物是一步步长出来的,页面会在对应步骤跑完后自己回来(无需重启服务)。")
|