72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
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
|
|
}
|