All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m35s
实现功能: - 实名状态检查轮询(可配置间隔) - 卡流量检查轮询(支持跨月流量追踪) - 套餐检查与超额自动停机 - 分布式并发控制(Redis 信号量) - 手动触发轮询(单卡/批量/条件筛选) - 数据清理配置与执行 - 告警规则与历史记录 - 实时监控统计(队列/性能/并发) 性能优化: - Redis 缓存卡信息,减少 DB 查询 - Pipeline 批量写入 Redis - 异步流量记录写入 - 渐进式初始化(10万卡/批) 压测工具(scripts/benchmark/): - Mock Gateway 模拟上游服务 - 测试卡生成器 - 配置初始化脚本 - 实时监控脚本 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
7.1 KiB
7.1 KiB
ADDED Requirements
Requirement: 卡流量查询
系统 SHALL 调用 Gateway API 查询卡的流量使用情况,并处理跨月流量计算。
Scenario: 查询卡流量
- WHEN 流量检查任务执行,卡A的 ICCID 为 "89860123456789012345"
- THEN 系统调用 Gateway.QueryFlow(ICCID),获取流量响应(包含月总流量 MB)
Scenario: Gateway 返回月总流量
- WHEN Gateway 返回流量数据,total_usage_mb=500(本自然月累计)
- THEN 系统获取到月总流量数据,准备计算增量
Scenario: Gateway API 超时
- WHEN 调用 Gateway API 超时(>30秒)
- THEN 系统记录错误日志,任务失败,不重试,卡重新入队(按原计划下次检查)
Scenario: Gateway API 返回错误
- WHEN Gateway API 返回业务错误(如卡号不存在)
- THEN 系统记录错误日志,不更新数据库,任务失败,卡重新入队
Requirement: 跨月流量计算
系统 SHALL 正确处理跨月流量计算,识别月份切换并重置月度统计。
Scenario: 首次查询流量(冷启动)
- WHEN 卡A从未查询过流量,current_month_start_date 为 NULL
- THEN 系统初始化 current_month_start_date=当前月1日,current_month_usage_mb=Gateway返回值,last_month_total_mb=0
Scenario: 同月内流量增长
- WHEN 卡A上次查询在本月(current_month_start_date=2024-01-01),Gateway 返回 total_usage_mb=500,数据库当前 current_month_usage_mb=400
- THEN 系统计算增量 100 MB,更新 current_month_usage_mb=500
Scenario: 跨月流量重置
- WHEN 卡A上次查询在上月(current_month_start_date=2024-01-01),当前时间为 2024-02-05,Gateway 返回 total_usage_mb=50(新月重置后)
- THEN 系统检测到跨月,保存 last_month_total_mb=400(上月结束值),重置 current_month_start_date=2024-02-01,current_month_usage_mb=50
Scenario: Gateway 返回值回退(异常)
- WHEN Gateway 返回 total_usage_mb=300,小于数据库当前值 current_month_usage_mb=400(同月内)
- THEN 系统记录警告日志,怀疑数据异常,但仍更新为 Gateway 值(信任 Gateway 数据源)
Requirement: 数据库更新
系统 SHALL 更新卡的流量字段到数据库。
Scenario: 更新流量字段
- WHEN 计算出增量流量 100 MB
- THEN 系统执行
UPDATE iot_cards SET current_month_usage_mb=500, current_month_start_date='2024-01-01', last_realname_check_at=NOW() WHERE id=?
Scenario: 数据库更新失败
- WHEN 数据库更新失败(如连接断开)
- THEN 系统记录错误日志,任务失败,卡重新入队
Requirement: Redis 缓存更新
系统 SHALL 同步更新 Redis 缓存中的卡流量信息。
Scenario: 更新缓存流量字段
- WHEN 数据库更新成功
- THEN 系统使用 HSET 更新 Redis 缓存(polling:card:{card_id})的 current_month_usage_mb、current_month_start_date、last_month_total_mb 字段
Scenario: 缓存更新失败不影响主流程
- WHEN Redis 更新失败
- THEN 系统记录警告日志,但任务仍视为成功(缓存可以通过定时同步或懒加载恢复)
Requirement: 流量历史记录
系统 SHALL 记录流量变化历史到 data_usage_records 表。
Scenario: 记录流量增量
- WHEN 计算出增量流量 100 MB
- THEN 系统插入记录到 data_usage_records 表(card_id、usage_mb=100、usage_type='data'、recorded_at=NOW())
Scenario: 跨月时记录上月总量
- WHEN 检测到跨月,上月总流量为 400 MB
- THEN 系统插入一条月度汇总记录(card_id、usage_mb=400、usage_type='monthly_summary'、recorded_at=上月最后一天)
Scenario: 历史记录插入失败
- WHEN 历史记录插入失败
- THEN 系统记录警告日志,但任务仍视为成功(历史记录非关键路径)
Requirement: 触发套餐检查
系统 SHALL 在流量更新后触发关联套餐的流量检查。
Scenario: 卡有关联套餐
- WHEN 卡A更新流量后,card_package_id 不为空
- THEN 系统将该套餐加入 polling:manual:package 手动触发队列,优先检查套餐流量
Scenario: 卡无关联套餐
- WHEN 卡A更新流量后,card_package_id 为空
- THEN 系统不触发套餐检查
Scenario: 卡关联设备级套餐
- WHEN 卡A属于设备D,设备D有套餐
- THEN 系统将设备的套餐加入手动触发队列
Requirement: 并发控制
系统 SHALL 使用 Redis 信号量控制流量检查的并发数。
Scenario: 获取并发信号量成功
- WHEN 流量检查任务开始执行,当前并发数为 30,配置的最大并发数为 50
- THEN 系统使用 INCR 增加计数,获取信号量成功,执行任务
Scenario: 并发已满
- WHEN 流量检查任务开始执行,当前并发数为 50,配置的最大并发数为 50
- THEN 系统 INCR 后发现超过限制,DECR 归还,任务返回 SkipRetry(不执行,等待下次调度)
Scenario: 任务完成释放信号量
- WHEN 流量检查任务完成(成功或失败)
- THEN 系统使用 DECR 释放信号量
Requirement: 重新入队
系统 SHALL 在检查完成后,将卡重新加入轮询队列。
Scenario: 计算下次检查时间
- WHEN 流量检查完成,当前配置的检查间隔为 1800 秒
- THEN 系统计算 next_check_time = NOW() + 1800秒
Scenario: 加回队列
- WHEN 计算出下次检查时间
- THEN 系统使用 ZADD 将卡ID和时间戳加入 polling:queue:carddata
Scenario: 任务失败也重新入队
- WHEN 任务因 Gateway 超时失败
- THEN 系统仍然将卡重新入队(按原计划下次检查),不阻塞后续检查
Requirement: 监控统计
系统 SHALL 记录流量检查的成功率和耗时。
Scenario: 记录成功统计
- WHEN 流量检查成功完成,耗时 234 毫秒
- THEN 系统更新 Redis Hash(polling:stats:carddata),增加 success_count_1h,累加 total_duration_1h
Scenario: 记录失败统计
- WHEN 流量检查失败(Gateway 超时)
- THEN 系统更新 Redis Hash,增加 failure_count_1h
Scenario: 每小时重置计数器
- WHEN 每小时整点(如 10:00:00)
- THEN 系统重置计数器(success_count_1h、failure_count_1h、total_duration_1h),保持时间窗口滚动
Requirement: 日志记录
系统 SHALL 记录详细的流量检查日志,便于排查问题。
Scenario: 记录开始日志
- WHEN 流量检查任务开始执行
- THEN 系统记录 Info 日志,包含 card_id、iccid、config_id
Scenario: 记录成功日志
- WHEN 流量检查成功完成
- THEN 系统记录 Info 日志,包含 card_id、iccid、old_usage_mb、new_usage_mb、increment_mb、duration_ms
Scenario: 记录失败日志
- WHEN 流量检查失败
- THEN 系统记录 Error 日志,包含 card_id、iccid、error 详情
Scenario: 记录跨月日志
- WHEN 检测到跨月
- THEN 系统记录 Info 日志,包含 card_id、old_month、new_month、last_month_total_mb