137 lines
3.3 KiB
Go
137 lines
3.3 KiB
Go
package cachev2
|
|
|
|
import (
|
|
"github.com/fiskerinc/cloud-services/pkg/common"
|
|
"github.com/fiskerinc/cloud-services/pkg/db/queries"
|
|
"github.com/fiskerinc/cloud-services/pkg/logger"
|
|
redis "github.com/fiskerinc/cloud-services/pkg/redisv2"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func NewDriversCache(redisClient redis.ClientInterface, cars queries.CarsInterface) *DriversCache {
|
|
return &DriversCache{
|
|
redisClient: redisClient,
|
|
cars: cars,
|
|
}
|
|
}
|
|
|
|
type DriversCache struct {
|
|
redisClient redis.ClientInterface
|
|
cars queries.CarsInterface
|
|
}
|
|
|
|
func (dc *DriversCache) RedisClientPool() redis.ClientInterface {
|
|
return dc.redisClient
|
|
}
|
|
|
|
func (dc *DriversCache) Cars() queries.CarsInterface {
|
|
return dc.cars
|
|
}
|
|
|
|
func (dc *DriversCache) hasCachedNoDrivers(drivers []string) bool {
|
|
// Redis will return []string{""} for no drivers
|
|
return len(drivers) == 1 && len(drivers[0]) == 0
|
|
}
|
|
|
|
func (dc *DriversCache) cacheDrivers(key string, drivers []string) error {
|
|
// cache driver IDs
|
|
if len(drivers) > 0 {
|
|
return dc.redisClient.NewSet(key, drivers, redisObjectExpire)
|
|
}
|
|
|
|
// Redis will not take an empty array as an arg
|
|
return nil
|
|
}
|
|
|
|
// RetrieveDriverIDs retrieves IDs from redis or from DB and proceeds to cache both the drivers and IDs
|
|
// redis keys:
|
|
//
|
|
// car:<VIN>:drivers
|
|
func (dc *DriversCache) RetrieveDriverIDs(vin string) ([]string, error) {
|
|
var driverIDs []string
|
|
driverIDsKey := redis.CarToAllDriversKey(vin)
|
|
|
|
// retrieve IDs from redis
|
|
err := dc.redisClient.GetSet(driverIDsKey, &driverIDs)
|
|
if err != nil {
|
|
logger.Warn().Err(err).Send()
|
|
return []string{}, err
|
|
}
|
|
|
|
if dc.hasCachedNoDrivers(driverIDs) {
|
|
return []string{}, nil
|
|
}
|
|
if len(driverIDs) > 0 {
|
|
return driverIDs, nil
|
|
}
|
|
|
|
// if IDs not present in redis perform DB lookup
|
|
var drivers []common.CarToDriver
|
|
drivers, err = dc.cars.GetDrivers(vin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, driver := range drivers {
|
|
driverIDs = append(driverIDs, driver.DriverID)
|
|
}
|
|
|
|
err = dc.cacheDrivers(driverIDsKey, driverIDs)
|
|
if err != nil {
|
|
return driverIDs, err
|
|
}
|
|
|
|
return driverIDs, nil
|
|
}
|
|
|
|
// RetrieveDriverIDsAsSet retrieves IDs from redis or from DB and proceeds to cache both the drivers and IDs
|
|
// redis keys:
|
|
//
|
|
// car:<VIN>:drivers
|
|
func (dc *DriversCache) RetrieveDriverIDsAsSet(vin string) (map[string]struct{}, error) {
|
|
driverIDs, err := dc.RetrieveDriverIDs(vin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var dIDsSet = make(map[string]struct{})
|
|
for _, did := range driverIDs {
|
|
dIDsSet[did] = struct{}{}
|
|
}
|
|
|
|
return dIDsSet, nil
|
|
}
|
|
|
|
func (dc *DriversCache) IsDriverOfVIN(vin string, driverid string) (bool, error) {
|
|
ids, err := dc.RetrieveDriverIDs(vin)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
for _, id := range ids {
|
|
if id == driverid {
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
return false, dc.NotDriverError(vin, driverid)
|
|
}
|
|
|
|
// Add driver to database and cache
|
|
func (dc *DriversCache) AddDriver(car *common.Car, driver *common.Driver, role string) (*common.CarToDriver, error) {
|
|
|
|
relation, err := dc.cars.AddDriver(car, driver, role)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
driverIDsKey := redis.CarToAllDriversKey(car.VIN)
|
|
|
|
dc.redisClient.AddToSet(driverIDsKey, driver.ID, redisObjectExpire)
|
|
return relation, nil
|
|
}
|
|
|
|
func (dc DriversCache) NotDriverError(vin string, driverid string) error {
|
|
return errors.Errorf("id %s is not a driver for vin %v", driverid, vin)
|
|
}
|