Files
cloud-services/pkg/cache/vehicles.go

125 lines
2.6 KiB
Go

package cache
import (
"encoding/json"
"github.com/fiskerinc/cloud-services/pkg/common"
orm "github.com/fiskerinc/cloud-services/pkg/db/queries"
"fmt"
"github.com/ReneKroon/ttlcache/v2"
"github.com/pkg/errors"
"sync"
"time"
)
var (
ErrCacheNotInitialized = errors.New("cache is not initialized")
)
type VehicleCacher interface {
Set(key VehiclesTTLParams, value *VehiclesTTLResult) error
Get(key VehiclesTTLParams) (*VehiclesTTLResult, error)
}
type VehiclesCache struct {
duration time.Duration
limit int
cache *ttlcache.Cache
onceCache *sync.Once
}
func (c *VehiclesCache) Duration() time.Duration {
return c.duration
}
func (c *VehiclesCache) Limit() int {
return c.limit
}
func (c *VehiclesCache) Once() *sync.Once {
return c.onceCache
}
func (c *VehiclesCache) SetCache(cache *ttlcache.Cache) {
c.cache = cache
}
func (c *VehiclesCache) Cache() *ttlcache.Cache {
return c.cache
}
type VehiclesTTLParams struct {
Options orm.PageQueryOptions `json:"options"`
CarOnlineFilter *common.CarOnlineFilter `json:"car_online_filter"`
Search string `json:"search"`
}
type VehiclesTTLResult struct {
Data []common.Car `json:"data"`
Total int `json:"total"`
}
func NewVehiclesCache(duration time.Duration, limit int) (*VehiclesCache, error) {
c := &VehiclesCache{
duration: duration,
limit: limit,
onceCache: &sync.Once{},
}
if cache := logCache(c); cache == nil {
return nil, ErrCacheNotInitialized
}
return c, nil
}
func (c *VehiclesCache) Set(key VehiclesTTLParams, value *VehiclesTTLResult) error {
if cache := logCache(c); cache == nil {
return ErrCacheNotInitialized
}
keyBts, err := json.Marshal(key)
if err != nil {
return errors.WithMessagef(err, "failed to marshal key")
}
return c.cache.Set(string(keyBts), value)
}
func (c *VehiclesCache) Get(key VehiclesTTLParams) (*VehiclesTTLResult, error) {
if cache := logCache(c); cache == nil {
return nil, ErrCacheNotInitialized
}
keyBts, err := json.Marshal(key)
if err != nil {
return nil, errors.WithMessagef(err, "failed to marshal key")
}
value, err := c.cache.Get(string(keyBts))
if err != nil {
return nil, fmt.Errorf("failed to get value from cache: %w", err)
}
return value.(*VehiclesTTLResult), nil
}
type Cacher interface {
Duration() time.Duration
Limit() int
Once() *sync.Once
Cache() *ttlcache.Cache
SetCache(*ttlcache.Cache)
}
func logCache(cacher Cacher) *ttlcache.Cache {
cacher.Once().Do(func() {
if cacher.Cache() == nil {
cache := ttlcache.NewCache()
cache.SetTTL(cacher.Duration())
cache.SetCacheSizeLimit(cacher.Limit())
cacher.SetCache(cache)
}
})
return cacher.Cache()
}