148 lines
3.3 KiB
Go
148 lines
3.3 KiB
Go
package cache
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/fiskerinc/cloud-services/pkg/common"
|
|
"github.com/fiskerinc/cloud-services/pkg/db/queries"
|
|
"github.com/fiskerinc/cloud-services/pkg/logger"
|
|
"github.com/fiskerinc/cloud-services/pkg/redis"
|
|
|
|
r "github.com/gomodule/redigo/redis"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func RetrieveFileEncryptionParams(client redis.Client, db queries.FileKeysInterface, fileids []string) ([]common.FileKeyResponse, error) {
|
|
result, err := retrieveFileEncryptionParamsRedis(client, fileids)
|
|
if err != nil && !errors.Is(err, redis.ErrNilObject) {
|
|
return nil, err
|
|
}
|
|
|
|
dbFileIDs := missingFileIDs(result, fileids)
|
|
if len(dbFileIDs) > 0 {
|
|
rows, err := retrieveFileEncryptionParamsDB(db, dbFileIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = cacheFileEncryptionParamsRedis(client, rows, redisObjectExpireDay)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result = append(rows, result...)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func retrieveFileEncryptionParamsRedis(client redis.Client, fileids []string) ([]common.FileKeyResponse, error) {
|
|
keys := make([]string, len(fileids))
|
|
|
|
for i, fileid := range fileids {
|
|
keys[i] = redis.FileIDEncryptionParamsKey(fileid)
|
|
}
|
|
|
|
if len(keys) == 0 {
|
|
return []common.FileKeyResponse{}, nil
|
|
}
|
|
|
|
values, err := client.GetMulti(keys)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result, err := getFileKeyResponses(values)
|
|
return result, err
|
|
}
|
|
|
|
func getFileKeyResponses(values []interface{}) ([]common.FileKeyResponse, error) {
|
|
result := []common.FileKeyResponse{}
|
|
|
|
for _, value := range values {
|
|
if value == nil {
|
|
continue
|
|
}
|
|
|
|
file := common.FileKeyResponse{}
|
|
data, err := r.Bytes(value, nil)
|
|
if err != nil {
|
|
file.Error = err.Error()
|
|
return result, errors.WithStack(err)
|
|
}
|
|
|
|
err = json.Unmarshal(data, &file)
|
|
if err != nil {
|
|
return result, errors.WithStack(err)
|
|
}
|
|
|
|
result = append(result, file)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func missingFileIDs(items []common.FileKeyResponse, fileids []string) []string {
|
|
result := []string{}
|
|
hash := map[string]bool{}
|
|
|
|
for _, item := range items {
|
|
if item.FileID != "" {
|
|
hash[item.FileID] = true
|
|
}
|
|
}
|
|
|
|
for _, fileid := range fileids {
|
|
if !hash[fileid] {
|
|
result = append(result, fileid)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func retrieveFileEncryptionParamsDB(db queries.FileKeysInterface, fileids []string) ([]common.FileKeyResponse, error) {
|
|
result := make([]common.FileKeyResponse, len(fileids))
|
|
hash := map[string]bool{}
|
|
data, err := db.GetMulti(fileids)
|
|
if err != nil {
|
|
return nil, errors.WithStack(err)
|
|
}
|
|
|
|
for i, file := range data {
|
|
result[i].Apply(&file)
|
|
hash[file.FileID] = true
|
|
}
|
|
|
|
if len(fileids) != len(data) {
|
|
starting := len(data)
|
|
current := 0
|
|
for _, fileid := range fileids {
|
|
if !hash[fileid] {
|
|
logger.Warn().Msgf("file id %s not found", fileid)
|
|
file := &result[starting+current]
|
|
file.FileID = fileid
|
|
file.Error = "not found"
|
|
current++
|
|
}
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func cacheFileEncryptionParamsRedis(client redis.Client, files []common.FileKeyResponse, expire int) error {
|
|
batch := redis.NewRedisBatchCommands()
|
|
|
|
for _, file := range files {
|
|
serialized, err := json.Marshal(file)
|
|
if err != nil {
|
|
return errors.WithStack(err)
|
|
}
|
|
id := redis.FileIDEncryptionParamsKey(file.FileID)
|
|
batch.Add("SET", id, serialized, "EX", expire)
|
|
}
|
|
|
|
_, err := client.ExecuteBatch(batch)
|
|
return errors.WithStack(err)
|
|
}
|