refactor(storage): ACM2-12 落地——自有 PostgreSQL 全内部状态,共享 MySQL 仅信箱

按 ACM2-12 定案把仓库存储口径从"MySQL 六辅助表"推进到最终形态:
- 迁移:删除 MySQL V2.0.0 六表脚本,新增自有 PG V1.0.0
  (PROC_STATE/MSG_EVENT/PUMP_JOB/REQ_TRACK/REF_MASTER,PG 方言,REQ_TRACK.COUTMSGS_ID
  按 U18 修为 BIGINT;FLIGHT_STATE 阶段 B 缓做不建表)。
- 配置:datasources.default = 自有 PostgreSQL(enabled=false 待 U05);
  移除 datasources.reference/flyway.reference;新增 mailbox.shared-mysql(共享信箱,
  仅 DML,不建表);test profile 显式启用 H2 内存 datasource。
- 接口/注释:Repositories KDoc 按 ACM2-12 归属(自有 PG / 信箱封装 / gen→Redis 占位 /
  FLIGHT_STATE 缓做);InboxService、Pump 事务模型注释对正
  (信箱外部副作用 + PG 本地事务 + 回填最终一致)。
- 文档:architecture §1/§2/§3/§4/§5(D1/D2)/§6/§7/§8、design §1/§2/§3.1/§3.4/§3.5/§6/§9、
  README 全部按 ACM2-12 收口(自有 PG + 共享信箱 + Redis 动态/gen + 阶段 B 缓做)。

验证:37 测试全绿;dev stub 冒烟仍可启动、/health UP、收报 200。
信箱适配层(CminmsgMailbox/OutboxMailbox)、gen→Redis Lua、作业窗口语义、影子重设计
属 ACM2-12 Checks ②③④⑤(U05/U09 批次)。
This commit is contained in:
windyboy
2026-09-07 08:21:11 +08:00
parent a3f1da4bcc
commit e0ce863905
10 changed files with 280 additions and 235 deletions
@@ -9,7 +9,11 @@ import com.gzzn.omms.msgexchange.nextgen.domain.RefUpsert
import java.time.Instant
/**
* ACMA-8 v4 仓储接口(接口驱动,主泵/调度循环可单测;Micronaut Data JDBC 实装属阶段 1 后续)。
* ACM2-12 仓储接口(接口驱动,主泵/调度循环可单测;Micronaut Data JDBC 实装属 U05 批次)。
* 存储边界:自有 PostgreSQLdatasources.default= 本文件除 CminmsgInboxRepository 外
* 的全部接口(消息管道 PROC_STATE/MSG_EVENT、PUMP_JOB、REQ_TRACK、21 类 REF_MASTER);
* 共享 MySQL 信箱(CMINMSGS 收 / COUTMSGS 出)经信箱封装访问,仅 DML、不建表;
* Redis = 航班动态 + 快照 genRefDataRepository 目标实现);FLIGHT_STATE 缓做。
*/
interface ProcStateRepository {
fun insert(cminmsgsId: Long, state: ProcStatus = ProcStatus.PENDING)
@@ -60,9 +64,10 @@ interface MsgEventRepository {
}
/**
* 快照 generationSCHD_GEN)协议——只留 genACM2-11 拆分后)
* 位置:业务事务库(MySQL,与 PROC_STATE/SUCCEEDED 同事务,流程 4 重放幂等依据);
* 21 类静态主数据已迁独立 PostgreSQL 参考库(见 [StaticRefRepository],阶段 6 实装)。
* 快照 generationSCHD_GEN)协议——只留 gen。
* ACM2-12gen 迁 Redis(与 flightInfo 同源,Lua 内原子「覆盖+按代差删+版本推进」,
* DB 仅写 SUCCEEDED;重放幂等由 Lua 承接,协议重设计属 U09)。本接口为过渡占位,
* 目标实现为 Redis gen storescript 化),非关系表。
*/
interface RefDataRepository {
data class GenMeta(val flids: List<String>, val version: Long)
@@ -74,10 +79,10 @@ interface RefDataRepository {
}
/**
* 21 类静态主数据(航空公司/航线/机位/登机桥等)——独立 PostgreSQL 参考库
* `datasources.reference`ACM2-11 定案SOURCE=ADMINAPI/AODB/PIPELINEN19 对齐)。
* 与主处理链路弱事务耦合:写入者为 ReferenceService21 类同步)与请求应答路径
* 不参与主泵事务 2Redis 只作只读热点投影(legacy orms_stand 语义延续,阶段 6)。
* 21 类静态主数据(航空公司/航线/机位/登机桥等)——自有 PostgreSQL `REF_MASTER` 表
* ACM2-12:与消息管道同自有库SOURCE=ADMINAPI/AODB/PIPELINEN19 对齐)。
* 与主弱事务耦合:写入者为 ReferenceService21 类同步)与请求应答路径
* Redis 只作只读热点投影(legacy orms_stand 语义延续,阶段 6)。
*/
interface StaticRefRepository {
fun upsertAll(refs: List<RefUpsert>)
@@ -85,6 +90,10 @@ interface StaticRefRepository {
fun findByType(type: String): List<RefUpsert>
}
/**
* 15 类请求状态机——自有 PG `REQ_TRACK`ACM2-12Reference & Query 域)。
* 与共享库 COUTMSGS(出站信箱)跨库:先 COUTMSGS 落库成功 → 再 markSent,补偿重扫,最终一致。
*/
interface ReqTrackRepository {
data class Req(
val reqId: Long,
@@ -108,6 +117,11 @@ interface ReqTrackRepository {
fun markDone(reqId: Long)
}
/**
* 泵作业调度记录——自有 PG `PUMP_JOB`ACM2-12)。
* 决策 1 修订:作业不插队,仅在消息队头空闲/退避窗口由主泵执行(跨库/异队列无全序);
* 作业动作本身(归档写共享库 CMINMSGS_HST、清场删 Redis/ES 等)仍在各自目标存储。
*/
interface PumpJobRepository {
data class Job(val jobId: Long, val kind: String) // ARCHIVE/HISTORY_SWEEP/PROJECTION_REBUILD
@@ -122,6 +136,10 @@ interface PumpJobRepository {
fun markFailed(jobId: Long, lastError: String)
}
/**
* 阶段 B 权威(ACM2-12:缓做,不落表——航班动态权威保持 Redis;阶段 B 重新
* 评估后再定是否引入事务化权威)。本接口仅供占位与测试,勿据此建表。
*/
interface FlightStateRepository {
/** 阶段 B 权威;replaceDay = 单事务删差集+写新代+版本提升。 */
fun replaceDay(day: String, flights: List<Pair<String, String>>)
@@ -129,15 +147,17 @@ interface FlightStateRepository {
fun findByDay(day: String): List<Pair<String, String>>
}
/**
* 收报信箱(共享 MySQL CMINMSGS,仅 DML——ACM2-12:库属他人系统,本系统不建表)。
* 事务模型:insertRaw = 外部副作用「信箱落信」(成功即返回其主键 CMINMSGS_ID)→
* 随后自有 PG 建 PROC_STATE(PENDING) 入队;PG 建行失败以共享库
* DATE_PROCESSED IS NULL 重扫补建。backfillOnSuccess 为处理成功后的外部回填
* DATE_PROCESSED/STATUS,最终一致、失败重试+告警)。
*/
interface CminmsgInboxRepository {
/** 事务 1:原文落库(沿用 SUBSYSTEM_* 列;仅 CLOB/DATE_RECEIVEDI3:无接收唯一约束)。 */
fun insertRaw(rawXml: String): Long
fun rawOf(cminmsgsId: Long): String?
/**
* v4 回滚兼容关键:SUCCEEDED 时回填 SUBSYSTEM_*FIX+ DATE_PROCESSED/STATUS
* 旧系统按自身 processed 语义可无缝接管(Runbook 第 7 步)。
*/
fun backfillOnSuccess(cminmsgsId: Long, sndr: String, type: String, styp: String, seqn: Long)
}
@@ -5,23 +5,24 @@ import com.gzzn.omms.msgexchange.nextgen.infra.persistence.ProcStateRepository
import jakarta.inject.Singleton
import java.time.Instant
/** ACMA-8 流程 1:入站接收(事务 1。响应语义 = “已持久化”(与现役一致);不解析报文(I3)。 */
/** ACMA-8 流程 1:入站接收。响应语义 = “已持久化”(与现役一致);不解析报文(I3)。 */
@Singleton
class InboxService(
private val inbox: CminmsgInboxRepository,
private val procState: ProcStateRepository,
// TODO(阶段1后续): 事务边界(@Transactional)随 Micronaut Data 实装补齐;
// pump 唤醒仅加速,崩溃后主泵 1s 轮询兜底。
// TODO(U05 批次): 事务模型(ACM2-12)——insertRaw 为共享信箱外部写(成功即返回 ID),
// 随后自有 PG 建 PROC_STATE(PENDING);两写跨库,PG 建行失败以共享库
// DATE_PROCESSED IS NULL 重扫补建;pump 唤醒仅加速,崩溃后主泵 1s 轮询兜底。
) {
private val log = org.slf4j.LoggerFactory.getLogger(InboxService::class.java)
data class Receipt(val cminmsgsId: Long, val receivedAt: Instant)
fun accept(rawXml: String): Receipt {
val id = inbox.insertRaw(rawXml)
procState.insert(id) // 同事务(实装后);接收层无唯一约束(I3
val id = inbox.insertRaw(rawXml) // 信箱外部写(ACM2-12,与 PG 跨库)
procState.insert(id) // 自有 PG 入队;接收层无唯一约束(I3
wakePump()
log.info("accepted cminmsgsId={} (tx1)", id)
log.info("accepted cminmsgsId={}", id)
return Receipt(id, Instant.now())
}
@@ -198,8 +198,9 @@ class MessageProcessor(
if (props.phase == PipelineProps.Phase.A) {
// 阶段 A:主泵线程先写 Redis(幂等),先于事件创建(I2);TODO: redisApply(flightChanges)
}
// 事务 2:事件 + CMINMSGS 回填 + SUCCEEDED(实装后 @Transactional);
// 静态主数据(refUpserts)落独立 PG reference 库,弱事务不入本事务(ACM2-11
// 事务 2(自有 PG 内原子):事件 + SUCCEEDED(实装后 @Transactional);
// CMINMSGS 回填 = 共享信箱外部副作用(最终一致,ACM2-12);
// 静态主数据(refUpserts)同自有 PG 但弱事务独立提交(21 类 REF_MASTER)。
val events = buildList {
decision.msgNotifies.forEach { add(MsgEvent(target = Targets.KAFKA_MSG, payloadJson = it.payloadJson)) }
decision.schdPush.forEach { add(MsgEvent(target = Targets.KAFKA_SCHD, partitionKey = it.flid, payloadJson = it.fltrJson)) }
+25 -25
View File
@@ -1,12 +1,15 @@
# =====================================================================
# msgexchange-nextgen 配置(ACMA-8 v4
# 口令/端点全部环境变量外置——零入库(ACMA-8 契约冻结 + 安全基线)
# msgexchange-nextgen 配置(ACM2-12 口径
# 口令/端点全部环境变量外置——零入库
# 存储边界:自有 PostgreSQLdatasources.default,全部内部状态)+
# 共享 MySQL 信箱(mailbox.cminmsgs / mailbox.coutmsgs,仅 DML,不建表)+
# Redis(航班动态 + 快照 gen+ Kafka + Eureka/logstash(见 ACM2-12 与 docs)。
# 键位口径:Micronaut 5.1U03):datasources.* / flyway.datasources.* /
# kafka.producers.<name>.* / eureka.client.*Micronaut 原生键,勿改回 datasource 单数或 Spring 风格)。
# kafka.producers.<name>.* / eureka.client.*Micronaut 原生键)。
# =====================================================================
msgx:
phase: A # A=Redis 权威(主泵单线程写,I5);B=FLIGHT_STATE 权威+投影
service-name: msgexchangeapi # 契约冻结;影子实例用 msgexchangeapi-shadow + 独立表/key前缀/topic
phase: A # 航班动态权威 Redis(主泵单线程写,I5);阶段 B 缓做(ACM2-12
service-name: msgexchangeapi # 契约冻结;影子实例用 msgexchangeapi-shadow
register-eureka: true # 影子对拍期置 false 或独立服务名
pipeline: # —— ACMA-8 参数表初值(阶段 0 基线校准)——
poll-interval: 1s # KEEP 现役 1s 轮询节奏
@@ -21,7 +24,7 @@ msgx:
flush-limit: 500 # 批上限,防积压尖峰
identity:
include-day-boundary: false # CONFIRM(矩阵 #11):SEQN 重置作用域确认前保持关闭
consistency-check: # 阶段 A 唯一主动一致性哨兵(必选
consistency-check: # 一致性哨兵(实装属 U25
on-startup: true
daily-sample-ratio: 0.01
@@ -32,36 +35,33 @@ micronaut:
port: 8080
# 管理端点(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。
datasources:
default:
url: ${MSGX_DB_URL}
username: ${MSGX_DB_USER}
password: ${MSGX_DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
# ACM2-1121 类静态主数据独立 PostgreSQL 参考库(reference datasource)。
# 数据层实装(阶段 6 / U05 批次)前默认 disabled——不建连不解析占位符;
# 接入时置 enabled=true 并设 MSGX_REF_DB_URL(或 host/port/name)等环境变量。
reference:
enabled: false
url: ${MSGX_REF_DB_URL}
username: ${MSGX_REF_DB_USER:reference}
password: ${MSGX_REF_DB_PASSWORD:}
url: ${MSGX_PG_URL}
username: ${MSGX_PG_USER}
password: ${MSGX_PG_PASSWORD}
driver-class-name: org.postgresql.Driver
flyway:
datasources:
default:
enabled: true
locations: classpath:db/migration
# U04R01):V2.0.0 只建六张辅助表,假定 CMINMSGS/CMINMSGS_HST 等 legacy 旧表已存在;
# 全新库请按 README「数据库初始化」先落 legacy schema(或 baseline),否则收报首句 SQL 会报表不存在。
reference:
# ACM2-11:21 类静态主数据 PG 库迁移(类表 DDL 草案见 ACM2-11 Checks,阶段 6 落库)
enabled: false
locations: classpath:db/ref-migration
locations: classpath:db/migration
# 共享 MySQL 信箱(他人系统库,仅 DML:收报写 CMINMSGS、出站写 COUTMSGS;不建表/schema
# ACM2-12)。驱动/依赖与信箱适配层(CminmsgMailbox/OutboxMailbox)随 U05 批次引入。
mailbox:
shared-mysql:
url: ${MSGX_MAILBOX_URL}
username: ${MSGX_MAILBOX_USER}
password: ${MSGX_MAILBOX_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
redis:
uri: ${MSGX_REDIS_URI} # 阶段 A 权威存储;仅主泵线程写(I5
uri: ${MSGX_REDIS_URI} # 航班动态权威 + 快照 gen;仅主泵线程写(I5
kafka:
bootstrap:
@@ -0,0 +1,77 @@
-- =====================================================================
-- 自有 PostgreSQL 库(唯一自有数据库)· ACM2-12 定稿口径
-- ---------------------------------------------------------------------
-- 存储边界(ACM2-12,取代 ACMA-8 v4「MySQL 六辅助表」口径,原 MySQL V2.0.0
-- 六表脚本已删除,定义见 git 历史):
-- · 自有 PG:全部内部状态 —— 消息管道(PROC_STATE / MSG_EVENT+ 调度与请求
-- PUMP_JOB / REQ_TRACK+ 21 类静态主数据(REF_MASTER)。本地事务只在此库。
-- · 共享 MySQLcdairport,他人系统库):仅信箱 DML —— 收报写 CMINMSGS、
-- 出站写 COUTMSGS(他人读取发送);本系统不在此建表/schema(迁移不覆盖)。
-- · Redis:航班动态 flightInfo + 快照 SCHD_GENLua 原子,另行脚本)。
-- · FLIGHT_STATE(阶段 B 权威):缓做,不落表(Redis 永续动态权威)。
-- 21 类静态表 REF_MASTER 为通用 rtype/rkey 形态(SOURCE 审计;gen/SCHD_GEN
-- 已迁 Redis,不再需要 VERSION/CAS 列)。
-- 影子对拍:本库开独立 schema/实例;共享信箱只读水位/回放(见 ACM2-12 影响面)。
-- =====================================================================
-- ① 收报处理伴生状态(取消息侧;与共享库 CMINMSGS 一一对应,CMINMSGS_ID 沿用其主键)
CREATE TABLE PROC_STATE (
CMINMSGS_ID BIGINT PRIMARY KEY,
STATE VARCHAR(16) NOT NULL, -- PENDING/FAILED/SUCCEEDED/SKIPPED/DEAD
IDENTITY_KEY VARCHAR(200), -- SNDR|TYPE|STYP|SEQNdecode 后首次绑定(I3
ATTEMPTS INT NOT NULL DEFAULT 0,
NEXT_ATTEMPT_AT TIMESTAMP,
ERROR_CLASS VARCHAR(20), -- MALFORMED/CODEC_ERROR/EXHAUSTED/INFRA/UNSUPPORTED
LAST_ERROR VARCHAR(1000),
UPDATED_AT TIMESTAMP NOT NULL,
CONSTRAINT uk_proc_identity UNIQUE (IDENTITY_KEY)
);
CREATE INDEX idx_proc_head ON PROC_STATE (STATE, CMINMSGS_ID); -- 主泵队头查询(I1
-- ② 统一投递事件 outbox(发消息侧)
CREATE TABLE MSG_EVENT (
EVENT_ID BIGSERIAL PRIMARY KEY,
TARGET VARCHAR(30) NOT NULL, -- KAFKA:msg / KAFKA:schdA起);ES:flight_hts / REDIS:flightInfoB起)
PARTITION_KEY VARCHAR(64), -- schd 事件恒为 FLID
PAYLOAD_JSON TEXT NOT NULL,
STATE VARCHAR(16) NOT NULL, -- PENDING/SENT/DEAD
ATTEMPTS INT NOT NULL DEFAULT 0,
NEXT_ATTEMPT_AT TIMESTAMP,
ERROR_CLASS VARCHAR(20),
LAST_ERROR VARCHAR(1000),
CREATED_AT TIMESTAMP NOT NULL
);
CREATE INDEX idx_evt_head ON MSG_EVENT (TARGET, STATE, EVENT_ID); -- 每 target 队头(I1 双层)
-- ③ 泵作业调度记录(作业不插队:仅在消息队头空闲/退避窗口由主泵执行,决策 1 修订)
CREATE TABLE PUMP_JOB (
JOB_ID BIGSERIAL PRIMARY KEY,
KIND VARCHAR(20) NOT NULL, -- ARCHIVE / HISTORY_SWEEP / PROJECTION_REBUILD
STATE VARCHAR(16) NOT NULL, -- QUEUED/RUNNING/DONE/FAILED
CREATED_AT TIMESTAMP NOT NULL,
UPDATED_AT TIMESTAMP NOT NULL,
LAST_ERROR VARCHAR(1000)
);
-- ④ 15 类请求状态机(Reference & Query 域;与共享库 COUTMSGS 跨库:
-- 先落 COUTMSGS 成功 → 再标 SENT,补偿重扫,最终一致)
CREATE TABLE REQ_TRACK (
REQ_ID BIGSERIAL PRIMARY KEY,
REQ_TYPE VARCHAR(20) NOT NULL,
PARAMS_JSON TEXT NOT NULL,
STATE VARCHAR(16) NOT NULL, -- REGISTERED/SENT/WAITING/DONE/EXPIRED
COUTMSGS_ID BIGINT, -- U18 修正:BIGINT(原 MySQL 版 INT
SENT_AT TIMESTAMP,
COMPLETED_AT TIMESTAMP
);
CREATE INDEX idx_req_open ON REQ_TRACK (REQ_TYPE, STATE);
-- ⑤ 21 类静态主数据(SOURCE=ADMINAPI/AODB/PIPELINE 审计;弱事务 upsert
CREATE TABLE REF_MASTER (
RTYPE VARCHAR(20) NOT NULL, -- AIRL/ARPT/...
RKEY VARCHAR(64) NOT NULL,
PAYLOAD_JSON TEXT NOT NULL,
SOURCE VARCHAR(20) NOT NULL,
REFRESHED_AT TIMESTAMP NOT NULL,
PRIMARY KEY (RTYPE, RKEY)
);
@@ -1,82 +0,0 @@
-- =====================================================================
-- ACMA-8 v4 数据模型(六表)· Flyway 基线迁移
-- 与 issue「综合架构设计」数据模型节逐字一致;影子实例在独立 schema 执行同一脚本。
--
-- U04/R01 前置声明:本脚本只建六张辅助表,假定 CMINMSGS/CMINMSGS_HST/COUTMSGS 等 legacy
-- 旧表已存在(本仓库不声明旧表 V1,归 legacy 仓库维护)。全新空库请先按 legacy schema
-- 建旧表再执行本脚本,否则收报首句 SQL 会报表不存在(详见 README「数据库初始化」)。
-- =====================================================================
-- ① 处理状态伴生表(不动 CMINMSGS 旧列;
-- 回滚兼容:SUCCEEDED 时回填 CMINMSGS.DATE_PROCESSED/STATUS,旧系统可接管续跑)
CREATE TABLE PROC_STATE (
CMINMSGS_ID BIGINT PRIMARY KEY,
STATE VARCHAR(16) NOT NULL, -- PENDING/FAILED/SUCCEEDED/SKIPPED/DEAD
IDENTITY_KEY VARCHAR(200) NULL, -- SNDR|TYPE|STYP|SEQNdecode 后首次绑定(I3
ATTEMPTS INT NOT NULL DEFAULT 0,
NEXT_ATTEMPT_AT TIMESTAMP NULL,
ERROR_CLASS VARCHAR(20) NULL, -- MALFORMED/CODEC_ERROR/EXHAUSTED/INFRA/UNSUPPORTED
LAST_ERROR VARCHAR(1000) NULL,
UPDATED_AT TIMESTAMP NOT NULL,
UNIQUE KEY UK_PROC_IDENTITY (IDENTITY_KEY),
INDEX IDX_PROC_HEAD (STATE, CMINMSGS_ID) -- 主泵队头查询(I1
);
-- ② 统一投递事件(outbox)
CREATE TABLE MSG_EVENT (
EVENT_ID BIGINT AUTO_INCREMENT PRIMARY KEY,
TARGET VARCHAR(30) NOT NULL, -- KAFKA:msg / KAFKA:schdA起);ES:flight_hts / REDIS:flightInfoB起)
PARTITION_KEY VARCHAR(64) NULL, -- schd 事件恒为 FLID
PAYLOAD_JSON MEDIUMTEXT NOT NULL,
STATE VARCHAR(16) NOT NULL, -- PENDING/SENT/DEAD
ATTEMPTS INT NOT NULL DEFAULT 0,
NEXT_ATTEMPT_AT TIMESTAMP NULL,
ERROR_CLASS VARCHAR(20) NULL,
LAST_ERROR VARCHAR(1000) NULL,
CREATED_AT TIMESTAMP NOT NULL,
INDEX IDX_EVT_HEAD (TARGET, STATE, EVENT_ID) -- 每 target 队头查询(I1 双层同策略)
);
-- ③ 参考数据 + SCHD generation 元数据(21 类;SCHD_GEN 行 RKEY=日期)
CREATE TABLE REF_DATA (
RTYPE VARCHAR(20) NOT NULL, -- AIRL/ARPT/... | SCHD_GEN
RKEY VARCHAR(64) NOT NULL,
PAYLOAD_JSON MEDIUMTEXT NOT NULL, -- SCHD_GEN: {"flids":[...],"version":N}
VERSION BIGINT NOT NULL DEFAULT 0, -- putGenIfVersion CAS 依据(流程 4
SOURCE VARCHAR(20) NOT NULL, -- ADMINAPI / AODB / PIPELINE
REFRESHED_AT TIMESTAMP NOT NULL,
PRIMARY KEY (RTYPE, RKEY)
);
-- ④ 请求状态机(15 类,流程 6)
CREATE TABLE REQ_TRACK (
REQ_ID BIGINT AUTO_INCREMENT PRIMARY KEY,
REQ_TYPE VARCHAR(20) NOT NULL,
PARAMS_JSON VARCHAR(500) NOT NULL,
STATE VARCHAR(16) NOT NULL, -- REGISTERED/SENT/WAITING/DONE/EXPIRED
COUTMSGS_ID INT NULL,
SENT_AT TIMESTAMP NULL,
COMPLETED_AT TIMESTAMP NULL,
INDEX IDX_REQ_OPEN (REQ_TYPE, STATE)
);
-- ⑤ 泵作业队列(定时任务统一入口:cron 触发入队,主泵 FIFO 执行)
CREATE TABLE PUMP_JOB (
JOB_ID BIGINT AUTO_INCREMENT PRIMARY KEY,
KIND VARCHAR(20) NOT NULL, -- ARCHIVE / HISTORY_SWEEP / PROJECTION_REBUILD
STATE VARCHAR(16) NOT NULL, -- QUEUED/RUNNING/DONE/FAILED
CREATED_AT TIMESTAMP NOT NULL,
UPDATED_AT TIMESTAMP NOT NULL,
LAST_ERROR VARCHAR(1000) NULL
);
-- ⑥ 航班状态权威(阶段 B 启用;此前 Redis 为权威,I5)
CREATE TABLE FLIGHT_STATE (
FLID VARCHAR(32) PRIMARY KEY,
FDAY DATE NOT NULL,
VERSION BIGINT NOT NULL,
MAID VARCHAR(32) NULL,
PAYLOAD_JSON MEDIUMTEXT NOT NULL, -- 投影兼容格式的 FLTR JSON
UPDATED_AT TIMESTAMP NOT NULL,
INDEX IDX_FS_DAY (FDAY, VERSION)
);
+2
View File
@@ -3,6 +3,7 @@
# 以便以「注入 PipelineProps/DataSource 断言」离线验证绑定(N02/R09/R01a),不依赖 /env 端点。
# U07stubs=true 提供内存仓储使全链路(Controller→Inbox→Pump→Dispatcher)可装配;
# autostart=false:测试内不自动拉起后台循环(避免泄漏线程),按需手动 tick。
# ACM2-12main 的 datasources.default(自有 PG)默认 enabled=false,测试以 H2 内存替代并显式启用。
msgx:
register-eureka: false
stubs: true
@@ -11,6 +12,7 @@ msgx:
datasources:
default:
enabled: true
url: jdbc:h2:mem:cfgtest;DB_CLOSE_DELAY=-1
username: sa
password: ""