Files
junhong_cmp_fiber/openspec/changes/add-carrier-channel-traffic-thresholds/tasks.md
break ef4d3696d4
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
fix(通道流量阈值): AUG26-011 修复周期处理连接池自锁并补齐根池句柄验证与文档
2026-09-16 16:59:32 +08:00

41 lines
6.8 KiB
Markdown
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.
## 1. 迁移与模型
- [x] 1.1 成对迁移:`tb_carrier` 扩列 `traffic_threshold_enabled`(默认 false`traffic_threshold_value`(正数 numeric`traffic_threshold_unit`MB/GB新增周期阈值停机锁表`(carrier_id, card_id, period_start)` 唯一键软删感知、任务状态组stop/resumepending/submitted/confirmed/failed/unknown、提交认领字段`stop_submitted_at`/`resume_submitted_at`)、`anomaly_flag``failure_reason`
- [x] 1.2 锁表模型与 Store含唯一键冲突 23505 识别、条件更新认领方法)。
## 2. 阈值配置与权限
- [x] 2.1 carrier 创建/更新 DTO 增阈值字段与校验(正数、单位 MB/GB、周期复用 `data_reset_day`)。
- [x] 2.2 字段级平台守卫Create/Update 仅 SuperAdmin/Platform 可写阈值字段非平台提交即拒绝List/Get 对非平台账号不返回阈值字段;不改 carrier 其余字段既有可见性。
- [x] 2.3 阈值新增、修改、启用、停用并入既有 carrier 更新审计前后值快照;同步 `cmd/gendocs` 文档。
## 3. 达量判定
- [x] 3.1 period_start 计算(显式 Asia/ShanghairesetDay 取卡 carrier 的 `data_reset_day`)与 GB→MB 换算常量1 GB = 1024 MB
- [x] 3.2 `ApplyTrafficObservation` 事务内达量判定:`ReadingAccepted == true` 且 carrier 阈值启用时,以 `last_gateway_reading_mb` 换算比较;达量写锁 + 停机 Outbox 事件同事务。
- [x] 3.3 锁唯一键 23505 单独捕获为「该周期已处理」跳过,与流量基线 CAS 冲突分离。
## 4. 可靠停复机消费者
- [x] 4.1 停机消费者:提交认领(`stop_submitted_at IS NULL` 条件更新);卡已 offline 跳过 Gateway 直接确认;否则复用 `stopCardWithRetry`;成功后写 `network_status=offline``stop_reason=channel_threshold``stopped_at`;失败/未知保留锁与任务状态unknown 的 Integration Log 必带 RecoveryStrategy。
- [x] 4.2 复机消费者:结构同停机(`resume_submitted_at` 认领、复用 `resumeCardWithRetry`、成功后写 online/清停因/resumed_at新增 2 个 Outbox 事件类型与 worker 消费者注册、装配。
## 5. 周期处理与恢复 cron
- [x] 5.1 周期处理 cron`@every 1m` + `asynq.Unique(10m)` + 无 payload扫描 period_start 过期持锁锁行(按锁行自身 carrier 的 `data_reset_day` 判断),条件更新认领解锁,逐卡评估(有效主套餐 + 流量未耗尽 + 实名 OK + 非风险 extend + 无其他停因),全满足写复机事件,否则只解锁。
- [x] 5.2 恢复扫描 cron同形态扫描未决子任务`domain.UnresolvedTaskStatuses()` = `{submitted, unknown, failed}`,见 8.1)的锁,只查询网关状态回填、绝不重复发起停复机;确认成功补写卡状态;自提交起超 30 分钟(常量)仍不可查 → `anomaly_flag` + 安全失败原因转人工,不自动删除锁。
- [x] 5.3 worker 注册两个 cron 与装配;周期处理与恢复 Handler 审计上下文固定 `ActorKind=AuditActorScheduledJob``Source=AuditSourceScheduler`
## 6. 停因与复机拒绝
- [x] 6.1 新增 `StopReasonChannelThreshold = "channel_threshold"` 常量;确认不纳入 `isPollingStopReason``isDeviceScopeReason`
- [x] 6.2 持锁拒绝覆盖四个入口(`resumeSingleCard``ManualStartCard``ForceStartCard``StartMachineSeparatedCard`):拒绝 + 审计 denied + 锁保留。
## 7. 验证
- [x] 7.1 隔离库验证:平台配置阈值(含 GB 换算)成功 + 审计前后值,代理/企业写被拒且读不到字段;达量触发停机、同周期重复判定唯一冲突不重复锁/不重复停机;持锁期四入口复机拒绝且锁保留;停机 unknown 保留 + RecoveryStrategy + 恢复扫描确认补写卡状态、超期 anomaly 转人工新周期解锁、条件满足才复机、其他停因stop_reason 非空非本停因或风险 extend只解锁停用后新卡不再锁、已持锁卡新周期照常解锁复机换运营商旧锁保留、新周期按新 carrier 重置日;第 12 项套餐预警与既有 3 种停因停复机回归不变;迁移 up/down/up。
- [x] 7.2 运行 `gofmt -w``go build ./cmd/api ./cmd/worker``go run cmd/gendocs/main.go``openspec validate add-carrier-channel-traffic-thresholds --strict``openspec doctor --json`;自动化测试按项目决策为 N/A。
## 8. 审查修复
- [x] 8.1B1停机/复机调用明确失败或结果未知的子任务不退出恢复扫描:扫描谓词与超期判定改用未决集合 `{submitted, unknown, failed}``markTaskConfirmed` 的 expected 改为未决集合confirmed 仍只写一次、部分索引谓词同步为未决集合000227已确认生产库未应用
- [x] 8.2B2锁行引用的运营商缺失或 `data_reset_day` 非法时给出出路:周期处理按跨期语义认领解锁并同事务标记 `anomaly_flag=1` + 安全原因 + Warn 日志转人工,不写复机事件、不调运营商、不静默跳过;`ActiveLock` 维持配置缺失时不放开复机的 fail-closed 语义。
- [x] 8.3R1恢复 `stopCardWithRetry`/`resumeCardWithRetry` 在 Integration Log 写入失败分支的「未完成」审计,保持既有审计覆盖与返回语义不变。
- [x] 8.4R2按 ENG-AUDIT-001 显式登记锁行状态迁移(`unlocked``anomaly_flag=1`)的审计决定(不新建独立审计动作 + 承载方式),并在 design.md 补「审计决定」小节。
- [x] 8.5R4`specs/package-lifecycle/spec.md` MODIFIED delta 建模「持通道阈值锁时拒绝复机」对既有套餐生命周期自动复机路径的行为变更,并更新 proposal 的 Modified Capabilities。
- [x] 8.6 修正 design.md 与实现不符的表述(失败/未知与不可判定 carrier 的收敛路径、四入口拒绝顺序与返回、认领谓词)。
- [x] 8.7 回归验证B1unknown/failed 扫描与收敛、超期 anomaly与 B2carrier 缺失/重置日非法的解锁与异常)**用生产等价句柄Service.s.db 为根连接池)实测**——fixture 以已提交短事务创建、逐条断言后删除并核对 0 残留回滚事务式写法会掩蔽连接池自锁不再用于这两条路径R1审计写入用回滚事务实测gofmt/go build/go vet/openspec validate --strict/context-health 全通过。
- [x] 8.8B3修复连接池自锁新增事务句柄版 `markAnomalyInTx``markAnomaly` 以自身连接池委托同一实现),`processUnresolvableLock` 在事务闭包内用 `tx` 标记异常,使解锁与 anomaly 同事务提交(否则解锁已持行锁、另一条连接上的 anomaly 更新会等待该行锁直到语句超时,表现为不可判定锁行停在 locked 且周期处理 cron 每分钟空转);并完成同类自锁全面排查(结论:本 Change 仅此一处)。