refactor: make latest state optional

This commit is contained in:
lingniu
2026-07-01 07:37:50 +08:00
parent 0987bb4718
commit ba4bb51a07
7 changed files with 39 additions and 5 deletions

View File

@@ -81,3 +81,12 @@
2. JSATL12 仅保留在 `optional-attachments` profile需要附件上传能力时显式构建。
3. 默认优化和验证优先覆盖活跃接入链路,附件上传能力保持源码可用但不增加默认构建面。
- **Consequences**: 默认构建更轻,生产部署边界更清晰;附件上传相关测试需要通过 `-Poptional-attachments` 显式运行。
## ADR-013 最新状态服务Optional only
- **Status**: Accepted
- **Context**: Redis 最新状态查询是独立消费能力,但当前默认 Portainer 部署和 Woodpecker 镜像发布只包含三条接入链路、history 和 analytics`vehicle-state-service` 没有独立 app也不应增加默认构建面。
- **Decision**:
1. `vehicle-state-service` 不进入默认 Maven reactor。
2. vehicle-state-service 仅保留在 `optional-latest-state` profile需要 Redis 最新状态查询能力时显式构建。
3. 默认优化和验证优先覆盖活跃接入、TDengine 历史和 MySQL 指标链路。
- **Consequences**: 默认构建和部署边界继续收窄;最新状态能力保持源码可用,但其测试需要通过 `-Poptional-latest-state` 显式运行。

View File

@@ -53,7 +53,7 @@ lingniu-vehicle-ingest/
│ │ └── event-file-store/ 可选兼容索引(旧 Parquet/DuckDB 路径)
│ ├── services/
│ │ ├── event-history-service/ Kafka 全字段事件消费 + 历史查询/导出
│ │ ├── vehicle-state-service/ Kafka 全字段事件消费 + Redis 热状态查询
│ │ ├── vehicle-state-service/ Kafka 全字段事件消费 + Redis 热状态查询optional-latest-state profile
│ │ └── vehicle-stat-service/ Kafka 全字段事件消费 + 可配置日统计
│ └── apps/
│ ├── command-gateway/ HTTP → 设备下行命令808 位置/参数/属性/控制/区域删除/报警确认 + 1078 音视频控制)
@@ -80,6 +80,8 @@ mvn -pl :jt808-ingest-app -am spring-boot:run
JSATL12 附件上传不在默认 Maven reactor 中;需要时使用 `-Poptional-attachments` 构建。
Redis 最新状态查询不在默认 Maven reactor 中;需要时使用 `-Poptional-latest-state` 构建 `vehicle-state-service`
## 迁移说明
本项目是 `lingniu-vehicle-data-reception` 的 v2 重构,采用 strangler fig 渐进式迁移,旧项目保留只读参考。迁移路径与决策参见 `../REFRACTOR_PLAN.md`

View File

@@ -325,7 +325,7 @@ flowchart TB
subgraph services["消费服务 modules/services"]
history["event-history-service<br/>Kafka event/raw 到 TDengine 历史查询"]
state["vehicle-state-service<br/>Kafka 全字段事件到 Redis 热状态"]
state["vehicle-state-service<br/>可选 Redis 热状态<br/>optional-latest-state"]
stat["vehicle-stat-service<br/>Kafka 全字段事件到指标表"]
end
@@ -614,7 +614,7 @@ flowchart LR
</tr>
<tr>
<td>modules/services/vehicle-state-service</td>
<td>消费 Kafka 全字段事件,更新车辆最新状态、位置、安全和最后事件到 Redis生产消费可使用 <code>tryIngest</code> 和自动装配的 <code>EnvelopeConsumerProcessor</code> 隔离坏 protobuf 和缺快照 Envelope并把失败记录交给死信出口。</td>
<td>消费 Kafka 全字段事件,更新车辆最新状态、位置、安全和最后事件到 Redis仅通过 <code>optional-latest-state</code> profile 显式构建,不属于默认生产 reactor生产消费可使用 <code>tryIngest</code> 和自动装配的 <code>EnvelopeConsumerProcessor</code> 隔离坏 protobuf 和缺快照 Envelope并把失败记录交给死信出口。</td>
<td>Kafka Protobuf Envelope。</td>
<td><code>vehicle:state:{vin}</code><code>vehicle:location:{vin}</code><code>vehicle:safety:{vin}</code></td>
<td><span class="tag green">毫秒级热查询</span><span class="tag red">氢泄露安全</span></td>

View File

@@ -136,7 +136,7 @@ java --sun-misc-unsafe-memory-access=allow \
-jar modules/apps/vehicle-analytics-app/target/vehicle-analytics-app.jar
```
`vehicle-analytics-app` is intentionally a metric runtime only. Latest-state APIs belong to `vehicle-state-service` and should be deployed as a separate consumer if that surface is needed.
`vehicle-analytics-app` is intentionally a metric runtime only. Latest-state APIs belong to `vehicle-state-service`, which stays outside the default reactor and should be built with `-Poptional-latest-state` and deployed as a separate consumer if that surface is needed.
## Health Verification

View File

@@ -140,6 +140,9 @@ require a separate Redis mileage state.
Module: `vehicle-state-service`
This module is outside the default production reactor. Build it with
`-Poptional-latest-state` when Redis latest-state APIs are explicitly needed.
Responsibilities:
- Consume normalized Kafka envelopes.
@@ -183,6 +186,8 @@ flowchart LR
- Xinda Push is absent from default deployment and history consumer bindings.
- JSATL12 is absent from the default Maven reactor and available through
`optional-attachments`.
- vehicle-state-service is absent from the default Maven reactor and available
through `optional-latest-state`.
- History APIs read from TDengine by default; Parquet/DuckDB is optional
compatibility only.
- Raw frame queries can return complete parsed JSON through `payloadJson.parsed`.

View File

@@ -41,6 +41,17 @@ class MavenModuleProfileTest {
.containsExactly("modules/protocols/protocol-jsatl12");
}
@Test
void latestStateServiceIsOptionalAndOutsideDefaultProductionReactor() throws Exception {
Document pom = rootPom();
assertThat(defaultModules(pom))
.doesNotContain("modules/services/vehicle-state-service");
assertThat(profileModules(pom, "optional-latest-state"))
.containsExactly("modules/services/vehicle-state-service");
}
@Test
void xindaIsLegacyOnlyAndOutsideDefaultProductionReactor() throws Exception {
Document pom = rootPom();
@@ -76,6 +87,7 @@ class MavenModuleProfileTest {
.contains("Eclipse Paho " + projectProperty(pom, "paho-mqtt.version"))
.contains("protocol-jsatl12/ 苏标主动安全报警附件optional-attachments profile")
.contains("event-file-store/ 可选兼容索引(旧 Parquet/DuckDB 路径)")
.contains("vehicle-state-service/ Kafka 全字段事件消费 + Redis 热状态查询optional-latest-state profile")
.contains("vehicle-history-app/ TDengine 历史查询 + RAW JSON")
.contains("vehicle-analytics-app/ JT808 每日里程指标消费")
.doesNotContain("Spring Boot 3.4")
@@ -108,6 +120,7 @@ class MavenModuleProfileTest {
.contains("GB32960、JT808、Yutong MQTT、vehicle-history-app、vehicle-analytics-app")
.contains("Xinda Push 仅保留在 `legacy-xinda` profile")
.contains("JSATL12 仅保留在 `optional-attachments` profile")
.contains("vehicle-state-service 仅保留在 `optional-latest-state` profile")
.doesNotContain("## ADR-004 信达 Push保留模块但彻底重写\n- **Status**: Accepted")
.doesNotContain("Spring Boot 3.4.x");
}

View File

@@ -30,7 +30,6 @@
<module>modules/sinks/event-file-store</module>
<module>modules/sinks/tdengine-history-store</module>
<module>modules/services/event-history-service</module>
<module>modules/services/vehicle-state-service</module>
<module>modules/services/vehicle-stat-service</module>
<module>modules/protocols/protocol-gb32960</module>
<module>modules/protocols/protocol-jt808</module>
@@ -56,6 +55,12 @@
<module>modules/protocols/protocol-jsatl12</module>
</modules>
</profile>
<profile>
<id>optional-latest-state</id>
<modules>
<module>modules/services/vehicle-state-service</module>
</modules>
</profile>
<profile>
<id>legacy-xinda</id>
<modules>