fix: 流量触发限速后主动清除节点用户缓存

节点用户列表缓存(server:user:{id})永不过期,用户流量超限触发按量限速后
缓存中仍是旧的速度值,节点不会感知限速状态。

修复:每次写入 traffic_log 后,检查该订阅是否触发按量限速规则,
若 IsThrottled=true 则立即删除对应节点的用户列表缓存,
节点下次拉取时重新计算并应用降速后的 speed_limit。

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
shanshanzhong 2026-03-28 18:36:13 -07:00
parent 0f28f4995f
commit 1a08949c80

View File

@ -3,11 +3,13 @@ package traffic
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/perfect-panel/server/internal/model/node"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/speedlimit"
"github.com/hibiken/asynq"
"github.com/perfect-panel/server/internal/model/traffic"
@ -126,6 +128,21 @@ func (l *TrafficStatisticsLogic) ProcessTask(ctx context.Context, task *asynq.Ta
logger.Field("error", err.Error()),
)
}
// 写完流量后检查是否触发按量限速,若触发则清除节点缓存使限速立即生效
if planSub, planErr := l.svc.SubscribeModel.FindOne(ctx, sub.SubscribeId); planErr == nil &&
(planSub.SpeedLimit > 0 || planSub.TrafficLimit != "") {
throttle := speedlimit.Calculate(ctx, l.svc.DB, sub.UserId, sub.Id, planSub.SpeedLimit, planSub.TrafficLimit)
if throttle.IsThrottled {
cacheKey := fmt.Sprintf("%s%d", node.ServerUserListCacheKey, payload.ServerId)
if delErr := l.svc.Redis.Del(ctx, cacheKey).Err(); delErr != nil {
logger.WithContext(ctx).Error("[TrafficStatistics] Clear server user cache failed",
logger.Field("serverId", payload.ServerId),
logger.Field("error", delErr.Error()),
)
}
}
}
}
return nil
}