feat: PollingRealnameHandler 新增设备级套餐实名激活联动
- 结构体新增 deviceSimBindingStore 字段,构造函数参数列表末尾追加 - 新增 triggerDeviceRealnameActivation:卡首次实名(0→1)时查询所属设备, 若有绑定则提交 carrier_type=device 的 TaskTypePackageFirstActivation 任务 - 独立卡(无绑定设备)静默跳过,任务提交失败仅记录 Warn 日志不阻断流程 - registerPollingHandlers 传入 h.workerResult.Stores.DeviceSimBinding - 修复「购买后某张卡实名」场景下设备级套餐永不激活的缺陷 Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -18,11 +18,12 @@ import (
|
||||
// 职责:调 Gateway 查实名状态 → 写 DB → 触发首次实名激活任务
|
||||
// 不做:停复机决策(实名状态 0→1 时通过 EvaluateAndAct 触发 not_realname 复机)
|
||||
type PollingRealnameHandler struct {
|
||||
base *PollingBase
|
||||
gateway *gateway.Client
|
||||
iotCardStore *postgres.IotCardStore
|
||||
asynqClient *asynq.Client
|
||||
stopResumeSvc iot_card_svc.StopResumeServiceInterface
|
||||
base *PollingBase
|
||||
gateway *gateway.Client
|
||||
iotCardStore *postgres.IotCardStore
|
||||
asynqClient *asynq.Client
|
||||
stopResumeSvc iot_card_svc.StopResumeServiceInterface
|
||||
deviceSimBindingStore *postgres.DeviceSimBindingStore
|
||||
}
|
||||
|
||||
// NewPollingRealnameHandler 创建实名检查任务处理器
|
||||
@@ -32,13 +33,15 @@ func NewPollingRealnameHandler(
|
||||
iotCardStore *postgres.IotCardStore,
|
||||
asynqClient *asynq.Client,
|
||||
stopResumeSvc iot_card_svc.StopResumeServiceInterface,
|
||||
deviceSimBindingStore *postgres.DeviceSimBindingStore,
|
||||
) *PollingRealnameHandler {
|
||||
return &PollingRealnameHandler{
|
||||
base: base,
|
||||
gateway: gw,
|
||||
iotCardStore: iotCardStore,
|
||||
asynqClient: asynqClient,
|
||||
stopResumeSvc: stopResumeSvc,
|
||||
base: base,
|
||||
gateway: gw,
|
||||
iotCardStore: iotCardStore,
|
||||
asynqClient: asynqClient,
|
||||
stopResumeSvc: stopResumeSvc,
|
||||
deviceSimBindingStore: deviceSimBindingStore,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +141,7 @@ func (h *PollingRealnameHandler) Handle(ctx context.Context, t *asynq.Task) erro
|
||||
if isFirstRealname {
|
||||
// 0→1:首次实名,触发套餐激活并立即复机评估(不等待下一个 carddata/package 周期)
|
||||
h.triggerFirstRealnameActivation(ctx, cardID)
|
||||
h.triggerDeviceRealnameActivation(ctx, cardID)
|
||||
if h.stopResumeSvc != nil {
|
||||
freshCard, loadErr := h.iotCardStore.GetByID(ctx, cardID)
|
||||
if loadErr == nil {
|
||||
@@ -192,3 +196,42 @@ func (h *PollingRealnameHandler) triggerFirstRealnameActivation(ctx context.Cont
|
||||
h.base.logger.Warn("提交首次实名激活任务失败", zap.Uint("card_id", cardID), zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
// triggerDeviceRealnameActivation 卡首次实名后,触发其所属设备的设备级套餐激活任务
|
||||
// 若卡不属于任何设备(独立卡),静默跳过
|
||||
func (h *PollingRealnameHandler) triggerDeviceRealnameActivation(ctx context.Context, cardID uint) {
|
||||
if h.asynqClient == nil || h.deviceSimBindingStore == nil {
|
||||
return
|
||||
}
|
||||
binding, err := h.deviceSimBindingStore.GetActiveBindingByCardID(ctx, cardID)
|
||||
if err != nil {
|
||||
if isNotFound(err) {
|
||||
return
|
||||
}
|
||||
h.base.logger.Warn("查询卡绑定设备失败,跳过设备级套餐激活",
|
||||
zap.Uint("card_id", cardID), zap.Error(err))
|
||||
return
|
||||
}
|
||||
deviceID := binding.DeviceID
|
||||
payload := map[string]any{
|
||||
"carrier_type": "device",
|
||||
"carrier_id": deviceID,
|
||||
"activation_type": "realname",
|
||||
"timestamp": time.Now().Unix(),
|
||||
}
|
||||
payloadBytes, err := sonic.Marshal(payload)
|
||||
if err != nil {
|
||||
h.base.logger.Warn("序列化设备实名激活任务载荷失败",
|
||||
zap.Uint("card_id", cardID), zap.Uint("device_id", deviceID), zap.Error(err))
|
||||
return
|
||||
}
|
||||
task := asynq.NewTask(constants.TaskTypePackageFirstActivation, payloadBytes,
|
||||
asynq.MaxRetry(3),
|
||||
asynq.Timeout(30*time.Second),
|
||||
asynq.Queue(constants.QueueDefault),
|
||||
)
|
||||
if _, err := h.asynqClient.EnqueueContext(ctx, task); err != nil {
|
||||
h.base.logger.Warn("提交设备实名激活任务失败",
|
||||
zap.Uint("card_id", cardID), zap.Uint("device_id", deviceID), zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ func (h *Handler) registerCommissionCalculationHandler() {
|
||||
func (h *Handler) registerPollingHandlers() {
|
||||
realnameHandler := task.NewPollingRealnameHandler(
|
||||
h.pollingBase, h.gatewayClient, h.workerResult.Stores.IotCard,
|
||||
h.asynqClient, h.pollingStopResumeSvc)
|
||||
h.asynqClient, h.pollingStopResumeSvc, h.workerResult.Stores.DeviceSimBinding)
|
||||
carrierStore := postgres.NewCarrierStore(h.db)
|
||||
carddataHandler := task.NewPollingCarddataHandler(
|
||||
h.pollingBase, h.gatewayClient, h.workerResult.Stores.IotCard,
|
||||
|
||||
Reference in New Issue
Block a user