125 lines
2.6 KiB
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()
|
|
}
|