fix: 停复机指令队列审查问题
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m24s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m24s
- 开关开启但分发器心跳缺失时回退为当场执行,避免指令无人消费 - 待确认指令先查上游状态再判断;执行期间被覆盖时把待确认带到新指令 - 同方向失败退避中重复写入不提前执行时间 - 领取容量把执行上限与本秒剩余 QPS 分开计算 - 队列复机共用单卡复机锁;执行上下文取消后按结果未知确认 - 消费者并行停止;读取最近调用时间失败时不覆盖;成功但终结日志失败按成功处理 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -238,7 +238,11 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateCarrierReq
|
||||
func (s *Service) requestRealnameControlEvaluation(ctx context.Context, carrierID uint, enabled bool) {
|
||||
evalCtx := context.WithoutCancel(ctx)
|
||||
go func() {
|
||||
defer func() { _ = recover() }()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
s.logger.Error("实名管控修改后批量请求停复机评估 panic", zap.Uint("carrier_id", carrierID), zap.Any("panic", r))
|
||||
}
|
||||
}()
|
||||
if _, err := s.realnameEvaluator.RequestRealnameControlEvaluation(evalCtx, carrierID, enabled); err != nil {
|
||||
s.logger.Error("实名管控修改后批量请求停复机评估失败", zap.Uint("carrier_id", carrierID), zap.Error(err))
|
||||
}
|
||||
|
||||
@@ -52,6 +52,9 @@ func (s *StopResumeService) DecideCommand(ctx context.Context, cardID uint, scen
|
||||
return CommandDecision{Card: card, Action: decision.Action, Reason: decision.Reason}, nil
|
||||
}
|
||||
|
||||
// ErrCommandBusy 表示该卡复机正在其他路径执行(持单卡复机锁),本次未调用上游。
|
||||
var ErrCommandBusy = stderrors.New("该卡复机正在执行中")
|
||||
|
||||
// CommandCallResult 是一次停复机网关调用的结果。
|
||||
type CommandCallResult struct {
|
||||
// Unknown 为 true 表示结果未知:超时、连接失败,或上游已成功但本地回写失败。
|
||||
@@ -66,8 +69,22 @@ func (s *StopResumeService) ExecuteCommand(ctx context.Context, card *model.IotC
|
||||
}
|
||||
if action == constants.StopResumeActionStop {
|
||||
outcome, err := s.stopCardAttempts(ctx, card, reason, 1)
|
||||
if err != nil && outcome.Result == constants.AuditResultSuccess {
|
||||
// 停机与回写已成功,只是 Integration Log 终结失败:按成功处理。
|
||||
s.logger.Warn("停机成功但终结 Integration Log 失败", zap.Uint("card_id", card.ID), zap.Error(err))
|
||||
return CommandCallResult{}, nil
|
||||
}
|
||||
return CommandCallResult{Unknown: err != nil && outcome.Result == constants.AuditResultUnknown && !gateway.IsRateLimited(err)}, err
|
||||
}
|
||||
// 与旧复机路径共用单卡复机锁,避免与自动续费、通道阈值等直接复机并发。
|
||||
if s.redis != nil {
|
||||
lockKey := constants.RedisCardResumeLockKey(card.ID)
|
||||
locked, lockErr := s.redis.SetNX(ctx, lockKey, "1", 30*time.Second).Result()
|
||||
if lockErr != nil || !locked {
|
||||
return CommandCallResult{}, ErrCommandBusy
|
||||
}
|
||||
defer s.redis.Del(context.WithoutCancel(ctx), lockKey)
|
||||
}
|
||||
actionCode, summary := constants.AuditActionIotCardAutoStarted, "自动恢复 IoT 卡网络"
|
||||
attempt, integrationID, err := s.resumeCardAttempts(ctx, card, actionCode, summary, 1)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package iot_card
|
||||
|
||||
import (
|
||||
"context"
|
||||
stderrors "errors"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
@@ -62,11 +63,15 @@ func (s *StopResumeService) legacyAssetEvaluation(ctx context.Context, assetType
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var failed []error
|
||||
for _, card := range cards {
|
||||
if err := s.EvaluateAndAct(ctx, card); err != nil {
|
||||
return err
|
||||
failed = append(failed, err)
|
||||
}
|
||||
}
|
||||
if len(failed) > 0 {
|
||||
return errors.Wrap(errors.CodeInternalError, stderrors.Join(failed...), "设备停复机评估存在未成功处理的卡")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
card, err := s.iotCardStore.GetByID(ctx, assetID)
|
||||
|
||||
Reference in New Issue
Block a user