feat: add reusable MySQL outbox and HTTP lifecycle example

This commit is contained in:
2026-09-24 20:54:36 +08:00
parent 0140c78ea7
commit e29dec717f
52 changed files with 2488 additions and 357 deletions

View File

@@ -0,0 +1,32 @@
-- 业务数据库的初始Outbox表,保留原示例表名以兼容,不属于平台迁移,无外键或级联删除。
CREATE TABLE sender_outbox (
namespace_id CHAR(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL COMMENT '固定目标命名空间,重启及换凭据不得改变',
queue_id CHAR(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL COMMENT '固定目标队列,发送前核对当前授权及命名空间',
operation_id CHAR(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL COMMENT '业务操作标识,同命名空间内唯一,调用方持久化后复用',
idempotency_key VARCHAR(128) CHARACTER SET ascii COLLATE ascii_bin NOT NULL COMMENT '冻结平台提交键,由业务操作标识派生,禁止换键补发',
request_json MEDIUMTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '冻结任务提交正文,保留精确数字,不存认证凭据',
request_digest BINARY(32) NOT NULL COMMENT '冻结正文SHA256,防止同身份不同内容,非平台摘要算法',
state VARCHAR(16) CHARACTER SET ascii COLLATE ascii_bin NOT NULL COMMENT 'PENDING待发,SENDING领取中,ACCEPTED已受理,REVIEW需核查',
send_count INT UNSIGNED NOT NULL COMMENT '领取次数,包含领取后崩溃的次数,最多100',
lease_epoch BIGINT UNSIGNED NOT NULL COMMENT '领取代次递增,旧发送器不能覆盖新代次结果',
wake_at DATETIME(6) NULL COMMENT '待发下次时间或发送租约期限,终结后为空,UTC微秒',
send_deadline_at DATETIME(6) NOT NULL COMMENT '首次入库24小时后的发送截止,短于平台幂等保留窗口',
last_code VARCHAR(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL COMMENT '最近稳定分类,不保存服务端错误正文或秘密',
task_id CHAR(32) CHARACTER SET ascii COLLATE ascii_bin NULL COMMENT '已确认的平台任务标识,只在ACCEPTED非空',
receipt_json MEDIUMTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT '原受理回执,仅ACCEPTED非空,不代表当前执行结果',
created_at DATETIME(6) NOT NULL COMMENT '业务事务首次创建命令UTC时间,微秒精度',
updated_at DATETIME(6) NOT NULL COMMENT '本地状态最近变化UTC时间,微秒精度',
PRIMARY KEY (namespace_id,operation_id),
UNIQUE KEY uq_sender_identity(namespace_id,idempotency_key),
KEY ix_sender_due(namespace_id,queue_id,wake_at,operation_id),
CONSTRAINT ck_sender_document CHECK (JSON_VALID(request_json)),
CONSTRAINT ck_sender_receipt CHECK (receipt_json IS NULL OR JSON_VALID(receipt_json)),
CONSTRAINT ck_sender_count CHECK (send_count<=100 AND lease_epoch=send_count),
CONSTRAINT ck_sender_state CHECK (
(state IN ('PENDING','SENDING') AND wake_at IS NOT NULL AND task_id IS NULL AND receipt_json IS NULL)
OR (state='REVIEW' AND wake_at IS NULL AND task_id IS NULL AND receipt_json IS NULL)
OR (state='ACCEPTED' AND wake_at IS NULL AND task_id IS NOT NULL AND receipt_json IS NOT NULL)
),
CONSTRAINT ck_sender_lease CHECK (state<>'SENDING' OR lease_epoch>0),
CONSTRAINT ck_sender_deadline CHECK (send_deadline_at>created_at AND send_deadline_at<=TIMESTAMPADD(HOUR,24,created_at))
) ENGINE=InnoDB COMMENT='业务事务Outbox,持久化原请求与有限重发状态,不承担业务恰好一次';