Files
junhong_cmp_fiber/migrations/000244_add_gateway_error_classification.up.sql
邹进 42e881576d
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m33s
feat: 卡网关按运营商账户限流并记录停复机调用
- 新增网关限流:按本系统运营商账户(卡 carrier_id)→ 限流组 → 操作限制每秒请求数,每次 HTTP 尝试计量,默认限流、仅后台人工点击/通道阈值/自动续费/手动刷新豁免;支持只统计与拦截两种模式,默认只统计
- Asynq 遇限流不计失败、固定短延迟重试;轮询任务与停复机业务重试遇限流短延迟重排
- 停机、复机不再使用网关内部重试,只发一次请求
- 网关返回结构化错误;新增上游错误分类规则表与测试接口
- 新增按月分区的停复机记录表:系统自动停复机只写记录,不再写统一审计与集成日志;普通轮询查询不再写集成日志
- 新增限流组、错误分类、停复机记录、按账户调用统计与枚举后台接口
- 迁移 000243~000246;同步 OpenSpec 提案(含后续 6 个 change)与技术方案、工程约束
2026-10-24 15:06:41 +09:00

62 lines
5.3 KiB
SQL
Raw 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.
-- 上游错误分类规则(add-carrier-gateway-rate-limit)。
-- 背景:网关对各类上游错误统一返回 code=400,失败原因只拼在错误字符串里,无法区分频率限制、终态、临时故障与业务错误。
-- 本表把上游返回信息按关键字归入类别,供停复机与轮询的失败处理、告警与统计使用;后台可逐条增补。
--
-- 设计选择:
-- 1. match_type:contains(包含)/ prefix(前缀)/ regex(正则);operations 为空数组表示适用全部操作。
-- 2. priority 越小越先匹配;未命中任何规则的上游业务错误归为业务错误(business)。
-- 3. maybe_accepted 标记"上游可能已受理"(如"调用成功-5分钟内最多重复调用3次"),停复机下次执行前先查卡状态确认。
-- 4. 只有明确表示卡已处于目标状态的返回才可归入 already_target;老系统结束停机任务的关键字("已存在""密码错误"等)
-- 不代表停机成功,初始数据不据此归类为 already_target。
-- 5. 初始规则来自《轮询按运营商账户限流技术方案》第三部分 6.2 节(生产 2026-10-22 实测返回)。
CREATE TABLE tb_gateway_error_classification (
id BIGSERIAL PRIMARY KEY,
keyword VARCHAR(200) NOT NULL,
match_type VARCHAR(20) NOT NULL DEFAULT 'contains',
category VARCHAR(30) NOT NULL,
operations JSONB NOT NULL DEFAULT '[]'::jsonb,
priority INTEGER NOT NULL DEFAULT 100,
maybe_accepted BOOLEAN NOT NULL DEFAULT FALSE,
status SMALLINT NOT NULL DEFAULT 1,
remark VARCHAR(500) NOT NULL DEFAULT '',
creator BIGINT NOT NULL DEFAULT 0,
updater BIGINT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ,
CONSTRAINT ck_gateway_error_classification_match CHECK (match_type IN ('contains', 'prefix', 'regex')),
CONSTRAINT ck_gateway_error_classification_category CHECK (category IN ('rate_limited_upstream', 'terminal', 'already_target', 'transient', 'business', 'account_config')),
CONSTRAINT ck_gateway_error_classification_status CHECK (status IN (0, 1))
);
CREATE INDEX idx_gateway_error_classification_active ON tb_gateway_error_classification (status, priority) WHERE deleted_at IS NULL;
COMMENT ON TABLE tb_gateway_error_classification IS '上游错误分类规则:按关键字把网关返回信息归入失败类别';
COMMENT ON COLUMN tb_gateway_error_classification.keyword IS '匹配关键字或正则';
COMMENT ON COLUMN tb_gateway_error_classification.match_type IS '匹配方式 contains-包含 prefix-前缀 regex-正则';
COMMENT ON COLUMN tb_gateway_error_classification.category IS '类别 rate_limited_upstream-上游频率限制 terminal-终态不可操作 already_target-已是目标状态 transient-临时故障 business-业务错误 account_config-账户配置错误';
COMMENT ON COLUMN tb_gateway_error_classification.operations IS '适用操作,空数组表示全部:query_flow/query_status/query_realname/stop/start';
COMMENT ON COLUMN tb_gateway_error_classification.priority IS '匹配优先级,越小越先匹配';
COMMENT ON COLUMN tb_gateway_error_classification.maybe_accepted IS '上游可能已受理(如返回含调用成功、操作进行中、请求被合并)';
COMMENT ON COLUMN tb_gateway_error_classification.status IS '状态 0-停用 1-启用';
COMMENT ON COLUMN tb_gateway_error_classification.remark IS '备注';
INSERT INTO tb_gateway_error_classification (keyword, match_type, category, priority, maybe_accepted, remark) VALUES
('仅允许一次', 'contains', 'rate_limited_upstream', 10, TRUE, '3分钟内同一张卡相同操作仅允许一次'),
('最多重复调用', 'contains', 'rate_limited_upstream', 10, TRUE, '调用成功-5分钟内最多重复调用3次'),
('只允许调用', 'contains', 'rate_limited_upstream', 10, TRUE, '调用成功-卡状态变更每十分钟只允许调用1次'),
('请求被合并', 'contains', 'rate_limited_upstream', 10, TRUE, '请求被合并,以最新一次为准'),
('操作进行中', 'contains', 'rate_limited_upstream', 10, TRUE, '操作进行中'),
('超频访问', 'contains', 'rate_limited_upstream', 10, FALSE, '超频访问'),
('已销户', 'contains', 'terminal', 20, FALSE, '当前用户已销户,无法操作'),
('仅支持风险复机', 'contains', 'terminal', 20, FALSE, '当前卡为风险停机状态,仅支持风险复机'),
('号码封存', 'contains', 'terminal', 20, FALSE, '用户状态是物联网号码封存,禁止办理物联网停机'),
('密码错误', 'contains', 'account_config', 30, FALSE, '账户凭证问题,影响该账户全部卡'),
('参数缺失', 'contains', 'account_config', 30, FALSE, '账户接入参数问题'),
('token 为空', 'contains', 'transient', 40, FALSE, '湖北省网获取到的 token 为空'),
('token为空', 'contains', 'transient', 40, FALSE, '获取到的 token 为空'),
('当前用户不允许办理', 'contains', 'business', 50, FALSE, '不视为已是目标状态'),
('防范实名', 'contains', 'business', 50, FALSE, '不视为已是目标状态'),
('请求失败', 'contains', 'transient', 90, FALSE, '上游通用失败');