refactor(processing): remove unused processing start field
processing_started_at 没有任何判据消费(终态只看尝试上限),删除字段、仓储接口与方法、主泵写入、重放清理、SELECT/映射与 H2 fixture,并新增 V7 DROP COLUMN;V1–V6 历史迁移不动。 验证:./gradlew test 123 tests / 0 fail;V7 的 DROP 与最终 schema 断言需真实 PG,本机无 Docker 时 FlywayMigrationTest 按既有 assumeTrue 跳过。
This commit is contained in:
+15
-3
@@ -48,7 +48,7 @@ class FlywayMigrationTest {
|
||||
while (rs.next()) {
|
||||
records.add(Triple(rs.getString("version"), rs.getString("script"), rs.getBoolean("success")))
|
||||
}
|
||||
assertTrue(records.size >= 5, "flyway_schema_history must record all migrations")
|
||||
assertTrue(records.size >= 7, "flyway_schema_history must record all migrations")
|
||||
assertEquals("1", records[0].first)
|
||||
assertEquals("V1__flight_state_baseline.sql", records[0].second)
|
||||
assertEquals("2", records[1].first)
|
||||
@@ -59,6 +59,10 @@ class FlywayMigrationTest {
|
||||
assertEquals("V4__backfill_closure.sql", records[3].second)
|
||||
assertEquals("5", records[4].first)
|
||||
assertEquals("V5__cutover_seed.sql", records[4].second)
|
||||
assertEquals("6", records[5].first)
|
||||
assertEquals("V6__enqueued_at.sql", records[5].second)
|
||||
assertEquals("7", records[6].first)
|
||||
assertEquals("V7__drop_processing_started_at.sql", records[6].second)
|
||||
assertTrue(records.all { it.third })
|
||||
}
|
||||
|
||||
@@ -88,7 +92,7 @@ class FlywayMigrationTest {
|
||||
"SELECT column_name FROM information_schema.columns WHERE table_name = 'proc_state' " +
|
||||
"AND column_name IN ('received_at', 'enqueued_at', 'backfill_at', 'backfill_next_at', " +
|
||||
"'backfill_attempts', 'backfill_error', 'backfill_abandoned_at', " +
|
||||
"'backfill_abandoned_reason', 'processing_started_at')",
|
||||
"'backfill_abandoned_reason')",
|
||||
).use { rs ->
|
||||
val cols = mutableSetOf<String>()
|
||||
while (rs.next()) cols.add(rs.getString("column_name"))
|
||||
@@ -96,12 +100,20 @@ class FlywayMigrationTest {
|
||||
setOf(
|
||||
"received_at", "enqueued_at", "backfill_at", "backfill_next_at", "backfill_attempts",
|
||||
"backfill_error", "backfill_abandoned_at", "backfill_abandoned_reason",
|
||||
"processing_started_at",
|
||||
),
|
||||
cols,
|
||||
)
|
||||
}
|
||||
|
||||
// V7:PROC_STATE 不再保留处理开始时间(无判据消费)
|
||||
stmt.executeQuery(
|
||||
"SELECT count(*) FROM information_schema.columns WHERE table_name = 'proc_state' " +
|
||||
"AND column_name = 'processing_started_at'",
|
||||
).use { rs ->
|
||||
assertTrue(rs.next())
|
||||
assertEquals(0, rs.getInt(1), "V7 必须已删除 PROCESSING_STARTED_AT")
|
||||
}
|
||||
|
||||
// V6:入队时间是超期判据 R 的比较对象,必须非空(received_at 则允许为 NULL)
|
||||
stmt.executeQuery(
|
||||
"SELECT is_nullable FROM information_schema.columns " +
|
||||
|
||||
-10
@@ -142,15 +142,6 @@ class InboxLifecycleJdbcSqlTest {
|
||||
assertEquals(InboxCursorRepository.Cursor(42L, t0), cursor.load())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `processing start is written once and is not refreshed`() {
|
||||
seed(11L, t0)
|
||||
proc.markProcessingStartedIfAbsent(11L, t0.plusSeconds(10))
|
||||
proc.markProcessingStartedIfAbsent(11L, t0.plusSeconds(20))
|
||||
|
||||
assertEquals(t0.plusSeconds(10), proc.find(11L)!!.processingStartedAt)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `pipeline transaction rolls back terminal and outbox writes after a late failure`() {
|
||||
seed(11L, t0)
|
||||
@@ -232,7 +223,6 @@ class InboxLifecycleJdbcSqlTest {
|
||||
backfill_error VARCHAR(512),
|
||||
backfill_abandoned_at TIMESTAMP WITH TIME ZONE,
|
||||
backfill_abandoned_reason VARCHAR(64),
|
||||
processing_started_at TIMESTAMP WITH TIME ZONE,
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
CONSTRAINT uk_proc_identity UNIQUE (identity_key)
|
||||
)
|
||||
|
||||
@@ -22,7 +22,6 @@ class ReplayServiceTest {
|
||||
fun seed(id: Long, status: ProcStatus, ec: ErrorClass?) {
|
||||
rows[id] = ProcState(
|
||||
id, status, identityKey = "k$id", attempts = 3, errorClass = ec, lastError = "x",
|
||||
processingStartedAt = Instant.parse("2026-09-08T03:00:00Z"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -34,7 +33,6 @@ class ReplayServiceTest {
|
||||
override fun find(msgId: Long): ProcState? = rows[msgId]
|
||||
override fun findSuccessTerminal(msgId: Long): Boolean = rows[msgId]?.state == ProcStatus.SUCCEEDED
|
||||
override fun headUnfinished(): ProcState? = null
|
||||
override fun markProcessingStartedIfAbsent(msgId: Long, now: Instant) = Unit
|
||||
override fun tryBindIdentity(msgId: Long, identityKey: String): Boolean = true
|
||||
override fun ownerOfIdentity(identityKey: String): Long? = null
|
||||
override fun update(
|
||||
@@ -69,7 +67,7 @@ class ReplayServiceTest {
|
||||
val s = rows[id]!!
|
||||
if (s.errorClass != null && s.errorClass in errorClasses &&
|
||||
(s.state == ProcStatus.FAILED || s.state == ProcStatus.DEAD)) {
|
||||
rows[id] = s.copy(state = ProcStatus.PENDING, attempts = 0, nextAttemptAt = null, processingStartedAt = null)
|
||||
rows[id] = s.copy(state = ProcStatus.PENDING, attempts = 0, nextAttemptAt = null)
|
||||
n++
|
||||
}
|
||||
}
|
||||
@@ -92,7 +90,6 @@ class ReplayServiceTest {
|
||||
assertEquals(ProcStatus.PENDING, repo.rows[1]!!.state)
|
||||
assertEquals(0, repo.rows[1]!!.attempts)
|
||||
assertNull(repo.rows[1]!!.nextAttemptAt)
|
||||
assertNull(repo.rows[1]!!.processingStartedAt)
|
||||
assertEquals(ProcStatus.DEAD, repo.rows[2]!!.state) // MALFORMED 永不被重放
|
||||
assertEquals(ProcStatus.PENDING, repo.rows[3]!!.state)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user