Extracted KeyFuncs in etc module

This commit is contained in:
Kelvin Clement Mwinuka
2024-02-18 23:52:33 +08:00
parent d456ce1f99
commit 888908db27
3 changed files with 90 additions and 85 deletions

View File

@@ -2,11 +2,9 @@ package etc
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"github.com/echovault/echovault/src/utils" "github.com/echovault/echovault/src/utils"
"net" "net"
"time"
) )
type KeyObject struct { type KeyObject struct {
@@ -15,14 +13,12 @@ type KeyObject struct {
} }
func handleSet(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) { func handleSet(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
ctx, cancel := context.WithCancel(ctx) keys, err := setKeyFunc(cmd)
defer cancel() if err != nil {
return nil, err
}
switch x := len(cmd); { key := keys[0]
default:
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
case x == 3:
key := cmd[1]
if !server.KeyExists(key) { if !server.KeyExists(key) {
_, err := server.CreateKeyAndLock(ctx, key) _, err := server.CreateKeyAndLock(ctx, key)
@@ -40,37 +36,34 @@ func handleSet(ctx context.Context, cmd []string, server utils.Server, conn *net
server.SetValue(ctx, key, utils.AdaptType(cmd[2])) server.SetValue(ctx, key, utils.AdaptType(cmd[2]))
server.KeyUnlock(key) server.KeyUnlock(key)
return []byte(utils.OK_RESPONSE), nil return []byte(utils.OK_RESPONSE), nil
} }
}
func handleSetNX(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) { func handleSetNX(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
switch x := len(cmd); { keys, err := setNXKeyFunc(cmd)
default: if err != nil {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE) return nil, err
case x == 3: }
key := cmd[1]
key := keys[0]
if server.KeyExists(key) { if server.KeyExists(key) {
return nil, fmt.Errorf("key %s already exists", cmd[1]) return nil, fmt.Errorf("key %s already exists", key)
} }
// TODO: Retry CreateKeyAndLock until we manage to obtain the key // TODO: Retry CreateKeyAndLock until we manage to obtain the key
_, err := server.CreateKeyAndLock(ctx, key) _, err = server.CreateKeyAndLock(ctx, key)
if err != nil { if err != nil {
return nil, err return nil, err
} }
server.SetValue(ctx, key, utils.AdaptType(cmd[2])) server.SetValue(ctx, key, utils.AdaptType(cmd[2]))
server.KeyUnlock(key) server.KeyUnlock(key)
}
return []byte(utils.OK_RESPONSE), nil return []byte(utils.OK_RESPONSE), nil
} }
func handleMSet(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) { func handleMSet(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
ctx, cancel := context.WithTimeout(ctx, 250*time.Millisecond) if _, err := msetKeyFunc(cmd); err != nil {
defer cancel() return nil, err
// Check if key/value pairs are complete
if len(cmd[1:])%2 != 0 {
return nil, errors.New("each key must have a matching value")
} }
entries := make(map[string]KeyObject) entries := make(map[string]KeyObject)
@@ -129,12 +122,7 @@ func Commands() []utils.Command {
Categories: []string{utils.WriteCategory, utils.SlowCategory}, Categories: []string{utils.WriteCategory, utils.SlowCategory},
Description: "(SET key value) Set the value of a key, considering the value's type.", Description: "(SET key value) Set the value of a key, considering the value's type.",
Sync: true, Sync: true,
KeyExtractionFunc: func(cmd []string) ([]string, error) { KeyExtractionFunc: setKeyFunc,
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
}
return []string{cmd[1]}, nil
},
HandlerFunc: handleSet, HandlerFunc: handleSet,
}, },
{ {
@@ -142,12 +130,7 @@ func Commands() []utils.Command {
Categories: []string{utils.WriteCategory, utils.SlowCategory}, Categories: []string{utils.WriteCategory, utils.SlowCategory},
Description: "(SETNX key value) Set the key/value only if the key doesn't exist.", Description: "(SETNX key value) Set the key/value only if the key doesn't exist.",
Sync: true, Sync: true,
KeyExtractionFunc: func(cmd []string) ([]string, error) { KeyExtractionFunc: setNXKeyFunc,
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
}
return []string{cmd[1]}, nil
},
HandlerFunc: handleSetNX, HandlerFunc: handleSetNX,
}, },
{ {
@@ -155,18 +138,7 @@ func Commands() []utils.Command {
Categories: []string{utils.WriteCategory, utils.SlowCategory}, Categories: []string{utils.WriteCategory, utils.SlowCategory},
Description: "(MSET key value [key value ...]) Automatically etc or modify multiple key/value pairs.", Description: "(MSET key value [key value ...]) Automatically etc or modify multiple key/value pairs.",
Sync: true, Sync: true,
KeyExtractionFunc: func(cmd []string) ([]string, error) { KeyExtractionFunc: msetKeyFunc,
if len(cmd[1:])%2 != 0 {
return nil, errors.New("each key must be paired with a value")
}
var keys []string
for i, key := range cmd[1:] {
if i%2 == 0 {
keys = append(keys, key)
}
}
return keys, nil
},
HandlerFunc: handleMSet, HandlerFunc: handleMSet,
}, },
} }

View File

@@ -138,7 +138,7 @@ func Test_HandleMSET(t *testing.T) {
command: []string{"SET", "test1", "value1", "test2", "10", "test3"}, command: []string{"SET", "test1", "value1", "test2", "10", "test3"},
expectedResponse: "", expectedResponse: "",
expectedValues: make(map[string]interface{}), expectedValues: make(map[string]interface{}),
expectedErr: errors.New("each key must have a matching value"), expectedErr: errors.New("each key must be paired with a value"),
}, },
} }

View File

@@ -0,0 +1,33 @@
package etc
import (
"errors"
"github.com/echovault/echovault/src/utils"
)
func setKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
}
return []string{cmd[1]}, nil
}
func setNXKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
}
return []string{cmd[1]}, nil
}
func msetKeyFunc(cmd []string) ([]string, error) {
if len(cmd[1:])%2 != 0 {
return nil, errors.New("each key must be paired with a value")
}
var keys []string
for i, key := range cmd[1:] {
if i%2 == 0 {
keys = append(keys, key)
}
}
return keys, nil
}