shy3130
|
b8f1ebaaf0
|
fix(mining): 旧格式锁也能定位持有者并强制释放, 不再永久卡挖掘
用户反馈: 挖掘工作台一直提示「挖掘锁被其他进程占用 — 锁文件为旧格式,
无法定位持有进程」(v0.3.17+ fail-closed 设计)。根因: 锁内容是 v0.2 时代
写入的 b"0" (无 pid), 持有者为升级前启动、仍在运行的旧版后端残留进程;
flock 是 OS 级锁, 进程存活即一直占用, 旧版本无法被识别 → 强制释放按钮
永不出现, 用户只能去任务管理器逐个猜进程。
- mining_process_lock: 新增 locate_lock_holder_pid — 锁内容不可读时用
lsof (POSIX) / psutil (跨平台兜底) 反查打开锁文件的进程; 只认本产品
形态 (python/uvicorn/desktop/tickflow), 且连续两次扫描命中才采信,
避免误杀瞬时探测或无关进程 (误杀是破坏性操作, 宁可定位失败)
- mining_lock_admin.lock_status: 旧格式锁 → OS 反查持有者, 继续走既有
fail-closed 判定 (无进行中挖掘 + 存储静默 >=600s 才允许释放);
状态新增 holder_source 字段
- 前端横幅: 展示「已通过系统扫描定位」并出现既有「强制停止并接管」按钮;
定位失败时保留手动指引
- 设计纪律不变: 仍只提供人工确认的强制释放, 不做启动自动 kill
验证: 新增 4 条用例 (旧格式持锁进程定位 / 强制释放完整接管 / 挖掘活跃时
仍拒绝 fail-closed / 锁空闲不误报); 撤销集成时 3 条红, 恢复后绿;
后端全量 3540 passed; 前端 build + tsc 通过。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-29 21:21:13 +08:00 |
|
shy3130
|
b573ca43eb
|
feat(mining): 挖掘锁撞锁降级启动 + 持有者诊断 + 一键强制释放
复现的原始问题: 旧实例挂死在 shutdown (热重载撞上挖掘运行) 或 worker
成为孤儿后, `.mining_process.lock` 被无限期占用, 后续所有后端实例
在 lifespan 抢锁时直接启动失败, 用户只能对着笼统报错手动找进程。
- 锁文件记录持有者 {pid, started_at, role, host} (flock 仍是唯一
事实, 内容只是诊断线索; 旧格式 "0" 兼容, 视为持有者未知);
新增非阻塞探测, 无需抢锁即可判断是否被持有。
- 撞锁降级启动: lifespan 抢锁失败不再上抛, 面板照常可用; 挖掘
启动入口 (手动/自动/周度调度) 返回 409 并指引到挖掘页; 桌面版
预检从「秒退失败页」改为留日志继续启动; 守护复验不受影响。
- 挖掘页锁占用横幅: 显示持有者 pid/角色/挖掘存储静默时长; 满足
陈旧判定时可一键「强制停止并接管」(SIGTERM→SIGKILL→当前后端
获取锁, 挖掘入口立即恢复)。
- 陈旧判定全部 fail-closed: 持有者信息可读、进程存活且 pid 未被
复用 (POSIX 比对进程实际启动时间)、无进行中的挖掘运行、挖掘
存储 10 分钟内无写入 — 任一不满足即拒绝并给出原因。不做启动
时自动清理, 终止进程必须人工确认。
测试: 新增 test_mining_lock_admin (含真实外部持锁进程的强停回路与
五类拒绝路径), 重写 lifespan 降级契约与桌面预检继续启动契约;
后端全量 3239 通过, 前端 308 通过, ruff 零新增; 沙盒 E2E 完整
复刻「持锁→降级→强停→接管→恢复」事故场景通过。
Signed-off-by: shy3130 <shy3130@qq.com>
|
2026-10-26 00:01:20 +08:00 |
|