package logic import ( "context" "encoding/json" "time" "bj_power_mes/internal/svc" ) // Service 业务逻辑服务(handler 薄层调用) type Service struct { ctx *svc.ServiceContext } func New(s *svc.ServiceContext) *Service { return &Service{ctx: s} } // cached 看板缓存:TTL + 防击穿(SETNX 锁),同一 key 同时仅一个打到 DB func (s *Service) cached(ctx context.Context, key string, ttl int, build func() (any, error)) (any, error) { if s.ctx.RedisClient == nil { return build() } if v, err := s.ctx.RedisClient.Get(key); err == nil && v != "" { var out any if json.Unmarshal([]byte(v), &out) == nil { return out, nil } } lockKey := key + ":lock" ok, _ := s.ctx.RedisClient.SetnxEx(lockKey, "1", 10) if !ok { // 有人正在重建缓存:短暂等待后重读 for i := 0; i < 10; i++ { time.Sleep(100 * time.Millisecond) if v, err := s.ctx.RedisClient.Get(key); err == nil && v != "" { var out any if json.Unmarshal([]byte(v), &out) == nil { return out, nil } } } return build() } defer func() { _, _ = s.ctx.RedisClient.Del(lockKey) }() data, err := build() if err == nil { if b, e := json.Marshal(data); e == nil { _ = s.ctx.RedisClient.Setex(key, string(b), ttl) } } return data, err }