Made GET, MGET, SET, MSET, SETNX commands compatible with redis client

This commit is contained in:
Kelvin Clement Mwinuka
2024-02-27 15:41:22 +08:00
parent 42154fe7dd
commit 088e4c25f0
8 changed files with 264 additions and 219 deletions

View File

@@ -18,11 +18,11 @@ services:
- PLUGIN_DIR=/usr/local/lib/echovault
- DATA_DIR=/var/lib/echovault
- IN_MEMORY=false
- TLS=true
- MTLS=true
- TLS=false
- MTLS=false
- BOOTSTRAP_CLUSTER=false
- ACL_CONFIG=/etc/config/echovault/acl.yml
- REQUIRE_PASS=true
- REQUIRE_PASS=false
- PASSWORD=default_password
- FORWARD_COMMAND=false
- SNAPSHOT_THRESHOLD=1000
@@ -45,206 +45,206 @@ services:
networks:
- testnet
cluster_node_1:
container_name: cluster_node_1
build:
context: .
dockerfile: Dockerfile.dev
environment:
- PORT=7480
- RAFT_PORT=8000
- ML_PORT=7946
- KEY=/etc/ssl/certs/echovault/server1.key
- CERT=/etc/ssl/certs/echovault/server1.crt
- SERVER_ID=1
- DATA_DIR=/var/lib/echovault
- IN_MEMORY=false
- TLS=true
- MTLS=true
- BOOTSTRAP_CLUSTER=true
- ACL_CONFIG=/etc/config/echovault/acl.yml
- REQUIRE_PASS=false
- FORWARD_COMMAND=true
- SNAPSHOT_THRESHOLD=1000
- SNAPSHOT_INTERVAL=5m30s
- RESTORE_SNAPSHOT=false
- RESTORE_AOF=false
- AOF_SYNC_STRATEGY=everysec
# List of server cert/key pairs
- CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
- CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# List of client certificate authorities
- CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
ports:
- "7480:7480"
- "7945:7946"
- "8000:8000"
volumes:
- ./config/acl.yml:/etc/config/echovault/acl.yml
- ./volumes/cluster_node_1:/var/lib/echovault
networks:
- testnet
cluster_node_2:
container_name: cluster_node_2
build:
context: .
dockerfile: Dockerfile.dev
environment:
- PORT=7480
- RAFT_PORT=8000
- ML_PORT=7946
- KEY=/etc/ssl/certs/echovault/server1.key
- CERT=/etc/ssl/certs/echovault/server1.crt
- SERVER_ID=2
- JOIN_ADDR=cluster_node_1:7946
- DATA_DIR=/var/lib/echovault
- IN_MEMORY=false
- TLS=true
- MTLS=true
- BOOTSTRAP_CLUSTER=false
- ACL_CONFIG=/etc/config/echovault/acl.yml
- REQUIRE_PASS=false
- FORWARD_COMMAND=true
- SNAPSHOT_THRESHOLD=1000
- SNAPSHOT_INTERVAL=5m30s
- RESTORE_SNAPSHOT=false
- RESTORE_AOF=false
- AOF_SYNC_STRATEGY=everysec
# List of server cert/key pairs
- CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
- CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# List of client certificate authorities
- CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
ports:
- "7481:7480"
- "7947:7946"
- "8001:8000"
volumes:
- ./config/acl.yml:/etc/config/echovault/acl.yml
- ./volumes/cluster_node_2:/var/lib/echovault
networks:
- testnet
cluster_node_3:
container_name: cluster_node_3
build:
context: .
dockerfile: Dockerfile.dev
environment:
- PORT=7480
- RAFT_PORT=8000
- ML_PORT=7946
- KEY=/etc/ssl/certs/echovault/server1.key
- CERT=/etc/ssl/certs/echovault/server1.crt
- SERVER_ID=3
- JOIN_ADDR=cluster_node_1:7946
- DATA_DIR=/var/lib/echovault
- IN_MEMORY=false
- TLS=true
- MTLS=true
- BOOTSTRAP_CLUSTER=false
- ACL_CONFIG=/etc/config/echovault/acl.yml
- REQUIRE_PASS=false
- FORWARD_COMMAND=true
- SNAPSHOT_THRESHOLD=1000
- SNAPSHOT_INTERVAL=5m30s
- RESTORE_SNAPSHOT=false
- RESTORE_AOF=false
- AOF_SYNC_STRATEGY=everysec
# List of server cert/key pairs
- CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
- CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# List of client certificate authorities
- CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
ports:
- "7482:7480"
- "7948:7946"
- "8002:8000"
volumes:
- ./config/acl.yml:/etc/config/echovault/acl.yml
- ./volumes/cluster_node_3:/var/lib/echovault
networks:
- testnet
cluster_node_4:
container_name: cluster_node_4
build:
context: .
dockerfile: Dockerfile.dev
environment:
- PORT=7480
- RAFT_PORT=8000
- ML_PORT=7946
- KEY=/etc/ssl/certs/echovault/server1.key
- CERT=/etc/ssl/certs/echovault/server1.crt
- SERVER_ID=4
- JOIN_ADDR=cluster_node_1:7946
- DATA_DIR=/var/lib/echovault
- IN_MEMORY=false
- TLS=true
- MTLS=true
- BOOTSTRAP_CLUSTER=false
- ACL_CONFIG=/etc/config/echovault/acl.yml
- REQUIRE_PASS=false
- FORWARD_COMMAND=true
- SNAPSHOT_THRESHOLD=1000
- SNAPSHOT_INTERVAL=5m30s
- RESTORE_SNAPSHOT=false
- RESTORE_AOF=false
- AOF_SYNC_STRATEGY=everysec
# List of server cert/key pairs
- CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
- CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# List of client certificate authorities
- CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
ports:
- "7483:7480"
- "7949:7946"
- "8003:8000"
volumes:
- ./config/acl.yml:/etc/config/echovault/acl.yml
- ./volumes/cluster_node_4:/var/lib/echovault
networks:
- testnet
cluster_node_5:
container_name: cluster_node_5
build:
context: .
dockerfile: Dockerfile.dev
environment:
- PORT=7480
- RAFT_PORT=8000
- ML_PORT=7946
- KEY=/etc/ssl/certs/echovault/server1.key
- CERT=/etc/ssl/certs/echovault/server1.crt
- SERVER_ID=5
- JOIN_ADDR=cluster_node_1:7946
- DATA_DIR=/var/lib/echovault
- IN_MEMORY=false
- TLS=true
- MTLS=true
- BOOTSTRAP_CLUSTER=false
- ACL_CONFIG=/etc/config/echovault/acl.yml
- REQUIRE_PASS=false
- FORWARD_COMMAND=true
- SNAPSHOT_THRESHOLD=1000
- SNAPSHOT_INTERVAL=5m30s
- RESTORE_SNAPSHOT=false
- RESTORE_AOF=false
- AOF_SYNC_STRATEGY=everysec
# List of server cert/key pairs
- CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
- CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# List of client certificate authorities
- CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
ports:
- "7484:7480"
- "7950:7946"
- "8004:8000"
volumes:
- ./config/acl.yml:/etc/config/echovault/acl.yml
- ./volumes/cluster_node_5:/var/lib/echovault
networks:
- testnet
# cluster_node_1:
# container_name: cluster_node_1
# build:
# context: .
# dockerfile: Dockerfile.dev
# environment:
# - PORT=7480
# - RAFT_PORT=8000
# - ML_PORT=7946
# - KEY=/etc/ssl/certs/echovault/server1.key
# - CERT=/etc/ssl/certs/echovault/server1.crt
# - SERVER_ID=1
# - DATA_DIR=/var/lib/echovault
# - IN_MEMORY=false
# - TLS=true
# - MTLS=true
# - BOOTSTRAP_CLUSTER=true
# - ACL_CONFIG=/etc/config/echovault/acl.yml
# - REQUIRE_PASS=false
# - FORWARD_COMMAND=true
# - SNAPSHOT_THRESHOLD=1000
# - SNAPSHOT_INTERVAL=5m30s
# - RESTORE_SNAPSHOT=false
# - RESTORE_AOF=false
# - AOF_SYNC_STRATEGY=everysec
# # List of server cert/key pairs
# - CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
# - CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# # List of client certificate authorities
# - CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
# ports:
# - "7480:7480"
# - "7945:7946"
# - "8000:8000"
# volumes:
# - ./config/acl.yml:/etc/config/echovault/acl.yml
# - ./volumes/cluster_node_1:/var/lib/echovault
# networks:
# - testnet
#
# cluster_node_2:
# container_name: cluster_node_2
# build:
# context: .
# dockerfile: Dockerfile.dev
# environment:
# - PORT=7480
# - RAFT_PORT=8000
# - ML_PORT=7946
# - KEY=/etc/ssl/certs/echovault/server1.key
# - CERT=/etc/ssl/certs/echovault/server1.crt
# - SERVER_ID=2
# - JOIN_ADDR=cluster_node_1:7946
# - DATA_DIR=/var/lib/echovault
# - IN_MEMORY=false
# - TLS=true
# - MTLS=true
# - BOOTSTRAP_CLUSTER=false
# - ACL_CONFIG=/etc/config/echovault/acl.yml
# - REQUIRE_PASS=false
# - FORWARD_COMMAND=true
# - SNAPSHOT_THRESHOLD=1000
# - SNAPSHOT_INTERVAL=5m30s
# - RESTORE_SNAPSHOT=false
# - RESTORE_AOF=false
# - AOF_SYNC_STRATEGY=everysec
# # List of server cert/key pairs
# - CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
# - CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# # List of client certificate authorities
# - CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
# ports:
# - "7481:7480"
# - "7947:7946"
# - "8001:8000"
# volumes:
# - ./config/acl.yml:/etc/config/echovault/acl.yml
# - ./volumes/cluster_node_2:/var/lib/echovault
# networks:
# - testnet
#
# cluster_node_3:
# container_name: cluster_node_3
# build:
# context: .
# dockerfile: Dockerfile.dev
# environment:
# - PORT=7480
# - RAFT_PORT=8000
# - ML_PORT=7946
# - KEY=/etc/ssl/certs/echovault/server1.key
# - CERT=/etc/ssl/certs/echovault/server1.crt
# - SERVER_ID=3
# - JOIN_ADDR=cluster_node_1:7946
# - DATA_DIR=/var/lib/echovault
# - IN_MEMORY=false
# - TLS=true
# - MTLS=true
# - BOOTSTRAP_CLUSTER=false
# - ACL_CONFIG=/etc/config/echovault/acl.yml
# - REQUIRE_PASS=false
# - FORWARD_COMMAND=true
# - SNAPSHOT_THRESHOLD=1000
# - SNAPSHOT_INTERVAL=5m30s
# - RESTORE_SNAPSHOT=false
# - RESTORE_AOF=false
# - AOF_SYNC_STRATEGY=everysec
# # List of server cert/key pairs
# - CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
# - CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# # List of client certificate authorities
# - CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
# ports:
# - "7482:7480"
# - "7948:7946"
# - "8002:8000"
# volumes:
# - ./config/acl.yml:/etc/config/echovault/acl.yml
# - ./volumes/cluster_node_3:/var/lib/echovault
# networks:
# - testnet
#
# cluster_node_4:
# container_name: cluster_node_4
# build:
# context: .
# dockerfile: Dockerfile.dev
# environment:
# - PORT=7480
# - RAFT_PORT=8000
# - ML_PORT=7946
# - KEY=/etc/ssl/certs/echovault/server1.key
# - CERT=/etc/ssl/certs/echovault/server1.crt
# - SERVER_ID=4
# - JOIN_ADDR=cluster_node_1:7946
# - DATA_DIR=/var/lib/echovault
# - IN_MEMORY=false
# - TLS=true
# - MTLS=true
# - BOOTSTRAP_CLUSTER=false
# - ACL_CONFIG=/etc/config/echovault/acl.yml
# - REQUIRE_PASS=false
# - FORWARD_COMMAND=true
# - SNAPSHOT_THRESHOLD=1000
# - SNAPSHOT_INTERVAL=5m30s
# - RESTORE_SNAPSHOT=false
# - RESTORE_AOF=false
# - AOF_SYNC_STRATEGY=everysec
# # List of server cert/key pairs
# - CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
# - CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# # List of client certificate authorities
# - CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
# ports:
# - "7483:7480"
# - "7949:7946"
# - "8003:8000"
# volumes:
# - ./config/acl.yml:/etc/config/echovault/acl.yml
# - ./volumes/cluster_node_4:/var/lib/echovault
# networks:
# - testnet
#
# cluster_node_5:
# container_name: cluster_node_5
# build:
# context: .
# dockerfile: Dockerfile.dev
# environment:
# - PORT=7480
# - RAFT_PORT=8000
# - ML_PORT=7946
# - KEY=/etc/ssl/certs/echovault/server1.key
# - CERT=/etc/ssl/certs/echovault/server1.crt
# - SERVER_ID=5
# - JOIN_ADDR=cluster_node_1:7946
# - DATA_DIR=/var/lib/echovault
# - IN_MEMORY=false
# - TLS=true
# - MTLS=true
# - BOOTSTRAP_CLUSTER=false
# - ACL_CONFIG=/etc/config/echovault/acl.yml
# - REQUIRE_PASS=false
# - FORWARD_COMMAND=true
# - SNAPSHOT_THRESHOLD=1000
# - SNAPSHOT_INTERVAL=5m30s
# - RESTORE_SNAPSHOT=false
# - RESTORE_AOF=false
# - AOF_SYNC_STRATEGY=everysec
# # List of server cert/key pairs
# - CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
# - CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
# # List of client certificate authorities
# - CLIENT_CA_1=/etc/ssl/certs/echovault/client/rootCA.crt
# ports:
# - "7484:7480"
# - "7950:7946"
# - "8004:8000"
# volumes:
# - ./config/acl.yml:/etc/config/echovault/acl.yml
# - ./volumes/cluster_node_5:/var/lib/echovault
# networks:
# - testnet

BIN
dump.rdb Normal file

Binary file not shown.

View File

@@ -48,11 +48,35 @@ func handleGetAllCommands(ctx context.Context, cmd []string, server utils.Server
}
}
res = fmt.Sprintf("*%d\r\n%s\r\n", commandCount, res)
res = fmt.Sprintf("*%d\r\n%s", commandCount, res)
return []byte(res), nil
}
func handleCommandDocs(ctx context.Context, cmd []string, server utils.Server, _ *net.Conn) ([]byte, error) {
return []byte("*0\r\n"), nil
}
func handleCommandCount(ctx context.Context, cmd []string, server utils.Server, _ *net.Conn) ([]byte, error) {
return nil, errors.New("command not yet implemented")
}
func handleCommandList(ctx context.Context, cmd []string, server utils.Server, _ *net.Conn) ([]byte, error) {
return nil, errors.New("command not yet implemented")
}
func handleConfigGet(ctx context.Context, cmd []string, server utils.Server, _ *net.Conn) ([]byte, error) {
return nil, errors.New("command not yet implemented")
}
func handleConfigRewrite(ctx context.Context, cmd []string, server *utils.Server, _ *net.Conn) ([]byte, error) {
return nil, errors.New("command not yet implemented")
}
func handleConfigSet(ctx context.Context, cmd []string, server *utils.Server, _ *net.Conn) ([]byte, error) {
return nil, errors.New("command not yet implemented")
}
func Commands() []utils.Command {
return []utils.Command{
{
@@ -63,6 +87,25 @@ func Commands() []utils.Command {
KeyExtractionFunc: func(cmd []string) ([]string, error) { return []string{}, nil },
HandlerFunc: handleGetAllCommands,
},
{
Command: "command",
Categories: []string{},
Description: "Commands pertaining to echovault commands",
Sync: false,
KeyExtractionFunc: func(cmd []string) ([]string, error) {
return []string{}, nil
},
SubCommands: []utils.SubCommand{
{
Command: "docs",
Categories: []string{utils.SlowCategory, utils.ConnectionCategory},
Description: "Get command documentation",
Sync: false,
KeyExtractionFunc: func(cmd []string) ([]string, error) { return []string{}, nil },
HandlerFunc: handleCommandDocs,
},
},
},
{
Command: "save",
Categories: []string{utils.AdminCategory, utils.SlowCategory, utils.DangerousCategory},

View File

@@ -2,6 +2,7 @@ package etc
import (
"context"
"errors"
"fmt"
"github.com/echovault/echovault/src/utils"
"net"
@@ -50,9 +51,7 @@ func handleSetNX(ctx context.Context, cmd []string, server utils.Server, conn *n
if server.KeyExists(key) {
return nil, fmt.Errorf("key %s already exists", key)
}
// TODO: Retry CreateKeyAndLock until we manage to obtain the key
_, err = server.CreateKeyAndLock(ctx, key)
if err != nil {
if _, err = server.CreateKeyAndLock(ctx, key); err != nil {
return nil, err
}
server.SetValue(ctx, key, utils.AdaptType(cmd[2]))
@@ -115,6 +114,10 @@ func handleMSet(ctx context.Context, cmd []string, server utils.Server, conn *ne
return []byte(utils.OK_RESPONSE), nil
}
func handleCopy(ctx context.Context, cmd []string, server *utils.Server, _ *net.Conn) ([]byte, error) {
return nil, errors.New("command not yet implemented")
}
func Commands() []utils.Command {
return []utils.Command{
{

View File

@@ -15,7 +15,7 @@ func handleGet(ctx context.Context, cmd []string, server utils.Server, conn *net
key := keys[0]
if !server.KeyExists(key) {
return []byte("+nil\r\n\r\n"), nil
return []byte("$-1\r\n"), nil
}
_, err = server.KeyRLock(ctx, key)
@@ -26,7 +26,7 @@ func handleGet(ctx context.Context, cmd []string, server utils.Server, conn *net
value := server.GetValue(key)
return []byte(fmt.Sprintf("+%v\r\n\r\n", value)), nil
return []byte(fmt.Sprintf("+%v\r\n", value)), nil
}
func handleMGet(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
@@ -72,8 +72,6 @@ func handleMGet(ctx context.Context, cmd []string, server utils.Server, conn *ne
bytes = append(bytes, []byte(fmt.Sprintf("$%d\r\n%s\r\n", len(values[key]), values[key]))...)
}
bytes = append(bytes, []byte("\r\n")...)
return bytes, nil
}

View File

@@ -13,9 +13,9 @@ func handlePing(ctx context.Context, cmd []string, server utils.Server, conn *ne
default:
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
case 1:
return []byte("+PONG\r\n\r\n"), nil
return []byte("+PONG\r\n"), nil
case 2:
return []byte(fmt.Sprintf("$%d\r\n%s\r\n\r\n", len(cmd[1]), cmd[1])), nil
return []byte(fmt.Sprintf("$%d\r\n%s\r\n", len(cmd[1]), cmd[1])), nil
}
}
@@ -40,7 +40,7 @@ func Commands() []utils.Command {
return []string{}, nil
},
HandlerFunc: func(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
return []byte("$-1\r\n\r\n"), nil
return []byte("$-1\r\n"), nil
},
},
}

View File

@@ -208,6 +208,7 @@ func (server *Server) handleConnection(ctx context.Context, conn net.Conn) {
if err != nil && errors.Is(err, io.EOF) {
// Connection closed
log.Println(err)
break
}
@@ -219,7 +220,7 @@ func (server *Server) handleConnection(ctx context.Context, conn net.Conn) {
res, err := server.handleCommand(ctx, message, &conn, false)
if err != nil {
if _, err = w.Write([]byte(fmt.Sprintf("-Error %s\r\n\r\n", err.Error()))); err != nil {
if _, err = w.Write([]byte(fmt.Sprintf("-Error %s\r\n", err.Error()))); err != nil {
log.Println(err)
}
continue

View File

@@ -25,6 +25,6 @@ const (
)
const (
OK_RESPONSE = "+OK\r\n\r\n"
OK_RESPONSE = "+OK\r\n"
WRONG_ARGS_RESPONSE = "wrong number of arguments"
)