feat: add prefix key support to keyvalue store (#1038)

feat: add prefix key operations to keyvalue store
This commit is contained in:
kolaente
2025-06-27 13:05:37 +02:00
committed by GitHub
parent 53a3945a03
commit ae92822ee0
3 changed files with 76 additions and 0 deletions

View File

@@ -30,6 +30,8 @@ type Storage interface {
Del(key string) (err error)
IncrBy(key string, update int64) (err error)
DecrBy(key string, update int64) (err error)
ListKeys(prefix string) ([]string, error)
DelPrefix(prefix string) error
}
var store Storage
@@ -74,3 +76,13 @@ func IncrBy(key string, update int64) (err error) {
func DecrBy(key string, update int64) (err error) {
return store.DecrBy(key, update)
}
// ListKeys returns all keys beginning with prefix from the configured backend
func ListKeys(prefix string) ([]string, error) {
return store.ListKeys(prefix)
}
// DelPrefix deletes all keys with the given prefix in the backend
func DelPrefix(prefix string) error {
return store.DelPrefix(prefix)
}

View File

@@ -18,6 +18,7 @@ package memory
import (
"reflect"
"strings"
"sync"
e "code.vikunja.io/api/pkg/modules/keyvalue/error"
@@ -125,3 +126,32 @@ func (s *Storage) DecrBy(key string, update int64) (err error) {
s.store[key] = val - update
return nil
}
// ListKeys returns all keys in the storage which start with the given prefix
func (s *Storage) ListKeys(prefix string) ([]string, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
keys := make([]string, 0)
for k := range s.store {
if strings.HasPrefix(k, prefix) {
keys = append(keys, k)
}
}
return keys, nil
}
// DelPrefix removes all keys which start with the given prefix
func (s *Storage) DelPrefix(prefix string) error {
s.mutex.Lock()
defer s.mutex.Unlock()
for k := range s.store {
if strings.HasPrefix(k, prefix) {
delete(s.store, k)
}
}
return nil
}

View File

@@ -113,3 +113,37 @@ func (s *Storage) IncrBy(key string, update int64) (err error) {
func (s *Storage) DecrBy(key string, update int64) (err error) {
return s.client.DecrBy(context.Background(), key, update).Err()
}
// ListKeys returns all keys in redis starting with the given prefix
func (s *Storage) ListKeys(prefix string) ([]string, error) {
ctx := context.Background()
pattern := prefix + "*"
var cursor uint64
var keys []string
for {
k, c, err := s.client.Scan(ctx, cursor, pattern, 100).Result()
if err != nil {
return nil, err
}
keys = append(keys, k...)
cursor = c
if cursor == 0 {
break
}
}
return keys, nil
}
// DelPrefix removes all keys in redis which start with the given prefix
func (s *Storage) DelPrefix(prefix string) error {
keys, err := s.ListKeys(prefix)
if err != nil {
return err
}
if len(keys) == 0 {
return nil
}
return s.client.Del(context.Background(), keys...).Err()
}