package cache import ( "github.com/fiskerinc/cloud-services/pkg/common" "github.com/fiskerinc/cloud-services/pkg/logger" "github.com/fiskerinc/cloud-services/pkg/redis" redigo "github.com/gomodule/redigo/redis" "github.com/pkg/errors" ) func GetVINListDigitalTwin(vins []string, clientPool redis.ClientPoolInterface) (digitalTwins map[string]common.CarState, errorList []error) { digitalTwins = make(map[string]common.CarState) client := clientPool.GetFromPool() defer client.Close() batch := redis.NewRedisBatchCommands() for _, vin := range vins { batch.Add("SISMEMBER", redis.CarSessionsKey(), vin) batch.Add("SISMEMBER", redis.HMISessionsKey(), vin) batch.Add("HGETALL", redis.CarStateHashKey(vin)) } payload, err := redigo.Values(client.ExecuteBatch(batch)) if err != nil { errorList = append(errorList, err) return } for index, vin := range vins { startPoint := index * 3 tempTwin, err := ParsePayloadForVehicleState(payload[startPoint:startPoint+3]) if err != nil { err = errors.WithMessage(err, vin) errorList = append(errorList, err) continue } digitalTwins[vin] = tempTwin } return } func ParsePayloadForVehicleState(payload []interface{}) (common.CarState, error) { var state common.CarState online, err := redigo.Bool(payload[0], nil) if err != nil { return state, err } else { state.Online = online } online, err = redigo.Bool(payload[1], nil) if err != nil { return state, errors.WithStack(err) } else { state.OnlineHMI = online } err = parseCarStatePayload(&state, payload[2]) return state, err } func parseCarStatePayload(state *common.CarState, payload interface{}) error { stateValues, err := redigo.Values(payload, nil) if err != nil { return err } if len(stateValues)%2 != 0 { return errors.New("object does not contain equal number of key value pairs") } err = parseStateValues(state, stateValues, parseCarState) return err } func parseStateValues(state *common.CarState, stateValues []interface{}, parser stateParser) error { for i := 0; i < len(stateValues); i += 2 { key, okKey := stateValues[i].([]byte) value, okValue := stateValues[i+1].([]byte) if !okKey || !okValue { return errors.New("cannot parse object into car state") } err := parser(state, string(key), value) // log error, do not return error so we can read other properties for digital twin if err != nil { logger.Err(err).Send() } } return nil }