package task import ( "context" "time" "github.com/hibiken/asynq" "go.uber.org/zap" iot_card_svc "github.com/break/junhong_cmp_fiber/internal/service/iot_card" "github.com/break/junhong_cmp_fiber/internal/store/postgres" "github.com/break/junhong_cmp_fiber/pkg/constants" ) // PollingPackageHandler 套餐检查任务处理器 // 职责:触发 EvaluateAndAct 检查套餐状态并判断停复机 // 不做:直接停复机决策,委托给 StopResumeService.EvaluateAndAct // 注:套餐状态由 PackageActivationHandler/DataResetHandler/UsageService 维护, // 本 Handler 无需查 Gateway,只负责周期性触发再评估。 type PollingPackageHandler struct { base *PollingBase iotCardStore *postgres.IotCardStore stopResumeSvc iot_card_svc.StopResumeServiceInterface } // NewPollingPackageHandler 创建套餐检查任务处理器 func NewPollingPackageHandler( base *PollingBase, iotCardStore *postgres.IotCardStore, stopResumeSvc iot_card_svc.StopResumeServiceInterface, ) *PollingPackageHandler { return &PollingPackageHandler{ base: base, iotCardStore: iotCardStore, stopResumeSvc: stopResumeSvc, } } // Handle 处理套餐检查任务 func (h *PollingPackageHandler) Handle(ctx context.Context, t *asynq.Task) error { startTime := time.Now() cardID, ok := parseTaskPayload(t.Payload(), h.base.logger) if !ok { return nil } if !h.base.acquireConcurrency(ctx, constants.TaskTypePollingPackage) { h.base.logger.Debug("并发已满,重新入队", zap.Uint("card_id", cardID)) return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingPackage) } defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingPackage) if _, cacheErr := h.base.getCardWithCache(ctx, cardID); cacheErr != nil { if isNotFound(cacheErr) { return nil } h.base.logger.Error("获取卡信息失败", zap.Uint("card_id", cardID), zap.Error(cacheErr)) h.base.updateStats(ctx, constants.TaskTypePollingPackage, false, time.Since(startTime)) return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingPackage) } if h.stopResumeSvc != nil { freshCard, loadErr := h.iotCardStore.GetByID(ctx, cardID) if loadErr == nil { h.base.logger.Info("套餐检查:执行停复机评估", zap.Uint("card_id", cardID), zap.Int("network_status", freshCard.NetworkStatus), zap.String("stop_reason", freshCard.StopReason)) if h.base.verboseLog { h.base.logger.Info("套餐检查详情", zap.Uint("card_id", cardID), zap.String("iccid", freshCard.ICCID), zap.Int("network_status", freshCard.NetworkStatus), zap.String("stop_reason", freshCard.StopReason)) } if evalErr := h.stopResumeSvc.EvaluateAndAct(ctx, freshCard); evalErr != nil { h.base.logger.Warn("套餐检查后停复机评估失败", zap.Uint("card_id", cardID), zap.Error(evalErr)) } } else { h.base.logger.Warn("套餐检查:加载卡信息失败", zap.Uint("card_id", cardID), zap.Error(loadErr)) } } h.base.updateStats(ctx, constants.TaskTypePollingPackage, true, time.Since(startTime)) return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingPackage) }