-- 卡轮询失败告警(add-carrier-polling-scheduler)。 -- 背景:新调度按"卡 × 检查类型"记连续失败并退避重试;持续失败需要告警,由运营联系上游或关闭该卡轮询。 -- -- 设计选择: -- 1. 同一卡同一检查类型只保留一条未处理告警(部分唯一索引),后续失败更新计数与最近错误。 -- 2. status:1-未处理 2-已恢复(首次成功自动转入)3-已关闭轮询 4-已处理(人工标记)。 -- 3. check_type 取值 card_status / carddata / realname / package;停复机方向在停复机指令队列接入同一张表。 -- 4. alert_level:card 卡级 / carrier 账户级(同账户窗口内告警数超阈值时产生,card_id 为 0)。 -- 5. 告警写入走异步,失败只记日志,不影响轮询;不使用数据库外键(ENG-MODEL-001)。 CREATE TABLE tb_polling_failure_alert ( id BIGSERIAL PRIMARY KEY, alert_level VARCHAR(20) NOT NULL DEFAULT 'card', card_id BIGINT NOT NULL DEFAULT 0, iccid VARCHAR(30) NOT NULL DEFAULT '', carrier_id BIGINT NOT NULL DEFAULT 0, check_type VARCHAR(30) NOT NULL, error_category VARCHAR(50) NOT NULL DEFAULT '', fail_count INTEGER NOT NULL DEFAULT 0, first_failed_at TIMESTAMPTZ, last_failed_at TIMESTAMPTZ, last_error VARCHAR(500) NOT NULL DEFAULT '', status SMALLINT NOT NULL DEFAULT 1, handled_by BIGINT NOT NULL DEFAULT 0, handled_at TIMESTAMPTZ, handle_remark VARCHAR(500) NOT NULL DEFAULT '', recovered_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT ck_polling_failure_alert_status CHECK (status IN (1, 2, 3, 4)), CONSTRAINT ck_polling_failure_alert_level CHECK (alert_level IN ('card', 'carrier')) ); CREATE UNIQUE INDEX uk_polling_failure_alert_open ON tb_polling_failure_alert (alert_level, card_id, carrier_id, check_type) WHERE status = 1; CREATE INDEX idx_polling_failure_alert_carrier ON tb_polling_failure_alert (carrier_id, status, last_failed_at DESC); CREATE INDEX idx_polling_failure_alert_card ON tb_polling_failure_alert (card_id, created_at DESC); CREATE INDEX idx_polling_failure_alert_created ON tb_polling_failure_alert (created_at DESC); COMMENT ON TABLE tb_polling_failure_alert IS '卡轮询失败告警:同一卡同一检查类型只保留一条未处理告警'; COMMENT ON COLUMN tb_polling_failure_alert.alert_level IS '告警级别 card-卡级 carrier-账户级'; COMMENT ON COLUMN tb_polling_failure_alert.card_id IS '卡ID,账户级告警为 0'; COMMENT ON COLUMN tb_polling_failure_alert.check_type IS '检查类型 card_status / carddata / realname / package;账户级告警为 all'; COMMENT ON COLUMN tb_polling_failure_alert.error_category IS '最近错误类别(网关错误类别或上游错误分类)'; COMMENT ON COLUMN tb_polling_failure_alert.fail_count IS '连续失败次数;账户级告警为窗口内告警数'; COMMENT ON COLUMN tb_polling_failure_alert.last_error IS '最近错误(脱敏截断)'; COMMENT ON COLUMN tb_polling_failure_alert.status IS '状态 1-未处理 2-已恢复 3-已关闭轮询 4-已处理';