feat(flight): UNMAPPED_FIELD、SRVT/VIPF 明细与白名单内未映射留档(ACM2-89/99/100)
V5 迁移;集合段出现才写;白名单 7 类内未落态写入 UNMAPPED_FIELD,不扩白名单。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -45,6 +45,13 @@ class FlopProcessor(
|
||||
val change = MergeChange(flid = payload.flid, scalars = payload.scalars, collections = payload.collections)
|
||||
val next = FlightStateEngine.mergedState(current, change)
|
||||
flightState.persistFullState(next, msgId = head.msgId, now = clock.instant())
|
||||
flightState.persistAuxiliaryFlightFields(
|
||||
head.msgId,
|
||||
payload.flid,
|
||||
payload.collections,
|
||||
payload.unmapped,
|
||||
clock.instant(),
|
||||
)
|
||||
msgEvents.insertAll(eventsFor(next, head.msgId, mapper, clock.instant()))
|
||||
DomainOutcome(ApplyResult.Succeeded, listOf(projectionOf(next, mapper)))
|
||||
}
|
||||
@@ -117,6 +124,7 @@ class AdftProcessor(
|
||||
if (current != null) {
|
||||
val next = FlightStateEngine.mergedState(current, setOnly(record))
|
||||
flightState.persistFullState(next, msgId = head.msgId, now = clock.instant())
|
||||
flightState.persistSrvtVipfIfPresent(record.flid, record.collections, clock.instant())
|
||||
msgEvents.insertAll(eventsFor(next, head.msgId, mapper, clock.instant()))
|
||||
revived = next
|
||||
}
|
||||
@@ -148,6 +156,7 @@ class AdftProcessor(
|
||||
FlightStateEngine.mergedState(current, setOnly(record))
|
||||
}
|
||||
val outcome = flightState.persistFullState(next, msgId = head.msgId, now = clock.instant())
|
||||
flightState.persistSrvtVipfIfPresent(record.flid, record.collections, clock.instant())
|
||||
if (outcome == PersistOutcome.DAY_GUARD_VIOLATION) {
|
||||
// 运营日冲突是**协议级**问题:与 SCHD 同分类 —— 整笔回滚、不重试、交人工。
|
||||
// 若按 INFRA 抛出去,会被当成暂时性故障白白重试到耗尽,并给出误导的错误类别。
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.gzzn.omms.msgexchange.processing
|
||||
|
||||
import com.gzzn.omms.msgexchange.domain.flight.UnmappedFieldEntry
|
||||
import com.gzzn.omms.msgexchange.infra.persistence.FlightStateRepository
|
||||
import java.time.Instant
|
||||
|
||||
/** `SRVT`/`VIPF` 与未映射字段的落库辅助(与航班主事务同批调用)。 */
|
||||
internal fun FlightStateRepository.persistAuxiliaryFlightFields(
|
||||
msgId: Long,
|
||||
flid: String,
|
||||
collections: Map<String, List<Map<String, String>>>,
|
||||
unmapped: List<UnmappedFieldEntry>,
|
||||
now: Instant,
|
||||
) {
|
||||
persistSrvtVipfIfPresent(flid, collections, now)
|
||||
replaceUnmappedForMessage(msgId, flid, unmapped, now)
|
||||
}
|
||||
@@ -167,12 +167,10 @@ class MessageProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
// [G-SRVT-VIPF]:SRVT/VIPF 段只保留在解码载荷里,尚未落明细表(清空语义待 Q2)。
|
||||
// 计数 + 告警替代此前的静默丢弃;出现即证明真实报文携带该段,可作为定案依据。
|
||||
// [G-SRVT-VIPF]:段出现计数,供真实流量观测;明细落库见 `G-SRVT-VIPF`(缺席是否清除待 Q2)。
|
||||
val unpersisted = unpersistedCollectionHits(decoded.body)
|
||||
if (unpersisted.isNotEmpty()) {
|
||||
counters.unpersistedCollectionSeenAdd(unpersisted)
|
||||
log.warn("unpersisted collection(s) {} present msgId={} [G-SRVT-VIPF]", unpersisted, head.msgId)
|
||||
}
|
||||
|
||||
// I3:identity 仅首次绑定(head.identityKey == null);FAILED 重试不重绑
|
||||
|
||||
@@ -141,6 +141,7 @@ class ScheduleProcessor(
|
||||
throw ProtocolViolation("operation-day guard violated flid=$flid")
|
||||
else -> batchWritten++
|
||||
}
|
||||
flightState.persistSrvtVipfIfPresent(flid, record.collections, clock.instant())
|
||||
events += eventsFor(next, head.msgId, mapper, clock.instant())
|
||||
projections += projectionOf(next, mapper)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user