Skip to content

refactor: 上下文传播(工程改进第三项)——EntryClock 条目时刻由 ThreadLocal 换 ScopedValue(纯重构、行为零变化) - #19

Merged
LamSpace merged 1 commit into
masterfrom
refactor/entry-clock-scoped-value
Oct 9, 2026
Merged

LamSpace merged 1 commit into
masterfrom
refactor/entry-clock-scoped-value

Conversation

@LamSpace

@LamSpace LamSpace commented Oct 9, 2026

Copy link
Copy Markdown
Owner

概述

工程改进第三项「上下文传播」落地:服务端 EntryClock 的条目时刻时间源由 ThreadLocal 换为 ScopedValue(JDK 25 / JEP 506 已转正)。纯内部机制替换、行为零变化。

为什么

  • 全仓库唯一真 ThreadLocal(EntryClock.APPLY_NOW,apply 期向应用调用路径注入条目携带时刻以保 Raft 回放确定性)以 set / try-finally 清值 配对,漏清即静默把陈旧条目时刻泄漏给该线程后续读取;ScopedValue 以有界作用域结构性消除该隐患面。
  • 定位修正:本项原措辞「客户端内部会话/追踪上下文传递评估,替代线程本地袋」经评估证伪——客户端会话身份全程显式传递(SessionContext 经 Route 捕获 + Thread.currentThread().threadId() 显式读),无 ambient 需求、不存在「线程本地袋」;落点据实收敛为服务端唯一真 ThreadLocal 的机制替换。

关键事实(决定本项为纯重构)

JEP 506 final 版 ScopedValue 绑定仅经 StructuredTaskScope.fork 继承——src.zip 中 java.base/java/lang/ScopedValue.java Inheritance 节原文,加探针实测(Thread.start / ofPlatform / ofVirtual / newVirtualThreadPerTaskExecutor 一律不继承)。故传播边界在 ThreadLocal 与 ScopedValue 下逐格相同,不引入语义变宽;按 OpenSpec「纯重构」规则设 .openspec.yaml skip_specs: true(无规格 delta)。

改动

  • EntryClock:ThreadLocal<Long> → ScopedValue<Long>;新增包内 ApplyOp + withApplyNow(long, ApplyOp)(宽 Exception 收窄:IPBE/RuntimeException 原样重抛、其余包 IllegalStateException);删除 setApplyNow/clearApplyNow。
  • LockStateMachineCore.apply:switch 抽为 applyBody(entry, t),入口收敛为作用域调用;catch 面逐字不变,finally clearApplyNow() 与 setApplyNow(0) 冗余死写消失。
  • 契约面:Clock / CoreEngine / SystemClock 零改动;无对外 API、无 wire、无协议门、无快照格式、无规格变化。

测试与验证

  • StateMachineDeterminismTest 新增「条目时刻作用域传播边界矩阵」五格(域内同线程可见 / 域外回落 / 既有非派生线程回落 / 域内新建子线程不继承 / 并发作用域互不串扰)——常驻回归绊线。行为零变化故无可红先锚点;初版「子线程继承」断言为错误前提,已按实测反转为「不继承」。
  • mvn -s settings.xml clean verify 全 7/7 模块 BUILD SUCCESS(0 失败 0 错误);javadoc:javadoc 无缺失;check-source-citations.sh 零命中;openspec validate --archived 本 change ✓。
  • -Pdrill 判不需要(无进程/时序/线程形态变化,判例对齐影子修复),依据记 evidence/drill-decision.md。

备注(如实)

首轮 clean verify 在 client 侧 surefire fork 启动处出现瞬时错误(无 Tests run 摘要);client 模块有 openlatch-server 的 test-scope 依赖,故未假定无关——经单模块复跑(含全部 IT)+ 整轮复跑双证为环境性 flake,非代码缺陷。

…纯重构、行为零变化)

- 改动:服务端 EntryClock.APPLY_NOW 由 ThreadLocal<Long> 改 ScopedValue<Long>(nowMs() 判定 get()!=null → isBound()),新增包内 ApplyOp 函数接口与 withApplyNow(long, ApplyOp)(ScopedValue.where(...).call(...) 的宽 Exception 收窄:InvalidProtocolBufferException/RuntimeException 原样重抛、其余包 IllegalStateException),删除 setApplyNow/clearApplyNow;LockStateMachineCore.apply 的 switch 抽为私有 applyBody(entry, t),入口收敛为 try { return EntryClock.withApplyNow(t, () -> applyBody(entry, t)); } catch (InvalidProtocolBufferException | RuntimeException e) { return error(...); }——catch 面逐字不变,finally clearApplyNow() 与 setApplyNow(0) 冗余死写随转换消失。全仓库唯一真 ThreadLocal 用法就此消灭,"忘清即泄漏陈旧条目时刻"的结构性隐患面随之关闭。
- 定位修正:工程改进"上下文传播"项原措辞"客户端内部会话/追踪上下文传递评估,替代线程本地袋"经评估证伪——客户端会话身份全程显式传递(SessionContext 经 Route 捕获 + Thread.currentThread().threadId() 显式读),无 ambient 需求、不存在"线程本地袋";落点据实收敛为服务端唯一真 ThreadLocal 的机制替换。
- 关键事实(实测双证,决定本项为纯重构):JEP 506 final 版 ScopedValue 绑定仅经 StructuredTaskScope.fork 继承(src.zip 中 java.base/java/lang/ScopedValue.java Inheritance 节原文 + 探针实测:Thread.start/ofPlatform/ofVirtual 与 newVirtualThreadPerTaskExecutor 一律不继承);故传播边界在 ThreadLocal 与 ScopedValue 下逐格相同,不引入语义变宽。据此按 OpenSpec"纯重构"规则设 .openspec.yaml skip_specs: true(无规格 delta,zero-delta 经 validate 接受)。
- 测试:StateMachineDeterminismTest 新增"条目时刻作用域传播边界矩阵"五格——域内同线程可见 / 域外同线程回落系统时钟 / 既有非派生线程回落 / 域内新建子线程不继承 / 并发作用域以不同携带时刻互不串扰且摘要与串行一致;作为常驻回归绊线(两种机制下皆绿)。行为零变化故无可红先锚点,初版"子线程继承"断言为错误前提,已按实测反转为"不继承";陈旧注释("thread-local")与 inApplyScope 辅助同步为有界作用域。
- 验证:mvn -s settings.xml clean verify 全 7 模块 BUILD SUCCESS(0 失败 0 错误;首轮 client 侧 surefire fork 启动瞬时错误经单模块复跑与整轮复跑双证为环境性 flake,非代码缺陷);javadoc:javadoc(server)无缺失;check-source-citations.sh 零命中;openspec validate --archived 本 change ✓;-Pdrill 判不需要(无进程/时序/线程形态变化,判例对齐影子修复),依据记 evidence/drill-decision.md。
- 文档·治理:EntryClock(类级线程模型/成立前提/契约边界,show=private)与 LockStateMachine 类级注释同步;ROADMAP 决策记录补 2026-10-09 评估裁决行 + 工程改进第 52 行描述与状态校正为已落地(附归档链接);change 归档至 openspec/changes/archive/2026-10-09-refactor-entry-clock-scoped-value/。
- 契约面:Clock 接口/CoreEngine/SystemClock 零改动;对外无 API、无 wire、无协议门、无快照格式、无规格变化。
@LamSpace
LamSpace merged commit acf4419 into master Oct 9, 2026
2 checks passed
@LamSpace
LamSpace deleted the refactor/entry-clock-scoped-value branch October 9, 2026 14:22
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.

1 participant