mirror of
https://github.com/EchoVault/SugarDB.git
synced 2025-10-07 00:43:37 +08:00
Uncommented AddCommand method
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@ package echovault
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/echovault/echovault/internal"
|
"github.com/echovault/echovault/internal"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -82,16 +83,11 @@ type CommandHandlerFunc func(params CommandHandlerFuncParams) ([]byte, error)
|
|||||||
// SetValue sets the value at the specified key. Make sure to invoke KeyLock on the key before
|
// SetValue sets the value at the specified key. Make sure to invoke KeyLock on the key before
|
||||||
// SetValue to ensure thread safety.
|
// SetValue to ensure thread safety.
|
||||||
type CommandHandlerFuncParams struct {
|
type CommandHandlerFuncParams struct {
|
||||||
Context context.Context
|
Context context.Context
|
||||||
Command []string
|
Command []string
|
||||||
KeyExists func(ctx context.Context, key string) bool
|
KeysExist func(keys []string) map[string]bool
|
||||||
CreateKeyAndLock func(ctx context.Context, key string) (bool, error)
|
GetValues func(ctx context.Context, keys []string) map[string]interface{}
|
||||||
KeyLock func(ctx context.Context, key string) (bool, error)
|
SetValues func(ctx context.Context, entries map[string]interface{}) error
|
||||||
KeyUnlock func(ctx context.Context, key string)
|
|
||||||
KeyRLock func(ctx context.Context, key string) (bool, error)
|
|
||||||
KeyRUnlock func(ctx context.Context, key string)
|
|
||||||
GetValue func(ctx context.Context, key string) interface{}
|
|
||||||
SetValue func(ctx context.Context, key string, value interface{}) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandOptions provides the specification of the command to be added to the EchoVault instance.
|
// CommandOptions provides the specification of the command to be added to the EchoVault instance.
|
||||||
@@ -229,133 +225,123 @@ func (server *EchoVault) RewriteAOF() (string, error) {
|
|||||||
// Errors:
|
// Errors:
|
||||||
//
|
//
|
||||||
// "command <command> already exists" - If a command with the same command name as the passed command already exists.
|
// "command <command> already exists" - If a command with the same command name as the passed command already exists.
|
||||||
// func (server *EchoVault) AddCommand(command CommandOptions) error {
|
func (server *EchoVault) AddCommand(command CommandOptions) error {
|
||||||
// server.commandsRWMut.Lock()
|
server.commandsRWMut.Lock()
|
||||||
// defer server.commandsRWMut.Unlock()
|
defer server.commandsRWMut.Unlock()
|
||||||
// // Check if command already exists
|
// Check if command already exists
|
||||||
// for _, c := range server.commands {
|
for _, c := range server.commands {
|
||||||
// if strings.EqualFold(c.Command, command.Command) {
|
if strings.EqualFold(c.Command, command.Command) {
|
||||||
// return fmt.Errorf("command %s already exists", command.Command)
|
return fmt.Errorf("command %s already exists", command.Command)
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// if command.SubCommand == nil || len(command.SubCommand) == 0 {
|
if command.SubCommand == nil || len(command.SubCommand) == 0 {
|
||||||
// // Add command with no subcommands
|
// Add command with no subcommands
|
||||||
// server.commands = append(server.commands, internal.Command{
|
server.commands = append(server.commands, internal.Command{
|
||||||
// Command: command.Command,
|
Command: command.Command,
|
||||||
// Module: strings.ToLower(command.Module), // Convert module to lower case for uniformity
|
Module: strings.ToLower(command.Module), // Convert module to lower case for uniformity
|
||||||
// Categories: func() []string {
|
Categories: func() []string {
|
||||||
// // Convert all the categories to lower case for uniformity
|
// Convert all the categories to lower case for uniformity
|
||||||
// cats := make([]string, len(command.Categories))
|
cats := make([]string, len(command.Categories))
|
||||||
// for i, cat := range command.Categories {
|
for i, cat := range command.Categories {
|
||||||
// cats[i] = strings.ToLower(cat)
|
cats[i] = strings.ToLower(cat)
|
||||||
// }
|
}
|
||||||
// return cats
|
return cats
|
||||||
// }(),
|
}(),
|
||||||
// Description: command.Description,
|
Description: command.Description,
|
||||||
// Sync: command.Sync,
|
Sync: command.Sync,
|
||||||
// KeyExtractionFunc: internal.KeyExtractionFunc(func(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
KeyExtractionFunc: internal.KeyExtractionFunc(func(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
||||||
// accessKeys, err := command.KeyExtractionFunc(cmd)
|
accessKeys, err := command.KeyExtractionFunc(cmd)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return internal.KeyExtractionFuncResult{}, err
|
return internal.KeyExtractionFuncResult{}, err
|
||||||
// }
|
}
|
||||||
// return internal.KeyExtractionFuncResult{
|
return internal.KeyExtractionFuncResult{
|
||||||
// Channels: []string{},
|
Channels: []string{},
|
||||||
// ReadKeys: accessKeys.ReadKeys,
|
ReadKeys: accessKeys.ReadKeys,
|
||||||
// WriteKeys: accessKeys.WriteKeys,
|
WriteKeys: accessKeys.WriteKeys,
|
||||||
// }, nil
|
}, nil
|
||||||
// }),
|
}),
|
||||||
// HandlerFunc: internal.HandlerFunc(func(params internal.HandlerFuncParams) ([]byte, error) {
|
HandlerFunc: internal.HandlerFunc(func(params internal.HandlerFuncParams) ([]byte, error) {
|
||||||
// return command.HandlerFunc(CommandHandlerFuncParams{
|
return command.HandlerFunc(CommandHandlerFuncParams{
|
||||||
// Context: params.Context,
|
Context: params.Context,
|
||||||
// Command: params.Command,
|
Command: params.Command,
|
||||||
// KeyLock: params.KeyLock,
|
KeysExist: params.KeysExist,
|
||||||
// KeyUnlock: params.KeyUnlock,
|
GetValues: params.GetValues,
|
||||||
// KeyRLock: params.KeyRLock,
|
SetValues: params.SetValues,
|
||||||
// KeyRUnlock: params.KeyRUnlock,
|
})
|
||||||
// KeyExists: params.KeyExists,
|
}),
|
||||||
// CreateKeyAndLock: params.CreateKeyAndLock,
|
})
|
||||||
// GetValue: params.GetValue,
|
return nil
|
||||||
// SetValue: params.SetValue,
|
}
|
||||||
// })
|
|
||||||
// }),
|
// Add command with subcommands
|
||||||
// })
|
newCommand := internal.Command{
|
||||||
// return nil
|
Command: command.Command,
|
||||||
// }
|
Module: command.Module,
|
||||||
//
|
Categories: func() []string {
|
||||||
// // Add command with subcommands
|
// Convert all the categories to lower case for uniformity
|
||||||
// newCommand := internal.Command{
|
cats := make([]string, len(command.Categories))
|
||||||
// Command: command.Command,
|
for j, cat := range command.Categories {
|
||||||
// Module: command.Module,
|
cats[j] = strings.ToLower(cat)
|
||||||
// Categories: func() []string {
|
}
|
||||||
// // Convert all the categories to lower case for uniformity
|
return cats
|
||||||
// cats := make([]string, len(command.Categories))
|
}(),
|
||||||
// for j, cat := range command.Categories {
|
Description: command.Description,
|
||||||
// cats[j] = strings.ToLower(cat)
|
Sync: command.Sync,
|
||||||
// }
|
KeyExtractionFunc: func(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
||||||
// return cats
|
return internal.KeyExtractionFuncResult{}, nil
|
||||||
// }(),
|
},
|
||||||
// Description: command.Description,
|
HandlerFunc: func(param internal.HandlerFuncParams) ([]byte, error) { return nil, nil },
|
||||||
// Sync: command.Sync,
|
SubCommands: make([]internal.SubCommand, len(command.SubCommand)),
|
||||||
// KeyExtractionFunc: func(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
}
|
||||||
// return internal.KeyExtractionFuncResult{}, nil
|
|
||||||
// },
|
for i, sc := range command.SubCommand {
|
||||||
// HandlerFunc: func(param internal.HandlerFuncParams) ([]byte, error) { return nil, nil },
|
// Skip the subcommand if it already exists in newCommand
|
||||||
// SubCommands: make([]internal.SubCommand, len(command.SubCommand)),
|
if slices.ContainsFunc(newCommand.SubCommands, func(subcommand internal.SubCommand) bool {
|
||||||
// }
|
return strings.EqualFold(subcommand.Command, sc.Command)
|
||||||
//
|
}) {
|
||||||
// for i, sc := range command.SubCommand {
|
continue
|
||||||
// // Skip the subcommand if it already exists in newCommand
|
}
|
||||||
// if slices.ContainsFunc(newCommand.SubCommands, func(subcommand internal.SubCommand) bool {
|
newCommand.SubCommands[i] = internal.SubCommand{
|
||||||
// return strings.EqualFold(subcommand.Command, sc.Command)
|
Command: sc.Command,
|
||||||
// }) {
|
Module: strings.ToLower(command.Module),
|
||||||
// continue
|
Categories: func() []string {
|
||||||
// }
|
// Convert all the categories to lower case for uniformity
|
||||||
// newCommand.SubCommands[i] = internal.SubCommand{
|
cats := make([]string, len(sc.Categories))
|
||||||
// Command: sc.Command,
|
for j, cat := range sc.Categories {
|
||||||
// Module: strings.ToLower(command.Module),
|
cats[j] = strings.ToLower(cat)
|
||||||
// Categories: func() []string {
|
}
|
||||||
// // Convert all the categories to lower case for uniformity
|
return cats
|
||||||
// cats := make([]string, len(sc.Categories))
|
}(),
|
||||||
// for j, cat := range sc.Categories {
|
Description: sc.Description,
|
||||||
// cats[j] = strings.ToLower(cat)
|
Sync: sc.Sync,
|
||||||
// }
|
KeyExtractionFunc: internal.KeyExtractionFunc(func(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
||||||
// return cats
|
accessKeys, err := sc.KeyExtractionFunc(cmd)
|
||||||
// }(),
|
if err != nil {
|
||||||
// Description: sc.Description,
|
return internal.KeyExtractionFuncResult{}, err
|
||||||
// Sync: sc.Sync,
|
}
|
||||||
// KeyExtractionFunc: internal.KeyExtractionFunc(func(cmd []string) (internal.KeyExtractionFuncResult, error) {
|
return internal.KeyExtractionFuncResult{
|
||||||
// accessKeys, err := sc.KeyExtractionFunc(cmd)
|
Channels: []string{},
|
||||||
// if err != nil {
|
ReadKeys: accessKeys.ReadKeys,
|
||||||
// return internal.KeyExtractionFuncResult{}, err
|
WriteKeys: accessKeys.WriteKeys,
|
||||||
// }
|
}, nil
|
||||||
// return internal.KeyExtractionFuncResult{
|
}),
|
||||||
// Channels: []string{},
|
HandlerFunc: internal.HandlerFunc(func(params internal.HandlerFuncParams) ([]byte, error) {
|
||||||
// ReadKeys: accessKeys.ReadKeys,
|
return sc.HandlerFunc(CommandHandlerFuncParams{
|
||||||
// WriteKeys: accessKeys.WriteKeys,
|
Context: params.Context,
|
||||||
// }, nil
|
Command: params.Command,
|
||||||
// }),
|
KeysExist: params.KeysExist,
|
||||||
// HandlerFunc: internal.HandlerFunc(func(params internal.HandlerFuncParams) ([]byte, error) {
|
GetValues: params.GetValues,
|
||||||
// return sc.HandlerFunc(CommandHandlerFuncParams{
|
SetValues: params.SetValues,
|
||||||
// Context: params.Context,
|
})
|
||||||
// Command: params.Command,
|
}),
|
||||||
// KeyLock: params.KeyLock,
|
}
|
||||||
// KeyUnlock: params.KeyUnlock,
|
}
|
||||||
// KeyRLock: params.KeyRLock,
|
|
||||||
// KeyRUnlock: params.KeyRUnlock,
|
server.commands = append(server.commands, newCommand)
|
||||||
// KeyExists: params.KeyExists,
|
|
||||||
// CreateKeyAndLock: params.CreateKeyAndLock,
|
return nil
|
||||||
// GetValue: params.GetValue,
|
}
|
||||||
// SetValue: params.SetValue,
|
|
||||||
// })
|
|
||||||
// }),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// server.commands = append(server.commands, newCommand)
|
|
||||||
//
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ExecuteCommand executes the command passed to it. If 1 string is passed, EchoVault will try to
|
// ExecuteCommand executes the command passed to it. If 1 string is passed, EchoVault will try to
|
||||||
// execute the command. If 2 strings are passed, EchoVault will attempt to execute the subcommand of the command.
|
// execute the command. If 2 strings are passed, EchoVault will attempt to execute the subcommand of the command.
|
||||||
|
@@ -159,14 +159,13 @@ func NewEchoVault(options ...func(echovault *EchoVault)) (*EchoVault, error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Load .so modules from config
|
// Load .so modules from config
|
||||||
// TODO: Uncomment this
|
for _, path := range echovault.config.Modules {
|
||||||
// for _, path := range echovault.config.Modules {
|
if err := echovault.LoadModule(path); err != nil {
|
||||||
// if err := echovault.LoadModule(path); err != nil {
|
log.Printf("%s %v\n", path, err)
|
||||||
// log.Printf("%s %v\n", path, err)
|
continue
|
||||||
// continue
|
}
|
||||||
// }
|
log.Printf("loaded plugin %s\n", path)
|
||||||
// log.Printf("loaded plugin %s\n", path)
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// Function for server commands retrieval
|
// Function for server commands retrieval
|
||||||
echovault.getCommands = func() []internal.Command {
|
echovault.getCommands = func() []internal.Command {
|
||||||
|
@@ -40,14 +40,9 @@ func KeyExtractionFunc(cmd []string, args ...string) ([]string, []string, error)
|
|||||||
func HandlerFunc(
|
func HandlerFunc(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
command []string,
|
command []string,
|
||||||
keyExists func(ctx context.Context, key string) bool,
|
keysExist func(keys []string) map[string]bool,
|
||||||
keyLock func(ctx context.Context, key string) (bool, error),
|
getValues func(ctx context.Context, keys []string) map[string]interface{},
|
||||||
keyUnlock func(ctx context.Context, key string),
|
setValues func(ctx context.Context, entries map[string]interface{}) error,
|
||||||
keyRLock func(ctx context.Context, key string) (bool, error),
|
|
||||||
keyRUnlock func(ctx context.Context, key string),
|
|
||||||
createKeyAndLock func(ctx context.Context, key string) (bool, error),
|
|
||||||
getValue func(ctx context.Context, key string) interface{},
|
|
||||||
setValue func(ctx context.Context, key string, value interface{}) error,
|
|
||||||
args ...string) ([]byte, error) {
|
args ...string) ([]byte, error) {
|
||||||
|
|
||||||
readKeys, _, err := KeyExtractionFunc(command, args...)
|
readKeys, _, err := KeyExtractionFunc(command, args...)
|
||||||
@@ -55,18 +50,13 @@ func HandlerFunc(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
key := readKeys[0]
|
key := readKeys[0]
|
||||||
|
exists := keysExist(readKeys)[key]
|
||||||
|
|
||||||
if !keyExists(ctx, key) {
|
if !exists {
|
||||||
return []byte(":0\r\n"), nil
|
return []byte(":0\r\n"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = keyRLock(ctx, key)
|
val, ok := getValues(ctx, []string{key})[key].(int64)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer keyRUnlock(ctx, key)
|
|
||||||
|
|
||||||
val, ok := getValue(ctx, key).(int64)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("value at key %s is not an integer", key)
|
return nil, fmt.Errorf("value at key %s is not an integer", key)
|
||||||
}
|
}
|
||||||
|
@@ -40,14 +40,9 @@ func KeyExtractionFunc(cmd []string, args ...string) ([]string, []string, error)
|
|||||||
func HandlerFunc(
|
func HandlerFunc(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
command []string,
|
command []string,
|
||||||
keyExists func(ctx context.Context, key string) bool,
|
keysExist func(keys []string) map[string]bool,
|
||||||
keyLock func(ctx context.Context, key string) (bool, error),
|
getValues func(ctx context.Context, keys []string) map[string]interface{},
|
||||||
keyUnlock func(ctx context.Context, key string),
|
setValues func(ctx context.Context, entries map[string]interface{}) error,
|
||||||
keyRLock func(ctx context.Context, key string) (bool, error),
|
|
||||||
keyRUnlock func(ctx context.Context, key string),
|
|
||||||
createKeyAndLock func(ctx context.Context, key string) (bool, error),
|
|
||||||
getValue func(ctx context.Context, key string) interface{},
|
|
||||||
setValue func(ctx context.Context, key string, value interface{}) error,
|
|
||||||
args ...string) ([]byte, error) {
|
args ...string) ([]byte, error) {
|
||||||
|
|
||||||
_, writeKeys, err := KeyExtractionFunc(command, args...)
|
_, writeKeys, err := KeyExtractionFunc(command, args...)
|
||||||
@@ -56,25 +51,12 @@ func HandlerFunc(
|
|||||||
}
|
}
|
||||||
key := writeKeys[0]
|
key := writeKeys[0]
|
||||||
|
|
||||||
if !keyExists(ctx, key) {
|
|
||||||
_, err := createKeyAndLock(ctx, key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, err := keyLock(ctx, key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer keyUnlock(ctx, key)
|
|
||||||
|
|
||||||
value, err := strconv.ParseInt(command[2], 10, 64)
|
value, err := strconv.ParseInt(command[2], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = setValue(ctx, key, value)
|
err = setValues(ctx, map[string]interface{}{key: value})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user