Files
svc-hall-service/sql/answer_reconcile_work.sql
chenxing 391281582a
build / build-push (push) Successful in 1m21s
t1~t3+精修: 事项FC绑定/可信建件(意图+投影+恢复)/答卷对账Worker
含10-22精修: 对账有限重试(retry_count/指数退避/work_version防旧覆盖)+接缝身份(source-app-key空拒收)+应急对账闸让位FlowApplyRecoveryService+同attempt指令不重开终态。SQL未执行。
2026-10-22 10:03:07 +08:00

83 lines
8.2 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- ============================================================
-- 办事大厅 · 对账任务接收与执行检查点 DDL(MySQL 5.7 兼容复核版,TASK_3)
-- 范围:一张新表 answer_reconcile_work(中心侧契约见 form-center/service/docs/answer-reconcile-v1.md)
-- 依据:任务书 TASK_3 改动点 4(SH 持久化接收任务、重复指令复用 taskId、进程重启从 checkpoint 续页)、
-- 改动点 5/6(比较四元摘要、经权威入口修复、多余行只在完整证明后退役)
-- 用途:生产 ddl-auto=none 时的升级脚本;开发期(本机 bsch_svchall,ddl-auto=update)由 Hibernate
-- 自动追加,本脚本同时是"实表应当长什么样"的评审权威(沿 fc_projection_and_apply_intent 先例)。
-- 5.7 复核要点:①无 CTE/WITH、无函数索引、无生成列、无 CHECK 约束;②utf8mb4 显式写 CHARSET/COLLATE;
-- ③<b>不建物理外键</b>——task_uuid 是中心任务的逻辑引用,本行要能在中心归档后继续留痕;
-- ④两条游标与水位同为 answer_uuid(32 位小写十六进制),锁步推进才是"多余行"可判的前提。
-- 边界纪律:本表只存<b>对账坐标与检查点</b>,不存答卷值文档——值文档归 fc_answer_projection(TASK_2),
-- 修复走 repairAuthoritative、退役走 retireAbsent,本任务不提供任何绕过它们的通道。
-- 状态纪律:接收端点的 2xx 只把 state 写成 QUEUED;COMPLETED/PARTIAL 必须来自本地扫描的真实收尾,
-- 且以 (task_uuid, attempt) 的回报为准。
-- 非幂等:MySQL 5.7 无评审友好的 CREATE TABLE IF NOT EXISTS 写法。
-- 执行前先 `SHOW TABLES LIKE 'answer_reconcile_work'` 确认表不存在。
-- ============================================================
CREATE TABLE `answer_reconcile_work` (
`work_version` BIGINT NOT NULL DEFAULT 0 COMMENT 'Local optimistic write generation',
`retry_count` INT NOT NULL DEFAULT 0 COMMENT 'Consecutive execution/report failures',
`pending_report_state` VARCHAR(16) DEFAULT NULL COMMENT 'Retry this result only; do not rescan data',
`id` INT NOT NULL AUTO_INCREMENT,
`task_uuid` VARCHAR(36) NOT NULL COMMENT '中心任务身份(<b>唯一键</b>:重复指令复用本行与检查点,不另起一轮扫描)',
`attempt` INT NOT NULL DEFAULT 0 COMMENT '当前执行的派发尝试;更旧 attempt 的指令只吸收,不动检查点与已提交结论',
`consumer_app_key` VARCHAR(64) NOT NULL COMMENT '本应用消费身份(须与已验签身份逐字相等才收)',
`consumer_school_id` BIGINT NOT NULL COMMENT '本轮租户域:本地扫描按它限定行集,跨校指令拒收',
`form_uuid` VARCHAR(32) NOT NULL COMMENT '本轮范围的表单坐标(一行任务=一个 (消费方, 租户域, 表单))',
`form_version` INT NOT NULL COMMENT '中心已核验的版本(不从本地旧清单猜)',
`trigger_type` VARCHAR(16) DEFAULT NULL COMMENT 'SCHEDULE / MANUAL',
`window_start` DATETIME NOT NULL COMMENT '任务起点:本地 create_time 晚于它或为空的行<b>只报告、不退役</b>',
`total_rows` INT NOT NULL DEFAULT 0 COMMENT '中心清单总行数(完整性核对用)',
`total_pages` INT NOT NULL DEFAULT 0 COMMENT '中心清单确定总页',
`page_size` INT NOT NULL DEFAULT 200 COMMENT '两侧同页大小(上限 500):锁步比较才对得上',
`state` VARCHAR(16) NOT NULL DEFAULT 'QUEUED' COMMENT 'QUEUED/RUNNING/COMPLETED/PARTIAL/FAILED/CANCELLED',
`fc_cursor` VARCHAR(32) DEFAULT NULL COMMENT '中心清单游标(=水位,answer_uuid)',
`local_cursor` VARCHAR(32) DEFAULT NULL COMMENT '本地图像游标(=水位,answer_uuid)',
`watermark` VARCHAR(32) DEFAULT NULL COMMENT '两侧都已比较到的最大 answer_uuid:断线重启从这里续',
`fc_completed` TINYINT NOT NULL DEFAULT 0 COMMENT '中心清单是否读到底(多余行判定的前提之一)',
`local_completed` TINYINT NOT NULL DEFAULT 0 COMMENT '本地图像是否扫完(另一个前提)',
`pages_processed` INT NOT NULL DEFAULT 0 COMMENT '已推进的锁步轮数',
`scanned_rows` INT NOT NULL DEFAULT 0 COMMENT '比较过的答卷数',
`missing_repaired` INT NOT NULL DEFAULT 0 COMMENT '缺失修复 APPLIED 数(期望三元组全 null,只建未关联投影)',
`stale_repaired` INT NOT NULL DEFAULT 0 COMMENT '陈旧与同版错 hash 的修复 APPLIED 数(同一权威入口)',
`hash_conflicts` INT NOT NULL DEFAULT 0 COMMENT '同 revision 异 hash 的观察数(记录后才取中心当前值修复)',
`tombstones_repaired` INT NOT NULL DEFAULT 0 COMMENT '墓碑修复数(保留本地业务扩展列,不物理删)',
`local_ahead` INT NOT NULL DEFAULT 0 COMMENT '本地 revision 更高:向中心复核后只报告,禁止降级覆盖',
`deferred` INT NOT NULL DEFAULT 0 COMMENT '新鲜授权核验不可达/撤权/纪元不等而暂停的条目',
`extra_reported` INT NOT NULL DEFAULT 0 COMMENT '本地多出的行观察数(含期间新增与 createTime 未知,只报告)',
`extra_retired` INT NOT NULL DEFAULT 0 COMMENT '经中心签名缺席证明实际退役的行数',
`pending_extras_json` MEDIUMTEXT NOT NULL COMMENT '待缺席答复的多余行候选(含 create_time;<b>不含值文档</b>,有上限)',
`error_count` INT NOT NULL DEFAULT 0 COMMENT '错误条数',
`errors_json` MEDIUMTEXT NOT NULL COMMENT '错误明细(每条含 consumer/task/range/answer 四坐标,<b>敏感 values 永不进这里</b>)',
`reported_attempt` INT DEFAULT NULL COMMENT '已提交给中心的结果 attempt(同 attempt 不重复提交)',
`reported_state` VARCHAR(16) DEFAULT NULL COMMENT '已提交的结果状态',
`resumed` INT NOT NULL DEFAULT 0 COMMENT 'RUNNING 超租约后被重新领取的次数(这一轮断过几次)',
`lease_until` DATETIME DEFAULT NULL COMMENT '本地执行租约:超期才可被别的扫描线程领走续跑',
`next_retry_at` DATETIME DEFAULT NULL COMMENT '退避到点才再扫(扫描中断/回报不可达时写)',
`received_at` DATETIME NOT NULL COMMENT '指令落库时刻(接收端点 2xx 的依据就在这列)',
`started_at` DATETIME DEFAULT NULL COMMENT '首次开始执行时刻',
`finished_at` DATETIME DEFAULT NULL COMMENT '终态落定时刻',
`last_error_code` VARCHAR(32) DEFAULT NULL COMMENT '末次稳定码(GRANT_REVOKED/CANCELLED/MANIFEST_INCOMPLETE/…)',
`last_error` VARCHAR(500) DEFAULT NULL COMMENT '末次错误摘要(截断存)',
`create_by` VARCHAR(255) DEFAULT NULL,
`create_time` DATETIME DEFAULT NULL,
`update_by` VARCHAR(255) DEFAULT NULL,
`update_time` DATETIME DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_reconcile_work_task` (`task_uuid`),
KEY `idx_reconcile_work_scan` (`state`, `next_retry_at`),
KEY `idx_reconcile_work_consumer` (`consumer_app_key`, `consumer_school_id`, `id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
COMMENT='对账任务接收与检查点(TASK_3:接收与执行解耦、同 taskId 幂等复用、重启从 watermark 续页;不存值文档)';
-- 自验(执行后逐条核对):
-- SHOW CREATE TABLE answer_reconcile_work\G -- 应含 uk_reconcile_work_task(同 taskId 只一行)
-- SELECT COUNT(*) FROM information_schema.referential_constraints
-- WHERE table_name='answer_reconcile_work'; -- 必须 0 行(无物理外键)
-- SELECT COUNT(*) FROM information_schema.columns
-- WHERE table_schema=DATABASE() AND table_name='answer_reconcile_work'
-- AND column_name IN ('values_json','snapshot_json','context_token');
-- -- 必须 0 行(值文档与令牌不进对账检查点)