Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for MODULE LOADEX command #2490

Merged
merged 12 commits into from
Apr 18, 2023
31 changes: 31 additions & 0 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,8 @@ type Cmdable interface {
GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd

ACLDryRun(ctx context.Context, username string, command ...interface{}) *StringCmd

ModuleLoadex(ctx context.Context, conf *ModuleLoadexConfig) *StringCmd
}

type StatefulCmdable interface {
Expand Down Expand Up @@ -3873,3 +3875,32 @@ func (c cmdable) ACLDryRun(ctx context.Context, username string, command ...inte
_ = c(ctx, cmd)
return cmd
}

// ModuleLoadexConfig struct is used to specify the arguments for the MODULE LOADEX command of redis.
// `MODULE LOADEX path [CONFIG name value [CONFIG name value ...]] [ARGS args [args ...]]`
type ModuleLoadexConfig struct {
Path string
Conf map[string]interface{}
Args []interface{}
}

func (c *ModuleLoadexConfig) ToArgs() []interface{} {
args := make([]interface{}, 3, 3+len(c.Conf)*3+len(c.Args)*2)
args[0] = "MODULE"
args[1] = "LOADEX"
args[2] = c.Path
for k, v := range c.Conf {
args = append(args, "CONFIG", k, v)
}
for _, arg := range c.Args {
args = append(args, "ARGS", arg)
}
return args
}

// ModuleLoadex Redis `MODULE LOADEX path [CONFIG name value [CONFIG name value ...]] [ARGS args [args ...]]` command.
func (c cmdable) ModuleLoadex(ctx context.Context, conf *ModuleLoadexConfig) *StringCmd {
cmd := NewStringCmd(ctx, conf.ToArgs()...)
_ = c(ctx, cmd)
return cmd
}
50 changes: 49 additions & 1 deletion commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1926,11 +1926,59 @@ var _ = Describe("Commands", func() {
Expect(replace.Val()).To(Equal(int64(1)))
})

It("should acl dryryn", func() {
It("should acl dryrun", func() {
dryRun := client.ACLDryRun(ctx, "default", "get", "randomKey")
Expect(dryRun.Err()).NotTo(HaveOccurred())
Expect(dryRun.Val()).To(Equal("OK"))
})

It("should fail module loadex", func() {
dryRun := client.ModuleLoadex(ctx, &redis.ModuleLoadexConfig{
Path: "/path/to/non-existent-library.so",
Conf: map[string]interface{}{
"param1": "value1",
},
Args: []interface{}{
"arg1",
},
})
Expect(dryRun.Err()).To(HaveOccurred())
Expect(dryRun.Err().Error()).To(Equal("ERR Error loading the extension. Please check the server logs."))
})

It("converts the module loadex configuration to a slice of arguments correctly", func() {
conf := &redis.ModuleLoadexConfig{
Path: "/path/to/your/module.so",
Conf: map[string]interface{}{
"param1": "value1",
},
Args: []interface{}{
"arg1",
"arg2",
3,
},
}

args := conf.ToArgs()

// Test if the arguments are in the correct order
expectedArgs := []interface{}{
"MODULE",
"LOADEX",
"/path/to/your/module.so",
"CONFIG",
"param1",
"value1",
"ARGS",
"arg1",
"ARGS",
"arg2",
"ARGS",
3,
}

Expect(args).To(Equal(expectedArgs))
})
})

Describe("hashes", func() {
Expand Down
2 changes: 1 addition & 1 deletion main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ func startRedis(port string, args ...string) (*redisProcess, error) {
return nil, err
}

baseArgs := []string{filepath.Join(dir, "redis.conf"), "--port", port, "--dir", dir}
baseArgs := []string{filepath.Join(dir, "redis.conf"), "--port", port, "--dir", dir, "--enable-module-command", "yes"}
process, err := execCmd(redisServerBin, append(baseArgs, args...)...)
if err != nil {
return nil, err
Expand Down