Files

3.2 KiB
Raw Blame History

MODIFIED Requirements

Requirement: 流量耗尽自动复机

系统 SHALL 在套餐激活或流量重置后,对满足以下全部条件的卡自动调用运营商接口复机:

  1. stop_reason = "traffic_exhausted"(仅限流量耗尽停机,手动停机不自动复机)
  2. real_name_status = 1(已完成实名认证)
  3. network_status = 0(当前处于停机状态)

系统 SHALL 在执行复机前获取 Redis 分布式锁Keycard:resume:lock:{cardID}TTL 30s防止并发重复调用 Gateway。

Scenario: 所有条件满足时自动复机

  • GIVEN 卡 C1 满足:stop_reason=traffic_exhaustedreal_name_status=1network_status=0
  • WHEN ResumeCardIfStopped(ctx, "iot_card", cardID) 被调用
  • THEN 系统获取分布式锁,调用 gateway.StartCard,更新 network_status=1,清空 stop_reason,释放锁

Scenario: 未实名卡跳过自动复机

  • GIVEN 卡 C2 stop_reason=traffic_exhaustedreal_name_status=0network_status=0
  • WHEN ResumeCardIfStopped 被调用
  • THEN 系统记录 WARN 日志,静默跳过,不调用 Gateway函数返回 nil

Scenario: 手动停机的卡不被自动复机

  • GIVEN 卡 C3 stop_reason=manualreal_name_status=1network_status=0
  • WHEN ResumeCardIfStopped 被调用
  • THEN 系统检测到 stop_reason != traffic_exhausted,静默跳过

Scenario: 并发调用时只有一次复机执行

  • GIVEN 卡 C4 满足复机条件,复机操作正在执行(分布式锁被持有)
  • WHEN 第二个 ResumeCardIfStopped 调用同时到达
  • THEN 第二个调用获锁失败,直接返回,不调用 Gateway

Scenario: 设备类型载体复机遍历所有绑定卡

  • GIVEN 设备 D1 绑定 3 张卡C1 已实名停机、C2 已实名停机、C3 未实名停机)
  • WHEN ResumeCardIfStopped(ctx, "device", deviceID) 被调用
  • THEN C1 和 C2 自动复机C3 因未实名跳过

ADDED Requirements

Requirement: 套餐超额停机必须写入 stop_reason 和 stopped_at

系统 SHALL 在套餐虚流量超额触发停机时(stopCards 函数),写入 stop_reason=traffic_exhaustedstopped_at 到 IoT 卡记录。

Scenario: 虚流量超额停机完整写入 DB

  • GIVEN 卡 C1 当月流量超过套餐 virtual_data_mb 上限,network_status=1
  • WHEN HandlePackageCheckstopCards 执行
  • THEN Gateway 调用成功后DB 更新包含:network_status=0stop_reason=traffic_exhaustedstopped_at=now()updated_at=now()

Requirement: 保护期停机使用常量 stop_reason

系统 SHALL 在保护期一致性检查停机时,使用 constants.StopReasonProtectPeriod 常量(值:protect_period)记录 stop_reason

Scenario: 保护期停机写入正确原因

  • GIVEN 设备处于停机保护期,绑定的卡 C1 network_status=1(开机状态不一致)
  • WHEN HandleProtectConsistencyCheck 触发停机
  • THEN DB 中 stop_reason=protect_period(使用常量,非中文硬编码)
  • AND ResumeCardIfStopped 调用时因 stop_reason != traffic_exhausted 跳过,不会错误触发自动复机