feat(processing): 实现自有 PostgreSQL 运营航班权威存储与单事务闭环 (ACM2-28)

- FS1: 增加 Flyway 迁移 V1.1.0__flight_schd.sql,创建 FLIGHT_SCHD 与 SCHD_GEN
- FS2: 实现 FlightSchdRepository 接口及 JdbcFlightSchdRepository 与 StubFlightSchd,增强 JdbcOps 事务管理
- FS3: 扩展 MessageProcessor 事务 2 与按 FLID 点查视图,合并变更、事件与终态入单事务提交
- FS4: SnapshotFlow SQL 化(批处理 upsert、域内差删、SQL CAS 推进与熔断保护),JobExecutor 接入 PG 清场删除
- FS5: 彻底退役 Redis 权威与写路径,移除 FlightRedisClient、Lua 脚本、健康指示器与配置残留
- FS6: 补齐 U09/U29 不变量门禁(崩溃幂等、CAS 防并发、ADFT 存活保障、非 UTC JVM/会话时区无漂移)与 FlywayMigrationTest
- FS7: 交付影子对拍比较内核 FlightStoreDiffTool 与单元测试
- FS8: 全面回改 decision-flight-state、architecture、design、user-stories 权威文档与规范
This commit is contained in:
windyboy
2026-09-07 16:12:00 +08:00
parent dd4bbc86ca
commit 7b7b61f100
37 changed files with 2037 additions and 382 deletions
+5 -10
View File
@@ -36,19 +36,14 @@ mailbox:
username: ${MSGX_MAILBOX_USER:msgx_dev}
password: ${MSGX_MAILBOX_PASSWORD:msgx_dev_pass}
driver-class-name: com.mysql.cj.jdbc.Driver
# stub 模式无 DataSourceFlyway 显式关闭(主配置默认 enabled:true 只作用于有 DataSource 的环境)
# dev 默认 profile 为纯内存 stubstubs=true),无外部数据库,故默认关 Flyway 避免启动报错;
# 当本地开发启用真实 PostgreSQLdatasources.default.enabled=true)时,设 MSGX_FLYWAY_ENABLED=true 自动运行 Flyway 迁移。
flyway:
datasources:
default:
enabled: false
# stub 模式无真实 Redis/Kafka:关掉 micronaut 自带的 RedisHealthIndicator / KafkaHealthIndicator
# (二者装配需构造真实 client/config;实测未设 MSGX_REDIS_URI / MSGX_KAFKA_SERVERS 时 /health 整体报 500)。
# 健康由自定义 redis-flight-store / kafka-delivery indicator 承担(stub ping=true → UP)。
redis:
health:
enabled: false
enabled: ${MSGX_FLYWAY_ENABLED:false}
# stub 模式无真实 Kafka:关掉 micronaut 自带的 KafkaHealthIndicator
# (健康由自定义 kafka-delivery indicator 承担;ACM2-28Redis 已退出阶段 A 权威与写路径)。
kafka:
health:
enabled: false
+6 -9
View File
@@ -3,14 +3,14 @@
# 系统角色:机场 OMMS 上游报文处理中间件(JDBC 轮询共享 CMINMSGS 为主路径;
# compat HTTP POST /cminmsgs/send 为辅助写路径)。
# 口令/端点全部环境变量外置——零入库。
# 存储边界:自有 PostgreSQLdatasources.default,全部内部状态)+
# 共享 MySQL 信箱(mailbox.cminmsgs / mailbox.coutmsgs,仅 DML,不建表)+
# Redis(航班动态 + 快照 gen+ Kafka + Eureka/logstash(见 ACM2-12 与 docs)。
# 存储边界:自有 PostgreSQLdatasources.default,全部内部状态与运营航班权威 FLIGHT_SCHD/SCHD_GEN+
# 共享 MySQL 信箱(mailbox.shared-mysql,仅 DML,不建表)+
# Kafka + Eureka/logstash(见 ACM2-28 与 docs;Redis 彻底退出阶段 A 权威与写路径)。
# 键位口径:Micronaut 5.1U03):datasources.* / flyway.datasources.* /
# kafka.producers.<name>.* / eureka.client.*Micronaut 原生键)。
# =====================================================================
msgx:
phase: A # 航班动态权威 Redis(主泵单线程写,I5);阶段 B 缓做(ACM2-12
phase: A # 航班动态权威落自有 PGFLIGHT_SCHD,主泵单线程写,I5ACM2-28 定案
service-name: msgexchangeapi # 契约冻结;影子实例用 msgexchangeapi-shadow
register-eureka: true # 影子对拍期置 false 或独立服务名
pipeline: # —— ACMA-8 参数表初值(阶段 0 基线校准)——
@@ -38,7 +38,7 @@ micronaut:
# 管理端点(U03/N32):/env、/beans 默认 sensitive;仅开发/影子环境放开——见 application-dev.yml
# 自有 PostgreSQL:全部内部状态(消息管道 PROC_STATE/MSG_EVENT、PUMP_JOB、REQ_TRACK、
# 21 类 REF_MASTER;迁移 db/migrationACM2-12)。数据层实装U05/阶段 6前 enabled=false。
# 21 类 REF_MASTER、运营航班表 FLIGHT_SCHD 与 SCHD_GEN;迁移 db/migrationACM2-28)。数据层实装前 enabled=false。
datasources:
default:
enabled: false
@@ -50,7 +50,7 @@ datasources:
flyway:
datasources:
default:
enabled: false
enabled: ${MSGX_FLYWAY_ENABLED:true}
locations: classpath:db/migration
# 共享 MySQL 信箱(他人系统库,仅 DML:上游外部写 CMINMSGS;本系统 JDBC 轮询读 +
@@ -64,9 +64,6 @@ mailbox:
password: ${MSGX_MAILBOX_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
redis:
uri: ${MSGX_REDIS_URI} # 航班动态权威 + 快照 gen;仅主泵线程写(I5)
kafka:
bootstrap:
servers: ${MSGX_KAFKA_SERVERS}
@@ -0,0 +1,32 @@
-- =====================================================================
-- 自有 PostgreSQL 库 · 阶段 A 运营航班表与计划代迁移 · ACM2-28 定案(选项 C)
-- ---------------------------------------------------------------------
-- 存储边界(ACM2-28 定案,取代 ACM2-12「FLIGHT_STATE 缓做不落表、Redis 永续权威」口径):
-- · FLIGHT_SCHDSCHD 日计划快照 + FLOP/ADFT 增量合并后的当前运营航班权威态,落自有 PG。
-- · SCHD_GEN:各日代版本与当前代航班全量集合(差删依据),由 Redis 回归自有 PG。
-- · Redis:彻底退出动态权威与全部写路径;阶段 A 读写事务全在自有 PG 原子完成。
-- · 增量 Upsert 语义:
-- - 快照全量写入(DNLD):声明/更新 FDAY 归属,更新 FLTR_JSON
-- - 增量写入(FLOP/ADFT):新插置 NULL,已有行通过 ON CONFLICT 保留原 FDAY
-- - 按代差删域化:DELETE FROM FLIGHT_SCHD WHERE FDAY = :day AND FLID = ANY(:diffSet)
-- 仅删除仍属旧代的行,ADFT(FDAY=NULL)与已迁移至新代的同 FLID 行天然存活。
-- · 时间列规范:统一使用 TIMESTAMP(6) WITH TIME ZONE (TIMESTAMPTZ)。
-- =====================================================================
-- ① 运营航班表(当前运营航班动态权威,FLID 与 legacy flightInfo 同键)
CREATE TABLE FLIGHT_SCHD (
FLID VARCHAR(32) NOT NULL PRIMARY KEY, -- AODB 唯一航班标识
FDAY DATE NULL, -- 所属日计划代;NULL = 非代所有(ADFT/增量增建)
FLTR_JSON JSONB NOT NULL, -- 航班全量记录(与 legacy flightInfo value 同构)
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL
);
CREATE INDEX idx_flight_schd_fday ON FLIGHT_SCHD (FDAY); -- 日代扫描与影子对拍分片
-- ② 日计划代与差删元数据表(代版本推进与版本 CAS)
CREATE TABLE SCHD_GEN (
FDAY DATE NOT NULL PRIMARY KEY, -- 计划日(yyyy-MM-dd
VERSION BIGINT NOT NULL, -- 代版本号(单调递增)
FLIDS_JSON JSONB NOT NULL, -- 当前代有效航班 FLID 集合
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL
);
-9
View File
@@ -1,9 +0,0 @@
-- ACMA-8 流程 4runJob HISTORY_SWEEP/ I43:30 清场批量删除。
-- 仅删除“ES 归档成功集”(调用方以 saveSync 成功返回集为参),同一泵线程程序序保证依赖。
-- KEYS[1] = flightInfoARGV = 待删除 FLID 列表
local n = 0
for i = 1, #ARGV do
redis.call('HDEL', KEYS[1], ARGV[i])
n = n + 1
end
return n
@@ -1,19 +0,0 @@
-- ACMA-8 流程 4 / I4 / I5:日计划快照“覆盖新代 + 按代差删”,同一 hash 原子执行。
-- KEYS[1] = flightInfo
-- ARGV[1] = set 对数 N,其后为 N 对 field/value;再后为待删除 field(按代差集)
-- 删除集边界:仅上一代 gen.flids − 新代 flids(按代,非全 hash)→ ADFT 自动存活。
local key = KEYS[1]
local nSet = tonumber(ARGV[1])
local i = 2
while i <= 1 + nSet * 2 do
redis.call('HSET', key, ARGV[i], ARGV[i + 1])
i = i + 2
end
local j = 2 + nSet * 2
local deleted = 0
while j <= #ARGV do
redis.call('HDEL', key, ARGV[j])
deleted = deleted + 1
j = j + 1
end
return deleted