docs(kdoc): 其余模块注释统一为直白说明

把上一提交没覆盖到的模块也改完,至此仓库内不再有"只写编号、不写说明"的注释。

涉及 33 个文件(生产 24 + 测试 9),包括航班状态模型与合并引擎、事件与留痕模型、
运营日计算、投递器、历史归档作业、编解码与身份、重试与重放、健康指示器、
生命周期装配、以及各自的测试类。

改法与前面一致:先说这段代码做什么,再说为什么这么做,术语第一次出现就地解释
(FLID、OPERATION_DAY、航班版本号、删除通知、待发事件表等)。工单编号
(U07/N02/ACM2-10 之类)已全部移除;段落编号只剩 10 处,全部带文件名位于句尾,
用作延伸阅读,例如"见 docs/flight-state.md §5"。

保留了本来就自解释的行内注释、PgTestSupport 顶部的环境变量默认值表格,
以及 InboxController 里描述待补接口的 TODO。

校验:逐文件做"去注释后比对"(块注释 + 行注释清除、空白归一),33 个文件代码
零差异;另做逐行非注释代码比对,同样零差异。clean test 为 78 passed / 1 skipped。
This commit is contained in:
windyboy
2026-09-10 11:14:11 +08:00
parent 6e7d819034
commit 1183c7522b
33 changed files with 283 additions and 210 deletions
@@ -12,29 +12,30 @@ import jakarta.inject.Singleton
import java.time.Duration
import java.time.Instant
/** 对外投递端口(Kafka 同步确认,at-least-once;阶段 B 追加 ES 投影写入)。 */
/** 对外投递的出口:同步等 Kafka 确认,语义是至少发一次(可能重复,但不会丢)。以后 ES 投影也从这里加。 */
interface DeliveryPort {
/** KAFKA_MSG 变化通知(key=FLID)。 */
/** 发一条变化通知,消息 key 是 FLID(航班实例 ID)。 */
fun sendKafka(topic: String, key: String, payloadJson: String)
/**
* KAFKA_SCHD 整态(key=FLID)。KAFKA_MSG 与 KAFKA_SCHD 映射同一 topic 语义由适配层定;
* target→topicKAFKA:msg→"msg"KAFKA:schd→"schd"。
*/
/** 发一条完整状态,消息 key 是 FLID。适配层负责把 target 映射成 topicKAFKA:msg 对应 "msg"KAFKA:schd 对应 "schd"。 */
fun sendKafkaSchd(topic: String, key: String, payloadJson: String)
/** TOMBSTONEkey=FLID、value=null——整态键缺失表示删除旧值(flight-state.md §5。 */
/** 发一条删除通知keyFLID、value 为空;下游按"整态里这个键没了"理解成删除。 */
fun sendKafkaNull(topic: String, key: String)
/** 连通性探测(健康检查用);默认 true,真实 Kafka 实装时覆写为 producer metadata 校验。 */
/** 给健康检查用的连通性探测;默认返回 true,真实 Kafka 实现要覆写成向 broker 拉一次 metadata 来判断。 */
fun ping(): Boolean = true
}
/**
* 投递调度docs/flight-state.md §5 + design.md §5.1/§5.2):逐条 KAFKA_MSG 严格 FIFO
* KAFKA_SCHD 走 flushSchd 批量——同一 FLID 未发事件按最新 STATE_VERSION 合并输出,
* TOMBSTONE 发 null 值消息。两主题间不保证顺序(§5)。
* 批量闭环:队首退避未到期不 claim;发送失败整批 attempts+1 退避,达上限整批 DEAD/DLQ
* 投递调度:把 outbox(待发事件表)里的事件发给下游。
*
* KAFKA_MSG 一条一条按登记顺序发,不插队。KAFKA_SCHD 走 flushSchd 批量发:同一个 FLID 攒了
* 多条未发事件时只发版本号最新的那条,旧的自然作废;删除通知发 value 为空的 tombstone
* 两个主题之间不保证先后顺序。
*
* 失败处理:队首的重试时间没到就不取;一批里有发送失败,整批重试次数加一并推后退避,
* 次数用尽整批转 DEAD 当死信。见 docs/flight-state.md §5。
*/
@Singleton
class Dispatcher(
@@ -50,7 +51,7 @@ class Dispatcher(
private var lastFlush: Instant? = null
/** 优雅停机:loop 收尾后退出;线程中断由 PipelineLifecycle 负责。 */
/** 请求停机:置位后 loop 走完当前一轮就退出;真正中断线程由 PipelineLifecycle 负责。 */
fun stop() {
running = false
}
@@ -91,7 +92,7 @@ class Dispatcher(
}
}
/** flushSchd:同 FLID 未发事件按最新 STATE_VERSION 合并(§5);TOMBSTONE 发 null。 */
/** 批量发 KAFKA_SCHD:每个 FLID 只发版本号最新的那条未发事件,删除通知发空 value。 */
internal fun flushSchd() {
val batch = try {
msgEvents.mergePendingSchd(props.schd.flushLimit)
@@ -116,7 +117,7 @@ class Dispatcher(
}
val sentIds = batch.mapNotNull { it.eventId }.toSet() - failures.mapNotNull { it.eventId }.toSet()
if (sentIds.isNotEmpty()) msgEvents.markAllSent(sentIds.toList())
// 被新版本合并压掉的未发事件同样关闭(§5:同 FLID 只按最新 STATE_VERSION 输出一次
// 被新版本压掉的旧事件也要标成已发,否则它们会一直留在队里:同一个 FLID 只按最新版本输出一次
val sentVersions = batch.associate { it.partitionKey to it.stateVersion }
runCatching {
while (true) {
@@ -130,7 +131,7 @@ class Dispatcher(
lastFlush = scheduler.now()
}
/** 条事件失败迁移:attempts+1;达上限 DEAD(EXHAUSTED)DLQattempts 落库审计),否则退避重试。 */
/** 条事件失败之后怎么走:重试次数加一,到上限就标成 DEAD(EXHAUSTED) 留作死信(次数落库便于追查),否则退避推到下次再发。 */
private fun retryOrDead(e: MsgEvent, lastError: String) {
val eventId = e.eventId ?: return
val attempts = e.attempts + 1