CREATE DATABASE IF NOT EXISTS hyapp_notice DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci; USE hyapp_notice; CREATE TABLE IF NOT EXISTS notice_delivery_events ( source_name VARCHAR(64) NOT NULL COMMENT '事件源表或服务名,例如 wallet_outbox', app_code VARCHAR(32) NOT NULL COMMENT '租户编码,必须和源 outbox 保持一致', source_event_id VARCHAR(128) NOT NULL COMMENT '源事件幂等键', channel VARCHAR(64) NOT NULL COMMENT '投递通道,例如 tencent_im_c2c', notice_type VARCHAR(64) NOT NULL COMMENT '业务通知类型,例如 WalletBalanceChanged', target_user_id BIGINT NOT NULL COMMENT '私有通知目标用户', status VARCHAR(32) NOT NULL COMMENT 'delivering/delivered/retryable/failed', retry_count INT NOT NULL DEFAULT 0 COMMENT '已尝试次数,达到上限后进入 failed', locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '当前抢占 worker', lock_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '抢占锁过期时间,UTC epoch ms', next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一次允许重试时间,UTC epoch ms', payload_json JSON NOT NULL COMMENT '发送给客户端的最终负载快照', last_error TEXT NULL COMMENT '最后一次投递失败原因,限制在应用层截断', delivered_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '成功投递时间,UTC epoch ms', created_at_ms BIGINT NOT NULL COMMENT 'notice 位点创建时间,UTC epoch ms', updated_at_ms BIGINT NOT NULL COMMENT 'notice 位点更新时间,UTC epoch ms', PRIMARY KEY (source_name, app_code, source_event_id, channel), KEY idx_notice_delivery_pending (status, next_retry_at_ms, lock_until_ms, updated_at_ms), KEY idx_notice_delivery_target (app_code, target_user_id, updated_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='notice-service 外部通知投递位点和死信表';