All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m11s
问题一:protect 轮询任务从未被调度器初始化入队 PollingConfig 新增 protect_check_interval 字段(NULL=不参与), 调度器 initCardsBatch/initCardPolling/requeueCard 补全 protect 队列 初始化逻辑,IotCard 新增 last_protect_check_at 记录上次检查时间。 迁移文件:000102_add_polling_protect_fields 问题二:设备套餐流量耗尽时绑定卡未被停机 UsageService.checkAndTriggerSuspension 新增 carrier_type=device 分支, 通过 DeviceSimBindingStore.ListByDeviceID 查询绑定卡,对每张卡异步 触发 CheckAndStopCard,同步注入 Bootstrap 依赖。 问题三:主套餐过期后不立即停机,依赖下次轮询兜底 PackageActivationHandler.processExpiredPackage 在 updateCarrierSuspended Status 后,若载体无后续生效套餐,立即异步调用 CheckAndStopCard(iot_card 类型直接触发,device 类型遍历绑定卡),消除停机延迟窗口。 Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2.1 KiB
2.1 KiB
ADDED Requirements
Requirement: 套餐过期时立即触发绑定卡停机
当主套餐过期处理完成后,若该套餐的载体(卡或设备)无任何后续生效套餐,系统 SHALL 立即异步触发停机检查,不依赖下一次 carddata 轮询兜底。
触发位置:PackageActivationHandler.processExpiredPackage 在执行 updateCarrierSuspendedStatus 后,若载体确认无生效套餐,异步调用 StopResumeCallback.CheckAndStopCard(iot_card 类型)或遍历绑定卡逐一触发(device 类型)。
幂等保护:CheckAndStopCard 已有"卡已停机则跳过"逻辑,重复触发安全。
与 carddata 轮询的关系:此处主动触发为优化项(消除延迟窗口),carddata 轮询的 checkStopResume 仍作为兜底保障,两者共存不冲突。
Scenario: 主套餐过期且无后续套餐,载体为 iot_card
- WHEN
HandlePackageActivationCheck检测到一张卡的主套餐已过期(expires_at <= NOW),执行processExpiredPackage后确认该卡无待生效或生效中的套餐 - THEN 系统异步调用
CheckAndStopCard(cardID),将卡停机(network_status = 0,stop_reason = "traffic_exhausted"),不等待网关响应
Scenario: 主套餐过期且无后续套餐,载体为 device
- WHEN
HandlePackageActivationCheck检测到一个设备的主套餐已过期,确认该设备无后续套餐 - THEN 系统查询设备绑定的所有在线已实名卡,逐一异步触发
CheckAndStopCard
Scenario: 主套餐过期但有排队待生效套餐
- WHEN
processExpiredPackage处理过期套餐,activateNextPackage成功激活了下一个待生效套餐 - THEN 系统不触发停机(因有生效套餐),
updateCarrierSuspendedStatus检查后确认有生效套餐即返回
Scenario: carddata 轮询兜底仍有效
- WHEN 套餐过期主动停机的异步触发因 gateway 异常失败,卡仍处于在线状态
- THEN 下一次
HandleCarddataCheck的checkStopResume检测到在线无套餐,再次尝试停机(兜底保障)