Files
lingniu-vehicle-ingest/CHANGELOG.md
2026-07-01 18:22:51 +08:00

6.7 KiB
Raw Permalink Blame History

Changelog

本文件记录本仓库的显著变更。日期使用 YYYY-MM-DD 格式。

格式参考 Keep a Changelog,版本遵循 SemVer

说明v0.1.0 为本仓库 git 初始化时的基线快照。下面列出的"主题改动"实际上都被压在 chore: initial import of lingniu-vehicle-ingest 这一个 commit 里——这是 git 初始化前已经完成的工作,无法事后拆分。从下一次提交开始走"小步分主题提交"流程。


[Unreleased]

Added —— 原始报文冷存Raw Archive接入 EventSink 扇出

  • 新增 VehicleEvent.RawArchive sealed 变体(ingest-api),携带一帧入站的原始字节 + command / infoType 供按协议命令分片归档。
  • Dispatcher.dispatch 在 interceptor 之前RawFrame.rawBytes() 产出一条 RawArchive 事件,保证 dedup / rate-limit 不过滤 raw archive满足"每帧必留痕"目标。
  • 新增 ArchiveEventSink implements EventSinksink-archive
    • acceptsVehicleEvent.RawArchive
    • 写入 key yyyy/MM/dd/<source>/<vin>/<eventId>.binUTC 日期分片)
    • 同 eventId 重复写按 put 语义覆盖
    • 失败 completeExceptionallyEventBus 打 WARN
    • AutoConfig 在 ArchiveStore bean 存在时自动装配
  • KafkaEventSink.accepts(RawArchive) 返回 false:本期 Kafka 不投递原始字节, 只落 ArchiveStore。未来需要 Kafka 回填 URI 时再开(TopicRouter / EnvelopeMapper 已补好 switch 分支)。
  • 覆盖测试 ArchiveEventSinkTest —— accepts 过滤 / 稳定 key 写入 / 幂等覆盖 3 case。

Changed —— GB/T 32960 Body Parser 单块异常隔离

  • Gb32960BodyParser 主循环对单信息块的 parser 异常不再放弃整帧:
    • 固定长度块(fixedLength ≥ 0):回滚 reader → 按 fixedLen 截取字节兜成 InfoBlock.Rawcontinue 继续解析后续块;
    • 变长块(fixedLength == -1)或剩余字节不足:剩余字节全部兜成 Raw 后终止循环;
    • parser 契约违反(声明 fixedLen=X 但实际读了 Y)仍抛 DecodeException 以暴露 parser bug不走 lenient 兜底,避免静默误解析长期误判;
    • 只捕获 DecodeException / BufferUnderflowException / IndexOutOfBoundsException RuntimeException 继续向上抛,保留 bug 可见性。
  • 新增配置 lingniu.ingest.gb32960.parse.lenient-block-failure(默认 true 需要回退严格模式时设为 false
  • InfoBlock.Raw record 结构未变,下游 Gb32960EventMapperfindBlock(Class) 类型匹配,新增 Raw 不影响业务事件映射。
  • 新增测试 Gb32960BodyParserIsolationTest —— 3 种隔离场景 + 严格模式回退,共 4 case。

0.1.0 — 2026-04-15

初始基线。多模块 Spring Boot 车辆遥测接入服务。

Added

  • GB/T 32960.3 接入protocol-gb32960Netty server、帧分帧器、消息解码器、 V2016/V2025 双版本信息体 parser、平台登入鉴权、VIN 白名单、读空闲告警。
  • JT/T 808 / JT/T 1078 / JSATL12 接入protocol-jt808 / protocol-jt1078 / protocol-jsatl12)。
  • MQTT 入站inbound-mqtt)。
  • Disruptor 事件总线ingest-core):高吞吐解耦解码与下游 sink。
  • Sink:本地归档(sink-archive、Kafkasink-kafka,含 protobuf envelope
  • 会话状态session-core)。
  • 可观测性Micrometer/Actuator 装配(observability)。
  • 终端控制命令网关command-gateway)。

Removed

  • 旧文件型事件索引模块和 DuckDB 依赖;历史查询统一收敛到 TDengine 与 archive://... 原始报文引用。

Fixed —— GB/T 32960 应答帧时间字段

  • Gb32960MessageDecoderVEHICLE_LOGIN / VEHICLE_LOGOUT / PLATFORM_LOGIN / PLATFORM_LOGOUT 命令预解析 body 首 6B 采集时间,写入 header.eventTime。修复前 handler 回 ACK 时落到 Instant.now(),导致应答时间与原 报文时间不一致,违反 §6.3.2 应答规则。

Added —— Netty 读空闲告警

  • 配置项 lingniu.ingest.gb32960.idle-read-seconds(默认 60s0 禁用)。
  • pipeline 注入 IdleStateHandler(idleReadSeconds, 0, 0),仅打 WARN 日志不断链, 用于排查"对端登入成功后长时间不推数据"场景。

Changed —— GB32960 信息体 parser 包结构重构

  • codec/parser/ 下的 16 个共用类按版本严格拆分到 parser/v2016/10 类) 和 parser/v2025/11 类)两个独立子包。
  • 取消 Vehicle/DriveMotor/Engine/Positionv2016()/v2025() 工厂方法,每个 版本独立类,零代码共用。
  • Alarm 解析中跨版本静态调用 readFaultList 也已改为各版本类内部私有方法。
  • Gb32960AutoConfiguration 同步更新所有 import 与 @Bean 工厂。

Removed —— 违反 2016 标准的 typeCode 注册

  • 经核对 GB/T 32960.3-2016 附录 B 表 B.30x30~0x7F 整段为预留区, 2016 标准里没有 0x30 / 0x31 / 0x32 任何字段定义
  • 删除 FuelCellStackV2016BlockParser(曾把 V2025 字段布局硬套到 V2016 帧的 0x30 段, 解出来的电压/电流远超规范上限,是非物理值)。
  • Gb32960AutoConfiguration 移除 gb32960V2016FuelCellStack bean。
  • Gb32960DecoderGoldenTest 中 749B 真实生产帧的断言由 "isEmpty()(不应有 Raw 兜底)"翻转为 "isPresent()peer 越界使用 0x30+ 预留 typeCode应有 Raw 兜底)"。这才是符合 2016 国标的正确预期。

Diagnostics —— BodyParser hex dump 增强

  • Gb32960BodyParser 在遇到未知 typeCode 触发 unknown 路径时,额外打一条 WARN 内容为整段 info-block 区域的 16 字节/行 hex dump并在 typeStartPos 字节后插入 < 标记,便于人工反查上一个块的字段对齐。

Notes —— 待办

  • peer 在 V2016 帧(2323 起始)里下发 0x30/0x31/0x32 是越界使用 2016 预留区段。 建议推动对端:
    1. 切换到 V2025 帧头(2424
    2. 或迁移到 0x80~0xFE 用户自定义区段;
    3. 或提供私有协议文档,再决定是否实现 vendor-specific parser。
  • Gb32960BodyParser 当前对 unknown 块的策略是"吞掉剩余所有字节为单个 Raw 后终止 循环",未做单块异常隔离。后续可改为对每个 parser.parse 调用加 try/catch + position 回滚,实现单块失败不拖垮整帧。
  • platformAuthorizer.authenticate 是 EventLoop 同步调用,存在 worker 阻塞风险, 建议挪到独立业务线程池(与 0x30 议题无关,但属于同模块潜在风险)。