Skip to content

ops-backlog #139:轮次内存峰值入台账 + queue.md 双边 flock - #198

Merged
steponeerror merged 10 commits into
masterfrom
feature/ops-backlog-139
Oct 25, 2026
Merged

steponeerror merged 10 commits into
masterfrom
feature/ops-backlog-139

Conversation

@steponeerror

Copy link
Copy Markdown
Owner

ops-backlog #139:轮次内存峰值入台账 + queue.md 双边锁

Closes #139

问题

#139 四子项挂账,triage 后两闭两实施:

变更

①内存峰值(merge 1ddab39,backend/ipdb/_ops_rounds.py +203/−2):

  • read_memory_peak():cgroup v2 memory.peak → v1 max_usage_in_bytes 回退 → 皆缺 None(缺读数≠零用量,不虚构)。
  • run_round 轮始基线 + finally 全路径收口(成功/失败/取消/OSError 兑底)写台账独立行 memory_peak_bytes=N;LEDGER_HEADER 是 T4 冻结契约不加列,老行缺字段=缺省;终值==基线附注「容器累计高水位,轮内未破」(cgroup 峰值=累计高水位,附注即上界语义诚实标注)。
  • 台账写 best-effort 不撕轮次链;spawn/env 面零改动(C4 白名单未扩)。

②双边 flock(merge 35c314a,6 文件 +390/−35):

  • python append_queue 临界段(读-判重-写全段)持 fcntl.flock(LOCK_EX),旧幂等判重/闭集校验/原子写零改写只包锁。
  • node 新 ops/agent/tools/queue-lock.mjs:spawn util-linux flock(1)(与 flock(2) 同锁域;弃 O_EXCL 自造锁=异锁域不互锁+stale 强接误杀竞态),零新 npm 依赖;CLI 面信封化(崩溃也是单行 JSON)。
  • 锁路径常量两侧各恰一处 + contract 第 17 哨跨语言对拍同址;锁文件永不删(删除即竞态)。
  • 竞态证据:修后 python 2×8 恰 16 行、同键判重恰 1、混语 python×node 各 8 恰 16 行(3/3);node t4 +4 例(跨子进程恰 N/SIGKILL 内核即释/缺 flock fail-closed 零写)。

验证

  • 门(实现分支,merger 独立复算+supervisor 亲跑):① pytest -k ops_rounds 53/1(含 e2e 真跑)+红测重放(常量实现→7 红);② pytest -k "queue or ops_store" 43/1、-k ops 251/1、node 四件 pipeline 63/0+t4 58/0+contract 17/0+standard-check 48、全量 2238/10/0(报告过的 startup_warm flake 未复现)。
  • 合流门(集成分支 tip 38bb4f5):-k ops 259 passed(含两子项+e2e)、node 四件同上全绿、CHANGELOG 双语伞条目。
  • SDD:两实现者独立 worktree(.worktrees/ops139-mem、ops139-lock)→ 各 merger 静态审(①五审点/②七审点全过,零 P0/P1)→ 动态门 supervisor 亲跑 → merge --no-ff 串行。

P2 留档(不阻塞)

  • 部署后顺手服务器实证 docker exec ip-lookup-tool-ipradar-1 flock --version(静态论证=util-linux 属 Debian Essential,终阶 python:3.12-slim 不删)。
  • recovery 轮(_run_recovery_round)不记内存峰值(票面 scope 限 run_round,留后续)。
  • init_ops_tree 骨架写在锁外(调用序纪律覆盖,报告级残留非本票引入)。
  • node 行 UTC vs python 本地日期=既有冻结形状(两侧写不同 source 无跨侧同键判重)。

…e_in_bytes 回退,皆不可读返回 None 不抛(缺读数≠零用量);三态测试(tmp_path 假 cgroup 树 monkeypatch 路径常量)
…k.mjs flock(1) 临界段子进程

- python:_queue_lock() 上下文管理器覆盖读-判重-写全段,锁文件 queue.md.lock
  同目录 O_CREAT 常驻;锁序恒 threading→flock 无倒置;模块头竞态判记改口径
- node:tools/queue-lock.mjs 基建(零仓依赖自含),取舍 = spawn util-linux
  flock(1)(与 fcntl.flock 同 flock(2) 锁域互认;O_EXCL 判龄案否——与 flock
  不互锁+stale 误杀),临界段 = 本文件 --append 子进程,失败 fail-closed 信封
- 竞态测试:python 两子进程不同 source 2×8 → 恰 16 行;同键 2×6 → 恰 6 行;
  混语互操 python×node 并发 → 不丢不重(node 缺供时 skip)
- 修前实证(2×40 无锁):期望 80 实际 40~41 丢行近半;修后 5 试全 0 丢
…/兜底全路径)写终值入台账为独立行 memory_peak_bytes(表头 T4 冻结不加列,老行缺字段=缺省不虚构;未破高水位标注上界语义);假 agent 增 mem_bump 钉终值读时序
- registry.mjs queueAction:临界段(读-判重-写)整体入 appendQueueRowLocked
  flock 子进程;锁外仅留 veto_cmd 计算/rationale 工件;锁不可得 fail-closed
  信封手返(不经 finish,防二次预算计数+入登记表破坏不变式);lineN 死变量随迁删
- flock 调用形修正:-w 选项须在锁文件前(2.39/2.41 同形)
- selftest-t4 四例:跨子进程并发恰 N 行/同键恰 1 行/持锁方进程组被杀内核即释
  (flock fork 后子进程继承锁 fd,须杀整组)/锁通道缺失 fail-closed 不写文件
- selftest-contract 17th 哨:锁路径跨语言对拍(python QUEUE_LOCK_NAME 文本解析
  ↔ node queueLockPath 实跑,生产同址链 DOCS_ROOT=ops_root().parent)+registry
  接线钉死;queue-lock.mjs 入 SRCS 扫描(零 env 读取,防未来静默扩面)
- 混语互操测试 node 侧改经 flock 包装(生产路径同形,直调 --append 无锁不测互操)
flock(1) 对锁文件 O_CREAT 但父目录缺失时 cannot open(fail-closed);不预建
则 node 子进程与 python 首笔 append 惰性建目录赛跑。生产面由 init_ops_tree
先建目录,测试补同一前提。三连跑 3/3 绿。
… 全路径收口写 memory_peak_bytes 独立行(T4 冻结表头不改,老行缺字段不虚构);merger 静态五审点全过+动态三门亲跑(53/1、红测 7 红、基线 44 绿)
…EX) + node queue-lock.mjs(spawn util-linux flock(1) 同锁域);锁路径常量两侧各一+contract 第 17 哨跨语言对拍;修前实证丢半数行→锁后 lost=0,混语互操 3/3;merger 静态七审点全过+动态四门亲跑全达期望
@steponeerror
steponeerror merged commit e952c58 into master Oct 25, 2026
5 of 6 checks passed
@steponeerror
steponeerror deleted the feature/ops-backlog-139 branch October 25, 2026 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

运营批挂账:内存峰值采集 / queue 跨进程竞态 / 镜像 gh CLI / 取消按钮

1 participant