Skip to content

Commit 6501a8b

Browse files
Implement FUNCTION group of commands (#2475)
* Implements function load, load replace and flush * Implements `FUNCTIONS LIST` * Fixes ineffectual assignment to err * Extends other tests from the `FUNCTION` group * Changes RdsFunction to Function * Renames FunctionList command, for consistency * Small fixes after review * More fixes after review * Implements the `LIBRARYNAME` and `WITHCODE` args for `FUNCTION LIST` * Implements `FUNCTION DUMP`. Solves #2396 * Use a pointer instead of value for `First()` * Implements `FUNCTION RESTORE`. Closes #2401. * chore: tidy code Signed-off-by: monkey92t <golang@88.com> --------- Signed-off-by: monkey92t <golang@88.com> Co-authored-by: monkey92t <golang@88.com>
1 parent cbfe6cd commit 6501a8b

File tree

3 files changed

+452
-0
lines changed

3 files changed

+452
-0
lines changed

command.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3840,3 +3840,155 @@ func (cmd *ZSliceWithKeyCmd) readReply(rd *proto.Reader) (err error) {
38403840

38413841
return nil
38423842
}
3843+
3844+
type Function struct {
3845+
Name string
3846+
Description string
3847+
Flags []string
3848+
}
3849+
3850+
type Library struct {
3851+
Name string
3852+
Engine string
3853+
Functions []Function
3854+
Code string
3855+
}
3856+
3857+
type FunctionListCmd struct {
3858+
baseCmd
3859+
3860+
val []Library
3861+
}
3862+
3863+
var _ Cmder = (*FunctionListCmd)(nil)
3864+
3865+
func NewFunctionListCmd(ctx context.Context, args ...interface{}) *FunctionListCmd {
3866+
return &FunctionListCmd{
3867+
baseCmd: baseCmd{
3868+
ctx: ctx,
3869+
args: args,
3870+
},
3871+
}
3872+
}
3873+
3874+
func (cmd *FunctionListCmd) SetVal(val []Library) {
3875+
cmd.val = val
3876+
}
3877+
3878+
func (cmd *FunctionListCmd) String() string {
3879+
return cmdString(cmd, cmd.val)
3880+
}
3881+
3882+
func (cmd *FunctionListCmd) Val() []Library {
3883+
return cmd.val
3884+
}
3885+
3886+
func (cmd *FunctionListCmd) Result() ([]Library, error) {
3887+
return cmd.val, cmd.err
3888+
}
3889+
3890+
func (cmd *FunctionListCmd) First() (*Library, error) {
3891+
if cmd.err != nil {
3892+
return nil, cmd.err
3893+
}
3894+
if len(cmd.val) > 0 {
3895+
return &cmd.val[0], nil
3896+
}
3897+
return nil, Nil
3898+
}
3899+
3900+
func (cmd *FunctionListCmd) readReply(rd *proto.Reader) (err error) {
3901+
n, err := rd.ReadArrayLen()
3902+
if err != nil {
3903+
return err
3904+
}
3905+
3906+
libraries := make([]Library, n)
3907+
for i := 0; i < n; i++ {
3908+
nn, err := rd.ReadMapLen()
3909+
if err != nil {
3910+
return err
3911+
}
3912+
3913+
library := Library{}
3914+
for f := 0; f < nn; f++ {
3915+
key, err := rd.ReadString()
3916+
if err != nil {
3917+
return err
3918+
}
3919+
3920+
switch key {
3921+
case "library_name":
3922+
library.Name, err = rd.ReadString()
3923+
case "engine":
3924+
library.Engine, err = rd.ReadString()
3925+
case "functions":
3926+
library.Functions, err = cmd.readFunctions(rd)
3927+
case "library_code":
3928+
library.Code, err = rd.ReadString()
3929+
default:
3930+
return fmt.Errorf("redis: function list unexpected key %s", key)
3931+
}
3932+
3933+
if err != nil {
3934+
return err
3935+
}
3936+
}
3937+
3938+
libraries[i] = library
3939+
}
3940+
cmd.val = libraries
3941+
return nil
3942+
}
3943+
3944+
func (cmd *FunctionListCmd) readFunctions(rd *proto.Reader) ([]Function, error) {
3945+
n, err := rd.ReadArrayLen()
3946+
if err != nil {
3947+
return nil, err
3948+
}
3949+
3950+
functions := make([]Function, n)
3951+
for i := 0; i < n; i++ {
3952+
nn, err := rd.ReadMapLen()
3953+
if err != nil {
3954+
return nil, err
3955+
}
3956+
3957+
function := Function{}
3958+
for f := 0; f < nn; f++ {
3959+
key, err := rd.ReadString()
3960+
if err != nil {
3961+
return nil, err
3962+
}
3963+
3964+
switch key {
3965+
case "name":
3966+
if function.Name, err = rd.ReadString(); err != nil {
3967+
return nil, err
3968+
}
3969+
case "description":
3970+
if function.Description, err = rd.ReadString(); err != nil && err != Nil {
3971+
return nil, err
3972+
}
3973+
case "flags":
3974+
// resp set
3975+
nx, err := rd.ReadArrayLen()
3976+
if err != nil {
3977+
return nil, err
3978+
}
3979+
3980+
function.Flags = make([]string, nx)
3981+
for j := 0; j < nx; j++ {
3982+
if function.Flags[j], err = rd.ReadString(); err != nil {
3983+
return nil, err
3984+
}
3985+
}
3986+
default:
3987+
return nil, fmt.Errorf("redis: function list unexpected key %s", key)
3988+
}
3989+
}
3990+
3991+
functions[i] = function
3992+
}
3993+
return functions, nil
3994+
}

commands.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,15 @@ type Cmdable interface {
395395
ScriptKill(ctx context.Context) *StatusCmd
396396
ScriptLoad(ctx context.Context, script string) *StringCmd
397397

398+
FunctionLoad(ctx context.Context, code string) *StringCmd
399+
FunctionLoadReplace(ctx context.Context, code string) *StringCmd
400+
FunctionDelete(ctx context.Context, libName string) *StringCmd
401+
FunctionFlush(ctx context.Context) *StringCmd
402+
FunctionFlushAsync(ctx context.Context) *StringCmd
403+
FunctionList(ctx context.Context, q FunctionListQuery) *FunctionListCmd
404+
FunctionDump(ctx context.Context) *StringCmd
405+
FunctionRestore(ctx context.Context, libDump string) *StringCmd
406+
398407
Publish(ctx context.Context, channel string, message interface{}) *IntCmd
399408
SPublish(ctx context.Context, channel string, message interface{}) *IntCmd
400409
PubSubChannels(ctx context.Context, pattern string) *StringSliceCmd
@@ -3270,6 +3279,76 @@ func (c cmdable) ScriptLoad(ctx context.Context, script string) *StringCmd {
32703279
return cmd
32713280
}
32723281

3282+
// ------------------------------------------------------------------------------
3283+
3284+
// FunctionListQuery is used with FunctionList to query for Redis libraries
3285+
//
3286+
// LibraryNamePattern - Use an empty string to get all libraries.
3287+
// - Use a glob-style pattern to match multiple libraries with a matching name
3288+
// - Use a library's full name to match a single library
3289+
// WithCode - If true, it will return the code of the library
3290+
type FunctionListQuery struct {
3291+
LibraryNamePattern string
3292+
WithCode bool
3293+
}
3294+
3295+
func (c cmdable) FunctionLoad(ctx context.Context, code string) *StringCmd {
3296+
cmd := NewStringCmd(ctx, "function", "load", code)
3297+
_ = c(ctx, cmd)
3298+
return cmd
3299+
}
3300+
3301+
func (c cmdable) FunctionLoadReplace(ctx context.Context, code string) *StringCmd {
3302+
cmd := NewStringCmd(ctx, "function", "load", "replace", code)
3303+
_ = c(ctx, cmd)
3304+
return cmd
3305+
}
3306+
3307+
func (c cmdable) FunctionDelete(ctx context.Context, libName string) *StringCmd {
3308+
cmd := NewStringCmd(ctx, "function", "delete", libName)
3309+
_ = c(ctx, cmd)
3310+
return cmd
3311+
}
3312+
3313+
func (c cmdable) FunctionFlush(ctx context.Context) *StringCmd {
3314+
cmd := NewStringCmd(ctx, "function", "flush")
3315+
_ = c(ctx, cmd)
3316+
return cmd
3317+
}
3318+
3319+
func (c cmdable) FunctionFlushAsync(ctx context.Context) *StringCmd {
3320+
cmd := NewStringCmd(ctx, "function", "flush", "async")
3321+
_ = c(ctx, cmd)
3322+
return cmd
3323+
}
3324+
3325+
func (c cmdable) FunctionList(ctx context.Context, q FunctionListQuery) *FunctionListCmd {
3326+
args := make([]interface{}, 2, 5)
3327+
args[0] = "function"
3328+
args[1] = "list"
3329+
if q.LibraryNamePattern != "" {
3330+
args = append(args, "libraryname", q.LibraryNamePattern)
3331+
}
3332+
if q.WithCode {
3333+
args = append(args, "withcode")
3334+
}
3335+
cmd := NewFunctionListCmd(ctx, args...)
3336+
_ = c(ctx, cmd)
3337+
return cmd
3338+
}
3339+
3340+
func (c cmdable) FunctionDump(ctx context.Context) *StringCmd {
3341+
cmd := NewStringCmd(ctx, "function", "dump")
3342+
_ = c(ctx, cmd)
3343+
return cmd
3344+
}
3345+
3346+
func (c cmdable) FunctionRestore(ctx context.Context, libDump string) *StringCmd {
3347+
cmd := NewStringCmd(ctx, "function", "restore", libDump)
3348+
_ = c(ctx, cmd)
3349+
return cmd
3350+
}
3351+
32733352
//------------------------------------------------------------------------------
32743353

32753354
// Publish posts the message to the channel.

0 commit comments

Comments
 (0)