Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
189
backend/internal/home/kv_helpers.go
Normal file
189
backend/internal/home/kv_helpers.go
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
package home
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func HashKeyPart(value string) string {
|
||||
sum := sha256.Sum256([]byte(value))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func CurrentKVClient() (*Client, bool, error) {
|
||||
client := Current()
|
||||
if client == nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
if !client.Enabled() {
|
||||
return nil, true, fmt.Errorf("home kv store unavailable: %w", ErrDisabled)
|
||||
}
|
||||
if !client.HeartbeatOK() {
|
||||
return nil, true, fmt.Errorf("home kv store unavailable: %w", ErrNotConnected)
|
||||
}
|
||||
return client, true, nil
|
||||
}
|
||||
|
||||
func KVGetJSONRequired(ctx context.Context, key string, out any) (bool, bool, error) {
|
||||
client, homeMode, errClient := CurrentKVClient()
|
||||
if !homeMode || errClient != nil {
|
||||
return homeMode, false, errClient
|
||||
}
|
||||
raw, found, errGet := client.KVGet(ctx, key)
|
||||
if errGet != nil || !found {
|
||||
return true, false, errGet
|
||||
}
|
||||
if errUnmarshal := json.Unmarshal(raw, out); errUnmarshal != nil {
|
||||
return true, false, errUnmarshal
|
||||
}
|
||||
return true, true, nil
|
||||
}
|
||||
|
||||
func KVSetJSONRequired(ctx context.Context, key string, value any, ttl time.Duration) (bool, error) {
|
||||
raw, errMarshal := json.Marshal(value)
|
||||
if errMarshal != nil {
|
||||
return false, errMarshal
|
||||
}
|
||||
return KVSetBytesRequired(ctx, key, raw, ttl)
|
||||
}
|
||||
|
||||
func KVSetBytesRequired(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error) {
|
||||
client, homeMode, errClient := CurrentKVClient()
|
||||
if !homeMode || errClient != nil {
|
||||
return homeMode, errClient
|
||||
}
|
||||
written, errSet := client.KVSet(ctx, key, value, kvSetOptionsForTTL(ttl))
|
||||
if errSet != nil {
|
||||
return true, errSet
|
||||
}
|
||||
if !written {
|
||||
return true, fmt.Errorf("home kv store unavailable")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func KVSetNXRequired(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, bool, error) {
|
||||
client, homeMode, errClient := CurrentKVClient()
|
||||
if !homeMode || errClient != nil {
|
||||
return homeMode, false, errClient
|
||||
}
|
||||
written, errSet := client.KVSetNX(ctx, key, value, ttl)
|
||||
return true, written, errSet
|
||||
}
|
||||
|
||||
func KVDelRequired(ctx context.Context, keys ...string) (bool, int64, error) {
|
||||
client, homeMode, errClient := CurrentKVClient()
|
||||
if !homeMode || errClient != nil {
|
||||
return homeMode, 0, errClient
|
||||
}
|
||||
deleted, errDel := client.KVDel(ctx, keys...)
|
||||
return true, deleted, errDel
|
||||
}
|
||||
|
||||
func KVExpireRequired(ctx context.Context, key string, ttl time.Duration) (bool, error) {
|
||||
client, homeMode, errClient := CurrentKVClient()
|
||||
if !homeMode || errClient != nil {
|
||||
return homeMode, errClient
|
||||
}
|
||||
_, errExpire := client.KVExpire(ctx, key, ttl)
|
||||
return true, errExpire
|
||||
}
|
||||
|
||||
func KVGetJSONBestEffort(ctx context.Context, key string, out any) (bool, bool) {
|
||||
homeMode, found, errGet := KVGetJSONRequired(ctx, key, out)
|
||||
if errGet != nil {
|
||||
log.Errorf("home kv best-effort get failed prefix=%s: %v", kvLogPrefix(key), errGet)
|
||||
return homeMode, false
|
||||
}
|
||||
return homeMode, found
|
||||
}
|
||||
|
||||
func KVSetJSONBestEffort(ctx context.Context, key string, value any, ttl time.Duration) bool {
|
||||
raw, errMarshal := json.Marshal(value)
|
||||
if errMarshal != nil {
|
||||
log.Errorf("home kv best-effort set failed prefix=%s: %v", kvLogPrefix(key), errMarshal)
|
||||
return false
|
||||
}
|
||||
return KVSetBytesBestEffort(ctx, key, raw, ttl)
|
||||
}
|
||||
|
||||
func KVSetBytesBestEffort(ctx context.Context, key string, value []byte, ttl time.Duration) bool {
|
||||
homeMode, errSet := KVSetBytesRequired(ctx, key, value, ttl)
|
||||
if !homeMode {
|
||||
return false
|
||||
}
|
||||
if errSet != nil {
|
||||
log.Errorf("home kv best-effort set failed prefix=%s: %v", kvLogPrefix(key), errSet)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func KVSetNXBestEffort(ctx context.Context, key string, value []byte, ttl time.Duration) bool {
|
||||
homeMode, written, errSet := KVSetNXRequired(ctx, key, value, ttl)
|
||||
if !homeMode {
|
||||
return false
|
||||
}
|
||||
if errSet != nil {
|
||||
log.Errorf("home kv best-effort setnx failed prefix=%s: %v", kvLogPrefix(key), errSet)
|
||||
return false
|
||||
}
|
||||
return written
|
||||
}
|
||||
|
||||
func KVDelBestEffort(ctx context.Context, keys ...string) bool {
|
||||
homeMode, _, errDel := KVDelRequired(ctx, keys...)
|
||||
if !homeMode {
|
||||
return false
|
||||
}
|
||||
if errDel != nil {
|
||||
log.Errorf("home kv best-effort del failed prefix=%s: %v", kvLogPrefix(firstKVKey(keys)), errDel)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func KVExpireBestEffort(ctx context.Context, key string, ttl time.Duration) bool {
|
||||
homeMode, errExpire := KVExpireRequired(ctx, key, ttl)
|
||||
if !homeMode {
|
||||
return false
|
||||
}
|
||||
if errExpire != nil {
|
||||
log.Errorf("home kv best-effort expire failed prefix=%s: %v", kvLogPrefix(key), errExpire)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func kvSetOptionsForTTL(ttl time.Duration) KVSetOptions {
|
||||
if ttl <= 0 {
|
||||
return KVSetOptions{}
|
||||
}
|
||||
return KVSetOptions{EX: ttl}
|
||||
}
|
||||
|
||||
func kvLogPrefix(key string) string {
|
||||
key = strings.TrimSpace(key)
|
||||
if key == "" {
|
||||
return "unknown"
|
||||
}
|
||||
parts := strings.Split(key, ":")
|
||||
if len(parts) >= 2 {
|
||||
return parts[0] + ":" + parts[1] + ":*"
|
||||
}
|
||||
return parts[0] + ":*"
|
||||
}
|
||||
|
||||
func firstKVKey(keys []string) string {
|
||||
if len(keys) == 0 {
|
||||
return ""
|
||||
}
|
||||
return keys[0]
|
||||
}
|
||||
Loading…
Reference in a new issue