145 lines
3.1 KiB
Go
145 lines
3.1 KiB
Go
package cache
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
redis "gopkg.in/redis.v5"
|
|
|
|
"time"
|
|
|
|
"sync"
|
|
|
|
"bitbucket.org/nemt/nemt-portal-api/domain"
|
|
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
|
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
|
)
|
|
|
|
var (
|
|
instance *RedisCache
|
|
once sync.Once
|
|
)
|
|
|
|
// RedisCache implements the CacheManager interface
|
|
type RedisCache struct {
|
|
cfg *config.Config
|
|
redis *redis.Client
|
|
}
|
|
|
|
// Instance returns a CacheManager instance
|
|
func Instance(cfg *config.Config) contract.CacheManager {
|
|
once.Do(func() {
|
|
client := redis.NewFailoverClient(&redis.FailoverOptions{
|
|
MasterName: "master01",
|
|
SentinelAddrs: []string{fmt.Sprintf("%s:%v", cfg.Cache.Server, cfg.Cache.Port)},
|
|
Password: cfg.Cache.Pass,
|
|
DB: cfg.Cache.DB,
|
|
})
|
|
|
|
instance = &RedisCache{cfg, client}
|
|
})
|
|
|
|
return instance
|
|
}
|
|
|
|
func (r *RedisCache) buildKey(key string) string {
|
|
return fmt.Sprintf("%s-%s", r.cfg.Cache.Prefix, key)
|
|
}
|
|
|
|
// GetItem returns an Item from cache
|
|
func (r *RedisCache) GetItem(key string) (data []byte, err error) {
|
|
val, err := r.redis.Get(r.buildKey(key)).Bytes()
|
|
if err == redis.Nil {
|
|
return val, domain.ErrCacheMiss
|
|
} else if err != nil {
|
|
return val, errors.Wrap(err)
|
|
}
|
|
|
|
return val, nil
|
|
}
|
|
|
|
// SetItem sets an item in cache
|
|
func (r *RedisCache) SetItem(key string, data []byte) error {
|
|
err := r.redis.Set(r.buildKey(key), data, r.cfg.Cache.DefaultExpiration).Err()
|
|
if err != nil {
|
|
return errors.Wrap(err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetString returns an string from cache
|
|
func (r *RedisCache) GetString(key string) (data string, err error) {
|
|
val, err := r.GetItem(key)
|
|
if err == domain.ErrCacheMiss {
|
|
return data, domain.ErrCacheMiss
|
|
} else if err != nil {
|
|
return data, errors.Wrap(err)
|
|
}
|
|
|
|
return string(val), nil
|
|
}
|
|
|
|
// SetString sets an item in cache
|
|
func (r *RedisCache) SetString(key string, data string) error {
|
|
err := r.SetItem(key, []byte(data))
|
|
if err != nil {
|
|
return errors.Wrap(err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetStruct returns an struct from cache
|
|
func (r *RedisCache) GetStruct(key string, data interface{}) (err error) {
|
|
val, err := r.GetItem(key)
|
|
if err == domain.ErrCacheMiss {
|
|
return domain.ErrCacheMiss
|
|
} else if err != nil {
|
|
return errors.Wrap(err)
|
|
}
|
|
|
|
err = json.Unmarshal(val, &data)
|
|
if err != nil {
|
|
return errors.Wrap(err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetStruct sets an item in cache
|
|
func (r *RedisCache) SetStruct(key string, data interface{}) error {
|
|
dataString, err := json.Marshal(data)
|
|
if err != nil {
|
|
return errors.Wrap(err)
|
|
}
|
|
|
|
err = r.SetItem(key, dataString)
|
|
if err != nil {
|
|
return errors.Wrap(err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetExpiration returns the expiration time for a key
|
|
func (r *RedisCache) GetExpiration(key string) (expiration time.Duration, err error) {
|
|
expiration, err = r.redis.TTL(r.buildKey(key)).Result()
|
|
if err != nil {
|
|
return expiration, errors.Wrap(err)
|
|
}
|
|
|
|
return expiration, nil
|
|
}
|
|
|
|
// SetExpiration sets the expiration time for a key
|
|
func (r *RedisCache) SetExpiration(key string, expiration time.Duration) (err error) {
|
|
err = r.redis.Expire(r.buildKey(key), expiration).Err()
|
|
if err != nil {
|
|
return errors.Wrap(err)
|
|
}
|
|
|
|
return nil
|
|
}
|