refactor(config): drop system-time defaults from domain and entry points
删除会被误用的系统时间默认值:MsgEvent.createdAt、ProcState.updatedAt、InboxPoller.pollOnce(now)、HistorySweepJob.run(now)、Identity.of(day)。Identity 的日期边界改由 MessageProcessor 按 PARAM:msgx.operation-day.zone 算出后传入(边界关闭时身份值不变);StubProcState/StubInbox 改注入 Clock(测试可传假时钟),全部调用点显式传时间。 验证:./gradlew test 145 tests / 0 fail / 0 skipped。
This commit is contained in:
@@ -92,7 +92,7 @@ class PipelineSmokeTest {
|
||||
assertNotNull(receipt.body()) // 受理 ID
|
||||
val id = receipt.body()!!.toLong()
|
||||
// 兼容入口只保证"已落信 + 已入队",**不推进水位**;必须先被收报发现(W 追平)才可领取。
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce()
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce(Instant.now())
|
||||
|
||||
pump.tick() // 解码成功但无 DELY Handler → FAILED(UNSUPPORTED)
|
||||
|
||||
@@ -109,7 +109,7 @@ class PipelineSmokeTest {
|
||||
fun `replay reopens failed UNSUPPORTED row to PENDING`() {
|
||||
val receipt = controller.send(UNSUPPORTED_XML)
|
||||
val id = receipt.body()!!.toLong()
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce()
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce(Instant.now())
|
||||
pump.tick()
|
||||
val stub = ctx.getBean(StubProcState::class.java)
|
||||
assertEquals(ProcStatus.FAILED, stub.snapshotOf(id)!!.state)
|
||||
@@ -135,7 +135,7 @@ class PipelineSmokeTest {
|
||||
val inbox = ctx.getBean(com.gzzn.omms.msgexchange.infra.stub.StubInbox::class.java)
|
||||
val proc = ctx.getBean(StubProcState::class.java)
|
||||
val dead = inbox.simulateExternalWrite("<MSG/>")
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce()
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce(Instant.now())
|
||||
|
||||
pump.tick() // 解码 MALFORMED → DEAD + 回填意图(同一条 UPDATE)
|
||||
|
||||
@@ -152,7 +152,7 @@ class PipelineSmokeTest {
|
||||
assertTrue(inbox.isMarked(dead))
|
||||
|
||||
val fresh = inbox.simulateExternalWrite("<MSG/>")
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce()
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce(Instant.now())
|
||||
assertNotNull(proc.find(fresh)) // 死信不阻断后续发现
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ class PipelineSmokeTest {
|
||||
val flights = ctx.getBean(com.gzzn.omms.msgexchange.infra.stub.StubFlightState::class.java)
|
||||
val events = ctx.getBean(StubMsgEvents::class.java)
|
||||
val id = inbox.simulateExternalWrite("<MSG/>") // 非法报文(无 META)→ MALFORMED
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce()
|
||||
ctx.getBean(com.gzzn.omms.msgexchange.ingress.InboxPoller::class.java).pollOnce(Instant.now())
|
||||
|
||||
pump.tick()
|
||||
|
||||
@@ -260,8 +260,8 @@ class PipelineSmokeTest {
|
||||
val events = ctx.getBean(StubMsgEvents::class.java)
|
||||
val port = ctx.getBean(StubDeliveryPort::class.java)
|
||||
events.insertAll(listOf(
|
||||
MsgEvent(target = Targets.KAFKA_SCHD, partitionKey = "F1", stateVersion = 1, payloadJson = """{"FLID":"F1","v":"old"}"""),
|
||||
MsgEvent(target = Targets.KAFKA_SCHD, partitionKey = "F1", stateVersion = 2, payloadJson = """{"FLID":"F1","v":"new"}"""),
|
||||
MsgEvent(target = Targets.KAFKA_SCHD, partitionKey = "F1", stateVersion = 1, payloadJson = """{"FLID":"F1","v":"old"}""", createdAt = Instant.now()),
|
||||
MsgEvent(target = Targets.KAFKA_SCHD, partitionKey = "F1", stateVersion = 2, payloadJson = """{"FLID":"F1","v":"new"}""", createdAt = Instant.now()),
|
||||
))
|
||||
|
||||
dispatcher.flushSchd()
|
||||
|
||||
@@ -32,7 +32,7 @@ class DispatcherTickTest {
|
||||
Dispatcher(repo, port, p, FailureScheduler(p, clock))
|
||||
|
||||
private fun ev(id: Long, target: String, key: String, payload: String, version: Long = 0) =
|
||||
MsgEvent(eventId = id, target = target, partitionKey = key, stateVersion = version, payloadJson = payload)
|
||||
MsgEvent(eventId = id, target = target, partitionKey = key, stateVersion = version, payloadJson = payload, createdAt = MutableClock.BASE)
|
||||
|
||||
@Test
|
||||
fun `first tick delivers msg and starts the independent schd flush`() {
|
||||
@@ -107,6 +107,7 @@ class DispatcherTickTest {
|
||||
MsgEvent(
|
||||
eventId = 1, target = Targets.KAFKA_SCHD, partitionKey = "F1",
|
||||
eventType = EventType.TOMBSTONE, stateVersion = 3, payloadJson = """{"flid":"F1","deleted":true}""",
|
||||
createdAt = MutableClock.BASE,
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -160,6 +161,7 @@ class DispatcherTickTest {
|
||||
MsgEvent(
|
||||
target = Targets.KAFKA_SCHD, partitionKey = "F1",
|
||||
eventType = EventType.TOMBSTONE, stateVersion = 3, payloadJson = """{"flid":"F1","deleted":true}""",
|
||||
createdAt = MutableClock.BASE,
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -234,7 +236,7 @@ private class ReentrantSchdPort(private val repo: StubMsgEvents) : DeliveryPort
|
||||
override fun sendKafkaSchd(topic: String, key: String, payloadJson: String) {
|
||||
repo.insertAll(
|
||||
listOf(
|
||||
MsgEvent(target = Targets.KAFKA_SCHD, partitionKey = key, stateVersion = 99, payloadJson = """{"v":"new"}"""),
|
||||
MsgEvent(target = Targets.KAFKA_SCHD, partitionKey = key, stateVersion = 99, payloadJson = """{"v":"new"}""", createdAt = MutableClock.BASE),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,13 +22,14 @@ class ReplayServiceTest {
|
||||
fun seed(id: Long, status: ProcStatus, ec: ErrorClass?) {
|
||||
rows[id] = ProcState(
|
||||
id, status, identityKey = "k$id", attempts = 3, errorClass = ec, lastError = "x",
|
||||
updatedAt = Instant.EPOCH,
|
||||
)
|
||||
}
|
||||
|
||||
override fun insertIfAbsent(msgId: Long, receivedAt: Instant?, enqueuedAt: Instant?): Boolean =
|
||||
rows.putIfAbsent(
|
||||
msgId,
|
||||
ProcState(msgId, ProcStatus.PENDING, receivedAt = receivedAt, enqueuedAt = enqueuedAt ?: receivedAt),
|
||||
ProcState(msgId, ProcStatus.PENDING, receivedAt = receivedAt, enqueuedAt = enqueuedAt ?: receivedAt, updatedAt = Instant.EPOCH),
|
||||
) == null
|
||||
override fun find(msgId: Long): ProcState? = rows[msgId]
|
||||
override fun findSuccessTerminal(msgId: Long): Boolean = rows[msgId]?.state == ProcStatus.SUCCEEDED
|
||||
|
||||
@@ -33,7 +33,7 @@ class FdelAndAdftProcessorTest {
|
||||
|
||||
private val msgId = 7L
|
||||
|
||||
private fun head() = ProcState(msgId, ProcStatus.PENDING)
|
||||
private fun head() = ProcState(msgId, ProcStatus.PENDING, updatedAt = java.time.Instant.EPOCH)
|
||||
|
||||
private fun msg() = DecodedMessage(
|
||||
meta = MetaFields("AODB", "FDEL", "", 9L, 1L),
|
||||
@@ -172,6 +172,6 @@ class FdelAndAdftProcessorTest {
|
||||
|
||||
@Suppress("unused")
|
||||
private fun unused() {
|
||||
MsgEvent(target = "x", partitionKey = "y", payloadJson = "")
|
||||
MsgEvent(target = "x", partitionKey = "y", payloadJson = "", createdAt = java.time.Instant.EPOCH)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class IdentityTest {
|
||||
|
||||
@Test
|
||||
fun `identity is pipe-joined SNDR TYPE STYP SEQN`() {
|
||||
val identity = Identity.of(msg(42), includeDayBoundary = false)
|
||||
val identity = Identity.of(msg(42), includeDayBoundary = false, day = LocalDate.of(2026, 9, 6))
|
||||
assertEquals("AODB|FLOP|DELY|42", identity)
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class ScheduleProcessorTest {
|
||||
|
||||
private val msgId = 42L
|
||||
|
||||
private fun head() = ProcState(msgId, ProcStatus.PENDING)
|
||||
private fun head() = ProcState(msgId, ProcStatus.PENDING, updatedAt = java.time.Instant.EPOCH)
|
||||
|
||||
private fun message(body: ScheduleBody) = DecodedMessage(
|
||||
meta = MetaFields("AODB", "SCHD", "DNLD", 100L, 1L),
|
||||
|
||||
Reference in New Issue
Block a user