feat(通道流量阈值): AUG26-011 运营商通道流量阈值达量停机与周期复机
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 12m59s

This commit is contained in:
2026-09-16 15:54:49 +08:00
parent 41722760b1
commit 59b3df868a
36 changed files with 2431 additions and 93 deletions

View File

@@ -0,0 +1,70 @@
// Package carrierthreshold 提供运营商通道流量阈值的停复机执行适配与计划任务处理。
//
// 本包只做两件事:把通道阈值的执行需求转发到既有停复机服务(不新增任何网关调用层实现、
// 不复制既有判定规则),以及把两个计划任务入口转换成对通道阈值用例的调用。
package carrierthreshold
import (
"context"
carrierthresholdapp "github.com/break/junhong_cmp_fiber/internal/application/carrierthreshold"
carrierthresholddomain "github.com/break/junhong_cmp_fiber/internal/domain/carrierthreshold"
iotcardsvc "github.com/break/junhong_cmp_fiber/internal/service/iot_card"
"github.com/break/junhong_cmp_fiber/pkg/errors"
)
// CardCommander 把通道阈值的停复机执行需求转发到既有停复机服务。
//
// 复用点:停机/复机的 3 次重试、Integration Log、统一审计、卡状态观测序列以及有效主套餐、
// 流量耗尽、实名、风险网关扩展等判定;本适配器不包含任何业务规则。
type CardCommander struct {
service *iotcardsvc.StopResumeService
}
// 编译期断言:适配器满足通道阈值停复机执行端口。
var _ carrierthresholdapp.CardCommander = (*CardCommander)(nil)
// NewCardCommander 创建通道阈值停复机执行适配器。
func NewCardCommander(service *iotcardsvc.StopResumeService) *CardCommander {
return &CardCommander{service: service}
}
// StopCardForThreshold 执行通道阈值达量停机。
func (c *CardCommander) StopCardForThreshold(ctx context.Context, cardID uint) (carrierthresholddomain.CommandOutcome, error) {
if c == nil || c.service == nil {
return carrierthresholddomain.CommandOutcome{}, errors.New(errors.CodeServiceUnavailable, "通道流量阈值停机执行能力未配置")
}
return c.service.StopCardForChannelThreshold(ctx, cardID)
}
// ResumeCardForThreshold 执行通道阈值新周期复机。
func (c *CardCommander) ResumeCardForThreshold(ctx context.Context, cardID uint) (carrierthresholddomain.CommandOutcome, error) {
if c == nil || c.service == nil {
return carrierthresholddomain.CommandOutcome{}, errors.New(errors.CodeServiceUnavailable, "通道流量阈值复机执行能力未配置")
}
return c.service.ResumeCardForChannelThreshold(ctx, cardID)
}
// ResumeReady 判断解锁后的卡是否满足自动复机条件。
func (c *CardCommander) ResumeReady(ctx context.Context, cardID uint) (bool, string, error) {
if c == nil || c.service == nil {
return false, "", errors.New(errors.CodeServiceUnavailable, "通道流量阈值复机判定能力未配置")
}
return c.service.ChannelThresholdResumeReady(ctx, cardID)
}
// CardNetworkStatus 只查询运营商卡状态并映射为本地网络状态。
func (c *CardCommander) CardNetworkStatus(ctx context.Context, cardID uint) (int, bool, string, error) {
if c == nil || c.service == nil {
return 0, false, "", errors.New(errors.CodeServiceUnavailable, "通道流量阈值状态查询能力未配置")
}
return c.service.QueryChannelThresholdCardStatus(ctx, cardID)
}
// ConfirmCardState 按已确认的运营商结果补写卡状态。
func (c *CardCommander) ConfirmCardState(ctx context.Context, cardID uint, offline bool) error {
if c == nil || c.service == nil {
return errors.New(errors.CodeServiceUnavailable, "通道流量阈值卡状态确认能力未配置")
}
return c.service.ConfirmChannelThresholdCardState(ctx, cardID, offline)
}

View File

@@ -0,0 +1,68 @@
package carrierthreshold
import (
"context"
"time"
"github.com/hibiken/asynq"
carrierthresholdapp "github.com/break/junhong_cmp_fiber/internal/application/carrierthreshold"
"github.com/break/junhong_cmp_fiber/pkg/auditcontext"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
)
// CycleTaskHandler 执行运营商通道流量阈值周期处理任务。
type CycleTaskHandler struct {
service *carrierthresholdapp.Service
}
// NewCycleTaskHandler 创建通道阈值周期处理任务 Handler。
func NewCycleTaskHandler(service *carrierthresholdapp.Service) *CycleTaskHandler {
return &CycleTaskHandler{service: service}
}
// Handle 扫描已跨期的持锁,认领解锁并在条件满足时写复机事件。
// 审计上下文固定为计划任务来源,使解锁与复机事件都可按计划任务维度追溯。
func (h *CycleTaskHandler) Handle(ctx context.Context, task *asynq.Task) error {
if h == nil || h.service == nil {
return errors.New(errors.CodeServiceUnavailable, "通道流量阈值周期处理任务未配置")
}
taskType := constants.TaskTypeCarrierThresholdCycle
if task != nil && task.Type() != "" {
taskType = task.Type()
}
ctx = auditcontext.With(ctx, auditcontext.Context{
ActorKind: constants.AuditActorScheduledJob, ActorID: taskType,
ActorName: "运营商通道流量阈值周期处理计划任务", Source: constants.AuditSourceScheduler,
})
_, err := h.service.ProcessDueLocks(ctx, time.Now().UTC())
return err
}
// RecoveryTaskHandler 执行运营商通道流量阈值停复机结果恢复任务。
type RecoveryTaskHandler struct {
service *carrierthresholdapp.Service
}
// NewRecoveryTaskHandler 创建通道阈值停复机结果恢复任务 Handler。
func NewRecoveryTaskHandler(service *carrierthresholdapp.Service) *RecoveryTaskHandler {
return &RecoveryTaskHandler{service: service}
}
// Handle 扫描已提交的停复机子任务并只查询运营商状态回填,绝不重复发起停复机。
func (h *RecoveryTaskHandler) Handle(ctx context.Context, task *asynq.Task) error {
if h == nil || h.service == nil {
return errors.New(errors.CodeServiceUnavailable, "通道流量阈值恢复扫描任务未配置")
}
taskType := constants.TaskTypeCarrierThresholdRecovery
if task != nil && task.Type() != "" {
taskType = task.Type()
}
ctx = auditcontext.With(ctx, auditcontext.Context{
ActorKind: constants.AuditActorScheduledJob, ActorID: taskType,
ActorName: "运营商通道流量阈值结果恢复计划任务", Source: constants.AuditSourceScheduler,
})
_, err := h.service.RecoverSubmitted(ctx, time.Now().UTC())
return err
}