From 3b0d10b4ed8c453383170b54891daa3fa1d396ed Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Thu, 14 Sep 2023 18:54:23 +0530 Subject: [PATCH] Support for CLIENT SETINFO (#2659) * feat: merge master * feat: revert ring.go * feat: add ClientSetInfo command * fix: test and cmd: * fix: test and cmd * fix: test and cmd * fix: test and cmd * feat: redesigning the API * fix: panic test * fix: panic test --------- Co-authored-by: Anuragkillswitch <70265851+Anuragkillswitch@users.noreply.github.com> Co-authored-by: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com> --- command.go | 6 ++++++ commands.go | 30 ++++++++++++++++++++++++++++ commands_test.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/command.go b/command.go index 549322a9..1700b328 100644 --- a/command.go +++ b/command.go @@ -5292,3 +5292,9 @@ func (cmd *ACLLogCmd) readReply(rd *proto.Reader) error { return nil } + +// LibraryInfo holds the library info. +type LibraryInfo struct { + LibName *string + LibVer *string +} diff --git a/commands.go b/commands.go index ce383025..4a3cd9ac 100644 --- a/commands.go +++ b/commands.go @@ -517,6 +517,7 @@ type StatefulCmdable interface { Select(ctx context.Context, index int) *StatusCmd SwapDB(ctx context.Context, index1, index2 int) *StatusCmd ClientSetName(ctx context.Context, name string) *BoolCmd + ClientSetInfo(ctx context.Context, info LibraryInfo) *StatusCmd Hello(ctx context.Context, ver int, username, password, clientName string) *MapStringInterfaceCmd } @@ -574,6 +575,35 @@ func (c statefulCmdable) ClientSetName(ctx context.Context, name string) *BoolCm return cmd } +// ClientSetInfo sends a CLIENT SETINFO command with the provided info. +func (c statefulCmdable) ClientSetInfo(ctx context.Context, info LibraryInfo) *StatusCmd { + err := info.Validate() + if err != nil { + panic(err.Error()) + } + + var cmd *StatusCmd + if info.LibName != nil { + cmd = NewStatusCmd(ctx, "client", "setinfo", "LIB-NAME", *info.LibName) + } else { + cmd = NewStatusCmd(ctx, "client", "setinfo", "LIB-VER", *info.LibVer) + } + + _ = c(ctx, cmd) + return cmd +} + +// Validate checks if only one field in the struct is non-nil. +func (info LibraryInfo) Validate() error { + if info.LibName != nil && info.LibVer != nil { + return errors.New("both LibName and LibVer cannot be set at the same time") + } + if info.LibName == nil && info.LibVer == nil { + return errors.New("at least one of LibName and LibVer should be set") + } + return nil +} + // Hello Set the resp protocol used. func (c statefulCmdable) Hello(ctx context.Context, ver int, username, password, clientName string) *MapStringInterfaceCmd { diff --git a/commands_test.go b/commands_test.go index f88cb21e..c8ea0f7b 100644 --- a/commands_test.go +++ b/commands_test.go @@ -231,6 +231,57 @@ var _ = Describe("Commands", func() { Expect(get.Val()).To(Equal("theclientname")) }) + It("should ClientSetInfo", func() { + + pipe := client.Pipeline() + + // Test setting the libName + libName := "go-redis" + libInfo := redis.LibraryInfo{LibName: &libName} + setInfo := pipe.ClientSetInfo(ctx, libInfo) + _, err := pipe.Exec(ctx) + + Expect(err).NotTo(HaveOccurred()) + Expect(setInfo.Err()).NotTo(HaveOccurred()) + Expect(setInfo.Val()).To(Equal("OK")) + + // Test setting the libVer + libVer := "vX.x" + libInfo = redis.LibraryInfo{LibVer: &libVer} + setInfo = pipe.ClientSetInfo(ctx, libInfo) + _, err = pipe.Exec(ctx) + + Expect(err).NotTo(HaveOccurred()) + Expect(setInfo.Err()).NotTo(HaveOccurred()) + Expect(setInfo.Val()).To(Equal("OK")) + + // Test setting both fields, expect a panic + libInfo = redis.LibraryInfo{LibName: &libName, LibVer: &libVer} + + Expect(func() { + defer func() { + if r := recover(); r != nil { + err := r.(error) + Expect(err).To(MatchError("both LibName and LibVer cannot be set at the same time")) + } + }() + pipe.ClientSetInfo(ctx, libInfo) + }).To(Panic()) + + // Test setting neither field, expect a panic + libInfo = redis.LibraryInfo{} + + Expect(func() { + defer func() { + if r := recover(); r != nil { + err := r.(error) + Expect(err).To(MatchError("at least one of LibName and LibVer should be set")) + } + }() + pipe.ClientSetInfo(ctx, libInfo) + }).To(Panic()) + }) + It("should ConfigGet", func() { val, err := client.ConfigGet(ctx, "*").Result() Expect(err).NotTo(HaveOccurred())