This commit is contained in:
@@ -20,6 +20,8 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const cardTrafficSyncLockTTL = 10 * time.Minute
|
||||
|
||||
// PollingCallback 轮询回调接口
|
||||
// 用于在卡生命周期事件发生时通知轮询调度器
|
||||
type PollingCallback interface {
|
||||
@@ -135,6 +137,24 @@ func (s *Service) SetRedisClient(redisClient *redis.Client) {
|
||||
s.redis = redisClient
|
||||
}
|
||||
|
||||
// acquireCardTrafficSyncLock 获取卡流量同步锁,避免主动刷新与轮询重复统计同一上游读数。
|
||||
func (s *Service) acquireCardTrafficSyncLock(ctx context.Context, cardID uint) (bool, error) {
|
||||
if s.redis == nil {
|
||||
return true, nil
|
||||
}
|
||||
return s.redis.SetNX(ctx, constants.RedisCardTrafficSyncLockKey(cardID), "1", cardTrafficSyncLockTTL).Result()
|
||||
}
|
||||
|
||||
// releaseCardTrafficSyncLock 释放卡流量同步锁。
|
||||
func (s *Service) releaseCardTrafficSyncLock(ctx context.Context, cardID uint) {
|
||||
if s.redis == nil {
|
||||
return
|
||||
}
|
||||
if err := s.redis.Del(ctx, constants.RedisCardTrafficSyncLockKey(cardID)).Err(); err != nil {
|
||||
s.logger.Warn("释放卡流量同步锁失败", zap.Uint("card_id", cardID), zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) ListStandalone(ctx context.Context, req *dto.ListStandaloneIotCardRequest) (*dto.ListStandaloneIotCardResponse, error) {
|
||||
page := req.Page
|
||||
pageSize := req.PageSize
|
||||
@@ -1418,6 +1438,20 @@ func (s *Service) RefreshCardDataFromGateway(ctx context.Context, iccid string)
|
||||
return err
|
||||
}
|
||||
|
||||
locked, lockErr := s.acquireCardTrafficSyncLock(ctx, card.ID)
|
||||
if lockErr != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, lockErr, "获取卡流量同步锁失败")
|
||||
} else if !locked {
|
||||
return errors.New(errors.CodeTooManyRequests, "卡流量正在同步,请稍后重试")
|
||||
} else {
|
||||
defer s.releaseCardTrafficSyncLock(ctx, card.ID)
|
||||
latestCard, loadErr := s.iotCardStore.GetByID(ctx, card.ID)
|
||||
if loadErr != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, loadErr, "刷新卡数据失败")
|
||||
}
|
||||
card = latestCard
|
||||
}
|
||||
|
||||
syncTime := time.Now()
|
||||
updates := map[string]any{
|
||||
"last_sync_time": syncTime,
|
||||
|
||||
Reference in New Issue
Block a user