package service import ( "context" "encoding" "errors" "github.com/redis/go-redis/v9" "sync" "time" "git.urec56.ru/urec/chat_back_go/internal/domain" "git.urec56.ru/urec/chat_back_go/internal/logger" ) type cacheService struct { l *logger.Logger r redis.UniversalClient storage *sync.Map } type userCache struct { u []byte // domain.User expiresAt time.Time } func newCacheService(r redis.UniversalClient, l *logger.Logger) *cacheService { return &cacheService{r: r, l: l, storage: &sync.Map{}} } func (c *cacheService) Get(key string, v encoding.BinaryUnmarshaler, isFast bool) error { return c.GetCtx(context.Background(), key, v, isFast) } func (c *cacheService) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler, isFast bool) error { if isFast { item, ok := c.storage.Load(key) if ok { if userData, ok := item.(userCache); ok && userData.expiresAt.After(time.Now()) { err := v.UnmarshalBinary(userData.u) return err } } } err := c.r.Get(ctx, key).Scan(v) if err != nil { if errors.Is(err, redis.Nil) { return domain.NoKeyFoundError } c.l.Errorf("getting key %s: %s", key, err) return domain.InternalServerError } return nil } func (c *cacheService) Set(key string, v encoding.BinaryMarshaler, ex time.Duration) error { return c.SetCtx(context.Background(), key, v, ex) } func (c *cacheService) SetCtx(ctx context.Context, key string, v encoding.BinaryMarshaler, ex time.Duration) error { if err := c.r.SetEx(ctx, key, v, ex).Err(); err != nil { return err } data, err := v.MarshalBinary() if err != nil { return err } c.storage.Store(key, userCache{u: data, expiresAt: time.Now().Add(time.Minute)}) return nil }