14.3 v1 验收:RS 合规、背压可观测、文档

按仓库真实状态做验收,而不是把计划全部打勾:编译通过(约 3 秒),但仓库里没有 TCK 测试类、没有 eventd-app 入口、没有 README,因此合规与可运行两项尚未达成。列出实际命令与真实失败输出,区分「章节中验证过的独立实验」和「仓库内可重复的测试」,并给出补齐验收所需的最小工作清单。

验收口径

把「验收」拆成四道门禁,每道都给出可执行的判据:

门禁判据当前状态
L1 结构模块、包名、依赖符合约定通过
L2 编译mvn clean compile 返回 0通过
L3 合规与运行仓库内 TCK 全绿,演示可启动未达成
L4 文档README、运行命令、基线记录齐全未达成

下面的结论只针对 .local/java_reactive/eventd-v1 这个仓库快照,不针对书中所有示例代码。

L1:结构

eventd-v1/
├── pom.xml
├── eventd-core/
│   ├── pom.xml
│   └── src/main/java/com/plume/eventd/core/
│       ├── SyncSinglePublisher.java
│       └── LoggingSubscriber.java
└── eventd-app/
    ├── pom.xml
    └── src/                      # 空

包名 com.plume.eventd.core、模块命名、父 POM 聚合都符合约定。eventd-app 目录存在,但没有源码。

L2:编译

export JAVA_HOME=~/.jdks/jdk-25.0.5+8/Contents/Home
cd .local/java_reactive/eventd-v1
mvn -q -DskipTests clean compile

本机实测:

mvn -q -DskipTests clean compile  3.25s user 0.26s system 116% cpu 3.004 total
exit=0

生成:

eventd-core/target/classes/com/plume/eventd/core/LoggingSubscriber.class
eventd-core/target/classes/com/plume/eventd/core/SyncSinglePublisher.class
eventd-core/target/classes/com/plume/eventd/core/SyncSinglePublisher$SingleSubscription.class

eventd-app 没有源码,所以没有它的 class。编译成功只证明 core 的两个类语法和依赖没问题。

L3:合规与运行

TCK:当前跑不起来

按书中类名执行:

mvn test -Dtest=SyncSinglePublisherTckTest

真实输出(截取):

[INFO] eventd-core — RS implementations & utilities ....... FAILURE [  4.420 s]
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.2.5:test
        on project eventd-core: No tests matching pattern "SyncSinglePublisherTckTest"
        were executed!

原因很直接:仓库里没有 src/test/java,也没有 SyncSinglePublisherTckTest 这个类。书中第 11 章确实跑过 TCK,但那些测试类是独立实验文件,没有进入本仓库。

这也解释了为什么不能把「第 11 章 TCK 全绿」直接当成「eventd v1 验收通过」:前者的被测对象是 BaseSubscriber 和 PublishProcessor,后者的被测对象应该是 SyncSinglePublisher 与后续手写类。

演示应用:当前没有入口

从模块目录执行:

cd eventd-app
mvn -q exec:java -Dexec.mainClass=com.plume.eventd.app.BackpressureDashboard

真实失败:

[ERROR] Failed to execute goal on project eventd-app: Could not resolve dependencies
[ERROR] dependency: com.plume.eventd:eventd-core:jar:1.0.0-SNAPSHOT (compile)
[ERROR]   Could not find artifact com.plume.eventd:eventd-core:jar:1.0.0-SNAPSHOT

这有两个原因叠在一起:

  1. eventd-app 在模块目录单独执行时,Maven 找不到尚未 install 的 eventd-core。
  2. 即使从根目录用 -pl eventd-app -am,也会因为 com.plume.eventd.app.BackpressureDashboard 不存在而失败。

真正的入口和面板类需要先按 13.3 的代码加进 eventd-app/src/main/java,再执行:

mvn -q -pl eventd-app -am exec:java \
  -Dexec.mainClass=com.plume.eventd.app.BackpressureDashboard

哪些运行结果是真的

内容在哪验证是否在仓库内
BaseSubscriber 白盒 TCK:27 用例,14 通过,13 跳过第 11 章独立实验否
BaseSubscriber 黑盒 TCK:26 用例,11 通过,15 跳过第 11 章独立实验否
PublishProcessor 作为 identity processor:68 用例,30 通过,14 失败,24 跳过第 11 章独立实验否
SensorSimulatorPublisher 的 request(1)/request(5)/request(0)/cancel 输出13.2否(章节代码)
BUFFER / DROP / LATEST 的丢弃统计13.3否(章节代码)
1M 元素与 10 万元素延迟测量14.2否(独立 benchmark)

这些都是真实跑出来的,但它们不等于「仓库 CI 绿了」。验收文档必须把这两件事分开。

L4:文档

ls README.md eventd-core/README.md

真实输出:

ls: README.md: No such file or directory
ls: eventd-core/README.md: No such file or directory

现有两个类有 JavaDoc,但仓库没有 README、没有运行说明、没有基线记录。第 14.2 节的测量模板可以作为 README 的一部分,目前尚未落地。

逐项清单

检查项状态证据
父 POM 聚合两个模块通过pom.xml 的 <modules>
eventd-core 编译通过mvn clean compile,exit 0
eventd-app 有入口未通过src/ 为空
SyncSinglePublisherTckTest 存在并可运行未通过surefire: No tests matching pattern
AsyncRangePublisherTckTest未通过类不存在
MapProcessorTckTest未通过类不存在
背压演示可一键启动未通过无 main 类
README 与运行命令未通过文件不存在
性能基线可复现部分14.2 有代码与实测,未进仓库
已知限制有记录部分13.1、13.2、14.2 文中有说明

补齐验收的最小工作

按依赖顺序:

  1. 决定接口口径。现有类用 java.util.concurrent.Flow,TCK 用 org.reactivestreams。两条现成路线:用 org.reactivestreams.FlowAdapters.toPublisher(...) 转成 RS 类型,或者引入 reactive-streams-tck-flow:1.0.4 直接继承 FlowPublisherVerification。不要把两套接口当成同一套。
  2. 加 TCK 测试类。reactive-streams-tck:1.0.4 是 TestNG 体系,测试类需要继承 PublisherVerification 并由 TestNG 运行。当前 POM 同时有 JUnit Jupiter,Surefire 需要能识别 TestNG;最省事的做法是单独建一个 eventd-core-tck 模块,只放 TCK 测试。
  3. 加 eventd-app 入口与面板。把 13.3 的 BackpressureDashboard 落到 eventd-app/src/main/java/com/plume/eventd/app/,补一个 main。否则 exec:java 永远失败。
  4. 写 README。至少包含:JDK 版本、mvn clean compile、TCK 命令、exec:java 命令、已知限制。
  5. 记录基线。用 14.2 的模板,注明 JDK、JVM flags、预热轮数、输入规模和源码版本。

在这些完成之前,把 L3/L4 标成「通过」是不诚实的。

已知限制

  1. SyncSinglePublisher 不是线程安全的。cancelled、completed 是普通 boolean,并发 request 可能重复发射。
  2. null 被静默当成空流。构造器不拒绝 null,request 里用 if (value != null) 跳过。更严格的做法是构造时抛 NullPointerException,需要空流时显式用空 Publisher。
  3. Flow 与 org.reactivestreams 不兼容。TCK 不能直接验证现有类,必须适配。
  4. 章节示例不是仓库文件。AsyncRangePublisher、MapProcessor、SensorSimulatorPublisher、BackpressureDashboard 都还需按章节落地。
  5. 性能数字只代表一次运行。14.2 的数字没有经过 JMH,不能当作生产容量规划依据。

小结

门禁结论
L1 结构通过
L2 编译通过(约 3 秒)
L3 合规与运行未达成:无 TCK 测试类、无 app 入口
L4 文档未达成:无 README、无基线记录

验收的价值不是把复选框全部打勾,而是准确说明「现在能证明什么、还不能证明什么」。以当前仓库状态,能证明的是「两个类可以编译」;不能证明的是「手写 Publisher 合规」和「演示可一键运行」。

阅读导航

上一篇:14.2 eventd v1 性能基线

下一篇:返回目录 或书稿书架 。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「java」更多文章

  1. 15.3 全书总结与学习路径回顾
  2. 15.2 响应式流处理的演进趋势
  3. 15.1 引擎选型指南