Skip to content

Commit

Permalink
Merge branch 'main' of ssh://github.com/absolutelightning/treds
Browse files Browse the repository at this point in the history
  • Loading branch information
absolutelightning committed Dec 31, 2024
2 parents 2708689 + 3a0cf84 commit 6669bd1
Show file tree
Hide file tree
Showing 9 changed files with 537 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ This graph shows the performance comparison between Treds - ScanKeys and Etcd ge
* `SCANKEYS cursor prefix count` - Returns the count number of keys matching prefix starting from an index in lex order only present in Key/Value Store. Last element is the next cursor
* `SCANKVS cursor prefix count` - Returns the count number of keys/value pair in which keys match prefix starting from an index in lex order only present in Key/Value Store. Last element is the next cursor
* `KEYS cursor regex count` - Returns count number of keys matching a regex in lex order starting with cursor. Count is optional. Last element is the next cursor
* `KEYSL cursor regex count` - Returns count number of keys in List Store matching a regex in lex order starting with cursor. Count is optional. Last element is the next cursor
* `KEYSH cursor regex count` - Returns count number of keys in Hash Store matching a regex in lex order starting with cursor. Count is optional. Last element is the next cursor
* `KEYSS cursor regex count` - Returns count number of keys in Set Store matching a regex in lex order starting with cursor. Count is optional. Last element is the next cursor
* `KEYSZ cursor regex count` - Returns count number of keys in Sorted Maps Store matching a regex in lex order starting with cursor. Count is optional. Last element is the next cursor
* `KVS cursor regex count` - Returns count number of keys/values in which keys match a regex in lex order starting with cursor. Count is optional. Last element is the next cursor
* `ZADD key score member_key member_value [score member_key member_value ....]` - Add member_key with member value with score to a sorted map in key
* `ZREM key member [member ...]` - Removes a member from sorted map in key
Expand Down
4 changes: 4 additions & 0 deletions commands/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ func RegisterCommands(r CommandRegistry) {
RegisterExpireCommand(r)
RegisterTtlCommand(r)
RegisterLongestPrefixCommand(r)
RegisterKeysHCommand(r)
RegisterKeysLCommand(r)
RegisterKeysSCommand(r)
RegisterKeysZCommand(r)
}
58 changes: 58 additions & 0 deletions commands/keysh.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package commands

import (
"fmt"
"math"
"regexp"
"strconv"

"treds/resp"
"treds/store"
)

const KeysHCommand = "KEYSH"

func RegisterKeysHCommand(r CommandRegistry) {
r.Add(&CommandRegistration{
Name: KeysHCommand,
Validate: validateKeysH(),
Execute: executeKeysH(),
})
}

func validateKeysH() ValidationHook {
return func(args []string) error {
if len(args) < 2 {
return fmt.Errorf("expected minimum 2 argument, got %d", len(args))
}
if len(args) == 3 {
_, err := strconv.Atoi(args[2])
if err != nil {
return err
}
}
_, err := regexp.Compile(args[1])
if err != nil {
return err
}
return nil
}
}

func executeKeysH() ExecutionHook {
return func(args []string, store store.Store) string {
regex := ""
count := math.MaxInt64
if len(args) >= 2 {
regex = args[1]
}
if len(args) == 3 {
count, _ = strconv.Atoi(args[2])
}
v, err := store.KeysH(args[0], regex, count)
if err != nil {
return resp.EncodeError(err.Error())
}
return resp.EncodeStringArray(v)
}
}
58 changes: 58 additions & 0 deletions commands/keysl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package commands

import (
"fmt"
"math"
"regexp"
"strconv"

"treds/resp"
"treds/store"
)

const KeysLCommand = "KEYSL"

func RegisterKeysLCommand(r CommandRegistry) {
r.Add(&CommandRegistration{
Name: KeysLCommand,
Validate: validateKeysL(),
Execute: executeKeysL(),
})
}

func validateKeysL() ValidationHook {
return func(args []string) error {
if len(args) < 2 {
return fmt.Errorf("expected minimum 2 argument, got %d", len(args))
}
if len(args) == 3 {
_, err := strconv.Atoi(args[2])
if err != nil {
return err
}
}
_, err := regexp.Compile(args[1])
if err != nil {
return err
}
return nil
}
}

func executeKeysL() ExecutionHook {
return func(args []string, store store.Store) string {
regex := ""
count := math.MaxInt64
if len(args) >= 2 {
regex = args[1]
}
if len(args) == 3 {
count, _ = strconv.Atoi(args[2])
}
v, err := store.KeysL(args[0], regex, count)
if err != nil {
return resp.EncodeError(err.Error())
}
return resp.EncodeStringArray(v)
}
}
58 changes: 58 additions & 0 deletions commands/keyss.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package commands

import (
"fmt"
"math"
"regexp"
"strconv"

"treds/resp"
"treds/store"
)

const KeysSCommand = "KEYSS"

func RegisterKeysSCommand(r CommandRegistry) {
r.Add(&CommandRegistration{
Name: KeysSCommand,
Validate: validateKeysS(),
Execute: executeKeysS(),
})
}

func validateKeysS() ValidationHook {
return func(args []string) error {
if len(args) < 2 {
return fmt.Errorf("expected minimum 2 argument, got %d", len(args))
}
if len(args) == 3 {
_, err := strconv.Atoi(args[2])
if err != nil {
return err
}
}
_, err := regexp.Compile(args[1])
if err != nil {
return err
}
return nil
}
}

func executeKeysS() ExecutionHook {
return func(args []string, store store.Store) string {
regex := ""
count := math.MaxInt64
if len(args) >= 2 {
regex = args[1]
}
if len(args) == 3 {
count, _ = strconv.Atoi(args[2])
}
v, err := store.KeysS(args[0], regex, count)
if err != nil {
return resp.EncodeError(err.Error())
}
return resp.EncodeStringArray(v)
}
}
58 changes: 58 additions & 0 deletions commands/keysz.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package commands

import (
"fmt"
"math"
"regexp"
"strconv"

"treds/resp"
"treds/store"
)

const KeysZCommand = "KEYSZ"

func RegisterKeysZCommand(r CommandRegistry) {
r.Add(&CommandRegistration{
Name: KeysZCommand,
Validate: validateKeysZ(),
Execute: executeKeysZ(),
})
}

func validateKeysZ() ValidationHook {
return func(args []string) error {
if len(args) < 2 {
return fmt.Errorf("expected minimum 2 argument, got %d", len(args))
}
if len(args) == 3 {
_, err := strconv.Atoi(args[2])
if err != nil {
return err
}
}
_, err := regexp.Compile(args[1])
if err != nil {
return err
}
return nil
}
}

func executeKeysZ() ExecutionHook {
return func(args []string, store store.Store) string {
regex := ""
count := math.MaxInt64
if len(args) >= 2 {
regex = args[1]
}
if len(args) == 3 {
count, _ = strconv.Atoi(args[2])
}
v, err := store.KeysZ(args[0], regex, count)
if err != nil {
return resp.EncodeError(err.Error())
}
return resp.EncodeStringArray(v)
}
}
64 changes: 64 additions & 0 deletions commands/mock_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,70 @@ func (m *MockStore) Keys(cursor, regex string, count int) ([]string, error) {
return res, nil
}

func (m *MockStore) KeysL(cursor, regex string, count int) ([]string, error) {
res := make([]string, 0)
keys := make([]string, 0)
for key, _ := range m.data {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
match, _ := regexp.MatchString(regex, key)
if match {
res = append(res, key)
}
}
return res, nil
}

func (m *MockStore) KeysH(cursor, regex string, count int) ([]string, error) {
res := make([]string, 0)
keys := make([]string, 0)
for key, _ := range m.data {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
match, _ := regexp.MatchString(regex, key)
if match {
res = append(res, key)
}
}
return res, nil
}

func (m *MockStore) KeysS(cursor, regex string, count int) ([]string, error) {
res := make([]string, 0)
keys := make([]string, 0)
for key, _ := range m.data {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
match, _ := regexp.MatchString(regex, key)
if match {
res = append(res, key)
}
}
return res, nil
}

func (m *MockStore) KeysZ(cursor, regex string, count int) ([]string, error) {
res := make([]string, 0)
keys := make([]string, 0)
for key, _ := range m.data {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
match, _ := regexp.MatchString(regex, key)
if match {
res = append(res, key)
}
}
return res, nil
}

func (m *MockStore) KVS(cursor, regex string, count int) ([]string, error) {
res := make([]string, 0)
keys := make([]string, 0)
Expand Down
4 changes: 4 additions & 0 deletions store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ type Store interface {
PrefixScanKeys(string, string, string) ([]string, error)
DeletePrefix(string) (int, error)
Keys(string, string, int) ([]string, error)
KeysH(string, string, int) ([]string, error)
KeysL(string, string, int) ([]string, error)
KeysS(string, string, int) ([]string, error)
KeysZ(string, string, int) ([]string, error)
KVS(string, string, int) ([]string, error)
Size() (int, error)
ZAdd([]string) error
Expand Down
Loading

0 comments on commit 6669bd1

Please sign in to comment.