Files
junhong_cmp_fiber/migrations/000271_add_refund_post_process_attempt.up.sql
邹进 8eb7d403c4 feat: 退款资产后处理逐次尝试记录与重试上限,停复机指令调用前结束写跳过记录
- 新增 tb_refund_post_process_attempt,每次尝试一条(步骤、触发方式、结果、错误码与信息、耗时)
- 退款单增加 asset_post_status/attempts/last_error/next_at;失败按 2^(n-1) 分钟退避(最长 1 小时),10 次后转人工
- 中间失败只写应用日志,成功或转人工写一条结论审计(带总尝试次数、首次失败时间、最后错误码)
- 补偿扫描跳过需人工处理与未到重试时间的退款单,Outbox 不再无限重投
- 新增 POST /refunds/:id/asset-post-processing/retry 人工重试
- 停复机指令执行前结束(已是目标状态、条件不再满足、需相反动作)写 skipped 停复机记录
- 迁移 000271 需维护者在测试库执行后再部署

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 18:33:32 +09:00

49 lines
2.9 KiB
PL/PgSQL

-- 退款资产后处理:逐次尝试记录 + 退款单上的当前状态、次数、最后错误与下次重试时间。
-- 每单自动重试最多 10 次,尝试记录量很小,不分区。
BEGIN;
ALTER TABLE tb_refund_request
ADD COLUMN IF NOT EXISTS asset_post_status smallint NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS asset_post_attempts int NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS asset_post_last_error varchar(500) NOT NULL DEFAULT '',
ADD COLUMN IF NOT EXISTS asset_post_next_at timestamptz;
COMMENT ON COLUMN tb_refund_request.asset_post_status IS '资产后处理状态 0-未开始 1-待重试 2-已完成 3-需人工处理';
COMMENT ON COLUMN tb_refund_request.asset_post_attempts IS '资产后处理已尝试次数';
COMMENT ON COLUMN tb_refund_request.asset_post_last_error IS '资产后处理最后一次错误摘要';
COMMENT ON COLUMN tb_refund_request.asset_post_next_at IS '资产后处理下次自动重试时间,为空表示可立即执行';
-- 已完成的存量退款单同步为已完成。
UPDATE tb_refund_request SET asset_post_status = 2 WHERE asset_reset = true AND asset_post_status = 0;
CREATE INDEX IF NOT EXISTS idx_refund_request_asset_post_status ON tb_refund_request (asset_post_status, asset_post_next_at);
CREATE TABLE IF NOT EXISTS tb_refund_post_process_attempt (
id BIGSERIAL PRIMARY KEY,
refund_id BIGINT NOT NULL,
refund_no VARCHAR(64) NOT NULL DEFAULT '',
step VARCHAR(32) NOT NULL,
asset_type VARCHAR(16) NOT NULL DEFAULT '',
asset_id BIGINT NOT NULL DEFAULT 0,
iccid VARCHAR(30) NOT NULL DEFAULT '',
attempt INT NOT NULL,
trigger VARCHAR(16) NOT NULL,
result VARCHAR(16) NOT NULL,
error_code VARCHAR(32) NOT NULL DEFAULT '',
error_message VARCHAR(500) NOT NULL DEFAULT '',
duration_ms INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE tb_refund_post_process_attempt IS '退款资产后处理逐次尝试记录,只新增不修改';
COMMENT ON COLUMN tb_refund_post_process_attempt.step IS '处理步骤 load-读取订单与资产 invalidate-套餐失效 activate-接续激活 check_main-查询生效主套餐 stop-停机评估或停机 mark-标记完成 done-全部完成';
COMMENT ON COLUMN tb_refund_post_process_attempt.trigger IS '触发方式 outbox-Outbox投递 manual-人工重试';
COMMENT ON COLUMN tb_refund_post_process_attempt.result IS '结果 success-成功 failed-失败';
CREATE INDEX IF NOT EXISTS idx_refund_post_attempt_refund ON tb_refund_post_process_attempt (refund_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_refund_post_attempt_time ON tb_refund_post_process_attempt (created_at DESC);
CREATE INDEX IF NOT EXISTS idx_refund_post_attempt_result ON tb_refund_post_process_attempt (result, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_refund_post_attempt_error ON tb_refund_post_process_attempt (error_code, created_at DESC);
COMMIT;