feat(jobs): 提交后回填补偿落库 backfill_todo 并到期重试 (ACM2-29 P2-3)
- V1.3.2 迁移:backfill_todo 持久补偿表(attempts/next_attempt_at/last_error) - BackfillTodoRepository 接口 + PG 实现与 stub;record 幂等 upsert - BackfillSweepJob:到期重试,成功即删,失败指数退避(30s 起步封顶 15 分钟); 触发点 = InboxPoller 每轮心跳(重启即对账)+ JobExecutor BACKFILL_SWEEP 类型 - MessageProcessor/SnapshotFlow 回填失败落待办(成功终态不降级,业务不重放); SKIPPED 重复报文同样补偿共享信箱回填,防止重复信件被反复轮询 - 新测试:扫描重试/退避/恢复对账 4 用例;快照回填失败落库断言; 跳过路径补偿落库断言 验证:MSGX_PG_PORT=5433 真实 PG 全量 102 用例 0 失败 0 跳过 (ACM2-29)
This commit is contained in:
@@ -2,6 +2,7 @@ package com.gzzn.omms.msgexchange.ingress
|
||||
|
||||
import com.gzzn.omms.msgexchange.config.PipelineProps
|
||||
import com.gzzn.omms.msgexchange.infra.persistence.CminmsgInboxRepository
|
||||
import com.gzzn.omms.msgexchange.jobs.BackfillSweepJob
|
||||
import jakarta.inject.Singleton
|
||||
|
||||
/**
|
||||
@@ -12,6 +13,7 @@ import jakarta.inject.Singleton
|
||||
class InboxPoller(
|
||||
private val inbox: CminmsgInboxRepository,
|
||||
private val enqueue: InboxEnqueue,
|
||||
private val backfillSweep: BackfillSweepJob,
|
||||
private val props: PipelineProps,
|
||||
) {
|
||||
private val log = org.slf4j.LoggerFactory.getLogger(InboxPoller::class.java)
|
||||
@@ -30,9 +32,22 @@ class InboxPoller(
|
||||
log.info("polled cminmsgsId={}", id)
|
||||
}
|
||||
}
|
||||
sweepBackfillTodos()
|
||||
return enqueued
|
||||
}
|
||||
|
||||
/** v2 §5:每轮心跳顺带对账回填补偿待办(重启即恢复;空表只花一次索引 SELECT)。 */
|
||||
private fun sweepBackfillTodos() {
|
||||
try {
|
||||
val outcome = backfillSweep.sweep()
|
||||
if (outcome.inspected > 0) {
|
||||
log.info("backfill sweep inspected={} succeeded={} failed={}", outcome.inspected, outcome.succeeded, outcome.failed)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.error("backfill sweep tick failed", e)
|
||||
}
|
||||
}
|
||||
|
||||
fun loop() {
|
||||
running = true
|
||||
log.info("inbox poller loop started")
|
||||
|
||||
Reference in New Issue
Block a user