From a1093022305ba41faea800104418811d4a0befdf Mon Sep 17 00:00:00 2001 From: RyoMiyashita Date: Sun, 10 Dec 2023 19:04:13 +0900 Subject: [PATCH 01/11] fix: #2730 data race at hooksMixin (#2814) --- redis.go | 13 +++++++++++++ redis_test.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/redis.go b/redis.go index 9430eb75..9792af76 100644 --- a/redis.go +++ b/redis.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net" + "sync" "sync/atomic" "time" @@ -40,12 +41,15 @@ type ( ) type hooksMixin struct { + hooksMu *sync.Mutex + slice []Hook initial hooks current hooks } func (hs *hooksMixin) initHooks(hooks hooks) { + hs.hooksMu = new(sync.Mutex) hs.initial = hooks hs.chain() } @@ -116,6 +120,9 @@ func (hs *hooksMixin) AddHook(hook Hook) { func (hs *hooksMixin) chain() { hs.initial.setDefaults() + hs.hooksMu.Lock() + defer hs.hooksMu.Unlock() + hs.current.dial = hs.initial.dial hs.current.process = hs.initial.process hs.current.pipeline = hs.initial.pipeline @@ -138,9 +145,13 @@ func (hs *hooksMixin) chain() { } func (hs *hooksMixin) clone() hooksMixin { + hs.hooksMu.Lock() + defer hs.hooksMu.Unlock() + clone := *hs l := len(clone.slice) clone.slice = clone.slice[:l:l] + clone.hooksMu = new(sync.Mutex) return clone } @@ -165,6 +176,8 @@ func (hs *hooksMixin) withProcessPipelineHook( } func (hs *hooksMixin) dialHook(ctx context.Context, network, addr string) (net.Conn, error) { + hs.hooksMu.Lock() + defer hs.hooksMu.Unlock() return hs.current.dial(ctx, network, addr) } diff --git a/redis_test.go b/redis_test.go index 5870fad7..728f6c29 100644 --- a/redis_test.go +++ b/redis_test.go @@ -579,3 +579,53 @@ var _ = Describe("Hook", func() { Expect(cmd.Val()).To(Equal("Script and hook")) }) }) + +var _ = Describe("Hook with MinIdleConns", func() { + var client *redis.Client + + BeforeEach(func() { + options := redisOptions() + options.MinIdleConns = 1 + client = redis.NewClient(options) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + err := client.Close() + Expect(err).NotTo(HaveOccurred()) + }) + + It("fifo", func() { + var res []string + client.AddHook(&hook{ + processHook: func(hook redis.ProcessHook) redis.ProcessHook { + return func(ctx context.Context, cmd redis.Cmder) error { + res = append(res, "hook-1-process-start") + err := hook(ctx, cmd) + res = append(res, "hook-1-process-end") + return err + } + }, + }) + client.AddHook(&hook{ + processHook: func(hook redis.ProcessHook) redis.ProcessHook { + return func(ctx context.Context, cmd redis.Cmder) error { + res = append(res, "hook-2-process-start") + err := hook(ctx, cmd) + res = append(res, "hook-2-process-end") + return err + } + }, + }) + + err := client.Ping(ctx).Err() + Expect(err).NotTo(HaveOccurred()) + + Expect(res).To(Equal([]string{ + "hook-1-process-start", + "hook-2-process-start", + "hook-2-process-end", + "hook-1-process-end", + })) + }) +}) From 2fc48987d1094976a7708c27be13202ff82ee273 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:54:06 +0200 Subject: [PATCH 02/11] chore(deps): bump actions/setup-go from 4 to 5 (#2829) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- .github/workflows/doctests.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 231233f7..4061bbdf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ jobs: steps: - name: Set up ${{ matrix.go-version }} - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} diff --git a/.github/workflows/doctests.yaml b/.github/workflows/doctests.yaml index 708dfcd3..6e49e647 100644 --- a/.github/workflows/doctests.yaml +++ b/.github/workflows/doctests.yaml @@ -29,7 +29,7 @@ jobs: steps: - name: Set up ${{ matrix.go-version }} - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} From 9372018b510844eecc1da6428140348b7bb3095b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:54:20 +0200 Subject: [PATCH 03/11] chore(deps): bump actions/stale from 8 to 9 (#2828) Bumps [actions/stale](https://github.com/actions/stale) from 8 to 9. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v8...v9) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale-issues.yml b/.github/workflows/stale-issues.yml index b3776d70..445af1c8 100644 --- a/.github/workflows/stale-issues.yml +++ b/.github/workflows/stale-issues.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue is marked stale. It will be closed in 30 days if it is not updated.' From 6ddf27879e9a3cac946d0ab7caf7d2afb4120065 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:56:17 +0200 Subject: [PATCH 04/11] chore(deps): bump rojopolis/spellcheck-github-actions from 0.34.0 to 0.35.0 (#2807) Bumps [rojopolis/spellcheck-github-actions](https://github.com/rojopolis/spellcheck-github-actions) from 0.34.0 to 0.35.0. - [Release notes](https://github.com/rojopolis/spellcheck-github-actions/releases) - [Changelog](https://github.com/rojopolis/spellcheck-github-actions/blob/master/CHANGELOG.md) - [Commits](https://github.com/rojopolis/spellcheck-github-actions/compare/0.34.0...0.35.0) --- updated-dependencies: - dependency-name: rojopolis/spellcheck-github-actions dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chayim --- .github/workflows/spellcheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index 46c629b2..a48781aa 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -8,7 +8,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Check Spelling - uses: rojopolis/spellcheck-github-actions@0.34.0 + uses: rojopolis/spellcheck-github-actions@0.35.0 with: config_path: .github/spellcheck-settings.yml task_name: Markdown From 631deaf25f822c01e78f0fa8843fe8ce9ed2b298 Mon Sep 17 00:00:00 2001 From: Lev Zakharov Date: Sun, 17 Dec 2023 13:13:01 +0300 Subject: [PATCH 05/11] test: fix WriteArg test (#2808) --- internal/proto/writer_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/proto/writer_test.go b/internal/proto/writer_test.go index 55f3d663..7c9d2088 100644 --- a/internal/proto/writer_test.go +++ b/internal/proto/writer_test.go @@ -112,7 +112,7 @@ var _ = Describe("WriteArg", func() { }) args := map[any]string{ - "hello": "$1\r\nhello\r\n", + "hello": "$5\r\nhello\r\n", int(10): "$2\r\n10\r\n", util.ToPtr(int(10)): "$2\r\n10\r\n", int8(10): "$2\r\n10\r\n", @@ -133,8 +133,8 @@ var _ = Describe("WriteArg", func() { util.ToPtr(uint32(10)): "$2\r\n10\r\n", uint64(10): "$2\r\n10\r\n", util.ToPtr(uint64(10)): "$2\r\n10\r\n", - float32(10.3): "$4\r\n10.3\r\n", - util.ToPtr(float32(10.3)): "$4\r\n10.3\r\n", + float32(10.3): "$18\r\n10.300000190734863\r\n", + util.ToPtr(float32(10.3)): "$18\r\n10.300000190734863\r\n", float64(10.3): "$4\r\n10.3\r\n", util.ToPtr(float64(10.3)): "$4\r\n10.3\r\n", bool(true): "$1\r\n1\r\n", @@ -144,6 +144,7 @@ var _ = Describe("WriteArg", func() { } for arg, expect := range args { + arg, expect := arg, expect It(fmt.Sprintf("should write arg of type %T", arg), func() { err := wr.WriteArg(arg) Expect(err).NotTo(HaveOccurred()) From 277e8b7d9f9c5c5dc5690e0e11a029278bb25297 Mon Sep 17 00:00:00 2001 From: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com> Date: Sun, 17 Dec 2023 12:35:10 +0200 Subject: [PATCH 06/11] Support Monitor Command (#2830) * Add monitor command * Add monitor commadn and tests * insure goroutine shutdown * fix data race * linting * change timeout explanation --------- Co-authored-by: Chayim --- command.go | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ commands.go | 18 ++++++++++- main_test.go | 5 +++ monitor_test.go | 48 ++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 monitor_test.go diff --git a/command.go b/command.go index c641a3fa..ea1bd927 100644 --- a/command.go +++ b/command.go @@ -8,6 +8,7 @@ import ( "regexp" "strconv" "strings" + "sync" "time" "github.com/redis/go-redis/v9/internal" @@ -5381,3 +5382,85 @@ func (cmd *InfoCmd) Item(section, key string) string { return cmd.val[section][key] } } + +type MonitorStatus int + +const ( + monitorStatusIdle MonitorStatus = iota + monitorStatusStart + monitorStatusStop +) + +type MonitorCmd struct { + baseCmd + ch chan string + status MonitorStatus + mu sync.Mutex +} + +func newMonitorCmd(ctx context.Context, ch chan string) *MonitorCmd { + return &MonitorCmd{ + baseCmd: baseCmd{ + ctx: ctx, + args: []interface{}{"monitor"}, + }, + ch: ch, + status: monitorStatusIdle, + mu: sync.Mutex{}, + } +} + +func (cmd *MonitorCmd) String() string { + return cmdString(cmd, nil) +} + +func (cmd *MonitorCmd) readReply(rd *proto.Reader) error { + ctx, cancel := context.WithCancel(cmd.ctx) + go func(ctx context.Context) { + for { + select { + case <-ctx.Done(): + return + default: + err := cmd.readMonitor(rd, cancel) + if err != nil { + cmd.err = err + return + } + } + } + }(ctx) + return nil +} + +func (cmd *MonitorCmd) readMonitor(rd *proto.Reader, cancel context.CancelFunc) error { + for { + cmd.mu.Lock() + st := cmd.status + cmd.mu.Unlock() + if pk, _ := rd.Peek(1); len(pk) != 0 && st == monitorStatusStart { + line, err := rd.ReadString() + if err != nil { + return err + } + cmd.ch <- line + } + if st == monitorStatusStop { + cancel() + break + } + } + return nil +} + +func (cmd *MonitorCmd) Start() { + cmd.mu.Lock() + defer cmd.mu.Unlock() + cmd.status = monitorStatusStart +} + +func (cmd *MonitorCmd) Stop() { + cmd.mu.Lock() + defer cmd.mu.Unlock() + cmd.status = monitorStatusStop +} diff --git a/commands.go b/commands.go index 842cc23a..546ebafb 100644 --- a/commands.go +++ b/commands.go @@ -204,7 +204,6 @@ type Cmdable interface { SlowLogGet(ctx context.Context, num int64) *SlowLogCmd Time(ctx context.Context) *TimeCmd DebugObject(ctx context.Context, key string) *StringCmd - MemoryUsage(ctx context.Context, key string, samples ...int) *IntCmd ModuleLoadex(ctx context.Context, conf *ModuleLoadexConfig) *StringCmd @@ -700,3 +699,20 @@ func (c cmdable) ModuleLoadex(ctx context.Context, conf *ModuleLoadexConfig) *St _ = c(ctx, cmd) return cmd } + +/* +Monitor - represents a Redis MONITOR command, allowing the user to capture +and process all commands sent to a Redis server. This mimics the behavior of +MONITOR in the redis-cli. + +Notes: +- Using MONITOR blocks the connection to the server for itself. It needs a dedicated connection +- The user should create a channel of type string +- This runs concurrently in the background. Trigger via the Start and Stop functions +See further: Redis MONITOR command: https://redis.io/commands/monitor +*/ +func (c cmdable) Monitor(ctx context.Context, ch chan string) *MonitorCmd { + cmd := newMonitorCmd(ctx, ch) + _ = c(ctx, cmd) + return cmd +} diff --git a/main_test.go b/main_test.go index 6aaaf1c0..1a1660c9 100644 --- a/main_test.go +++ b/main_test.go @@ -41,6 +41,11 @@ var ( redisAddr = ":" + redisPort ) +var ( + rediStackPort = "6379" + rediStackAddr = ":" + rediStackPort +) + var ( sentinelAddrs = []string{":" + sentinelPort1, ":" + sentinelPort2, ":" + sentinelPort3} diff --git a/monitor_test.go b/monitor_test.go new file mode 100644 index 00000000..1bc82eca --- /dev/null +++ b/monitor_test.go @@ -0,0 +1,48 @@ +package redis_test + +import ( + "context" + "time" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + + "github.com/redis/go-redis/v9" +) + +var _ = Describe("Monitor command", Label("monitor"), func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(&redis.Options{Addr: ":6379"}) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + It("should monitor", Label("monitor"), func() { + ress := make(chan string) + client1 := redis.NewClient(&redis.Options{Addr: rediStackAddr}) + mn := client1.Monitor(ctx, ress) + mn.Start() + // Wait for the Redis server to be in monitoring mode. + time.Sleep(100 * time.Millisecond) + client.Set(ctx, "foo", "bar", 0) + client.Set(ctx, "bar", "baz", 0) + client.Set(ctx, "bap", 8, 0) + client.Get(ctx, "bap") + lst := []string{} + for i := 0; i < 5; i++ { + s := <-ress + lst = append(lst, s) + } + mn.Stop() + Expect(lst[0]).To(ContainSubstring("OK")) + Expect(lst[1]).To(ContainSubstring(`"set" "foo" "bar"`)) + Expect(lst[2]).To(ContainSubstring(`"set" "bar" "baz"`)) + Expect(lst[3]).To(ContainSubstring(`"set" "bap" "8"`)) + }) +}) From 1d784578dfea5d9a33a7b0fc0d989cc929c98f2b Mon Sep 17 00:00:00 2001 From: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com> Date: Sun, 17 Dec 2023 15:19:27 +0200 Subject: [PATCH 07/11] Add BITFIELD_RO Command (#2820) Co-authored-by: Chayim --- bitmap_commands.go | 22 +++++++++++++++++++++- commands_test.go | 14 ++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/bitmap_commands.go b/bitmap_commands.go index 1436b02a..550d7f52 100644 --- a/bitmap_commands.go +++ b/bitmap_commands.go @@ -1,6 +1,8 @@ package redis -import "context" +import ( + "context" +) type BitMapCmdable interface { GetBit(ctx context.Context, key string, offset int64) *IntCmd @@ -127,3 +129,21 @@ func (c cmdable) BitField(ctx context.Context, key string, values ...interface{} _ = c(ctx, cmd) return cmd } + +// BitFieldRO - Read-only variant of the BITFIELD command. +// It is like the original BITFIELD but only accepts GET subcommand and can safely be used in read-only replicas. +// - BitFieldRO(ctx, key, "", "", "","") +func (c cmdable) BitFieldRO(ctx context.Context, key string, values ...interface{}) *IntSliceCmd { + args := make([]interface{}, 2, 2+len(values)) + args[0] = "BITFIELD_RO" + args[1] = key + if len(values)%2 != 0 { + panic("BitFieldRO: invalid number of arguments, must be even") + } + for i := 0; i < len(values); i += 2 { + args = append(args, "GET", values[i], values[i+1]) + } + cmd := NewIntSliceCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd +} diff --git a/commands_test.go b/commands_test.go index fdc41c5a..f36e9d94 100644 --- a/commands_test.go +++ b/commands_test.go @@ -1279,6 +1279,20 @@ var _ = Describe("Commands", func() { Expect(nn).To(Equal([]int64{0, 4})) }) + It("should BitFieldRO", func() { + nn, err := client.BitField(ctx, "mykey", "SET", "u8", 8, 255).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(nn).To(Equal([]int64{0})) + + nn, err = client.BitFieldRO(ctx, "mykey", "u8", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(nn).To(Equal([]int64{0})) + + nn, err = client.BitFieldRO(ctx, "mykey", "u8", 0, "u4", 8, "u4", 12, "u4", 13).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(nn).To(Equal([]int64{0, 15, 15, 14})) + }) + It("should Decr", func() { set := client.Set(ctx, "key", "10", 0) Expect(set.Err()).NotTo(HaveOccurred()) From e535124055c53d281390d3ec5957e437a885430d Mon Sep 17 00:00:00 2001 From: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com> Date: Sun, 17 Dec 2023 15:20:01 +0200 Subject: [PATCH 08/11] Change Z member to string (#2818) --- commands_test.go | 8 ++++---- sortedset_commands.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/commands_test.go b/commands_test.go index f36e9d94..309ba1eb 100644 --- a/commands_test.go +++ b/commands_test.go @@ -3722,28 +3722,28 @@ var _ = Describe("Commands", func() { It("should ZAdd bytes", func() { added, err := client.ZAdd(ctx, "zset", redis.Z{ Score: 1, - Member: []byte("one"), + Member: "one", }).Result() Expect(err).NotTo(HaveOccurred()) Expect(added).To(Equal(int64(1))) added, err = client.ZAdd(ctx, "zset", redis.Z{ Score: 1, - Member: []byte("uno"), + Member: "uno", }).Result() Expect(err).NotTo(HaveOccurred()) Expect(added).To(Equal(int64(1))) added, err = client.ZAdd(ctx, "zset", redis.Z{ Score: 2, - Member: []byte("two"), + Member: "two", }).Result() Expect(err).NotTo(HaveOccurred()) Expect(added).To(Equal(int64(1))) added, err = client.ZAdd(ctx, "zset", redis.Z{ Score: 3, - Member: []byte("two"), + Member: "two", }).Result() Expect(err).NotTo(HaveOccurred()) Expect(added).To(Equal(int64(0))) diff --git a/sortedset_commands.go b/sortedset_commands.go index 67014027..7e96e1eb 100644 --- a/sortedset_commands.go +++ b/sortedset_commands.go @@ -727,7 +727,7 @@ func (c cmdable) ZScan(ctx context.Context, key string, cursor uint64, match str // Z represents sorted set member. type Z struct { Score float64 - Member interface{} + Member string } // ZWithKey represents sorted set member including the name of the key where it was popped. From 8c695488a247283d92e4d03c1774d9e2c4583244 Mon Sep 17 00:00:00 2001 From: "fengyun.rui" Date: Sun, 17 Dec 2023 21:20:23 +0800 Subject: [PATCH 09/11] fix: add Cmder annotation (#2816) * fix: add Cmder annotation Signed-off-by: rfyiamcool * fix: add Cmder annotation Signed-off-by: rfyiamcool --------- Signed-off-by: rfyiamcool Co-authored-by: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com> --- command.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/command.go b/command.go index ea1bd927..3dd475fa 100644 --- a/command.go +++ b/command.go @@ -18,10 +18,22 @@ import ( ) type Cmder interface { + // command name. + // e.g. "set k v ex 10" -> "set", "cluster info" -> "cluster". Name() string + + // full command name. + // e.g. "set k v ex 10" -> "set", "cluster info" -> "cluster info". FullName() string + + // all args of the command. + // e.g. "set k v ex 10" -> "[set k v ex 10]". Args() []interface{} + + // format request and response string. + // e.g. "set k v ex 10" -> "set k v ex 10: OK", "get k" -> "get k: v". String() string + stringArg(int) string firstKeyPos() int8 SetFirstKeyPos(int8) From 86c68be278a8541f6419513940ffaefa45341e78 Mon Sep 17 00:00:00 2001 From: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com> Date: Sun, 17 Dec 2023 15:21:01 +0200 Subject: [PATCH 10/11] Execute "COMMAND" command only when readonly (#2815) * remove command command from oss cluster * remove command command from oss cluster * remove cmdInfo from ring --------- Co-authored-by: Chayim --- bench_decode_test.go | 8 -------- command.go | 6 +----- osscluster.go | 15 ++++++++------- ring.go | 18 ++---------------- 4 files changed, 11 insertions(+), 36 deletions(-) diff --git a/bench_decode_test.go b/bench_decode_test.go index 50e33908..16bdf2cd 100644 --- a/bench_decode_test.go +++ b/bench_decode_test.go @@ -59,14 +59,6 @@ func NewClusterClientStub(resp []byte) *ClientStub { }, }) - // init command. - tmpClient := NewClient(&Options{Addr: ":6379"}) - cmdsInfo, err := tmpClient.Command(ctx).Result() - _ = tmpClient.Close() - client.cmdsInfoCache = newCmdsInfoCache(func(_ context.Context) (map[string]*CommandInfo, error) { - return cmdsInfo, err - }) - stub.Cmdable = client return stub } diff --git a/command.go b/command.go index 3dd475fa..1a33cb32 100644 --- a/command.go +++ b/command.go @@ -75,7 +75,7 @@ func writeCmd(wr *proto.Writer, cmd Cmder) error { return wr.WriteArgs(cmd.Args()) } -func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int { +func cmdFirstKeyPos(cmd Cmder) int { if pos := cmd.firstKeyPos(); pos != 0 { return int(pos) } @@ -95,10 +95,6 @@ func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int { return 2 } } - - if info != nil { - return int(info.FirstKeyPos) - } return 1 } diff --git a/osscluster.go b/osscluster.go index 93e0eef1..b8a82d9b 100644 --- a/osscluster.go +++ b/osscluster.go @@ -907,7 +907,6 @@ func (c *ClusterClient) Process(ctx context.Context, cmd Cmder) error { } func (c *ClusterClient) process(ctx context.Context, cmd Cmder) error { - cmdInfo := c.cmdInfo(ctx, cmd.Name()) slot := c.cmdSlot(ctx, cmd) var node *clusterNode var ask bool @@ -921,7 +920,7 @@ func (c *ClusterClient) process(ctx context.Context, cmd Cmder) error { if node == nil { var err error - node, err = c.cmdNode(ctx, cmdInfo, slot) + node, err = c.cmdNode(ctx, cmd.Name(), slot) if err != nil { return err } @@ -1783,8 +1782,7 @@ func (c *ClusterClient) cmdSlot(ctx context.Context, cmd Cmder) int { return args[2].(int) } - cmdInfo := c.cmdInfo(ctx, cmd.Name()) - return cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo)) + return cmdSlot(cmd, cmdFirstKeyPos(cmd)) } func cmdSlot(cmd Cmder, pos int) int { @@ -1797,7 +1795,7 @@ func cmdSlot(cmd Cmder, pos int) int { func (c *ClusterClient) cmdNode( ctx context.Context, - cmdInfo *CommandInfo, + cmdName string, slot int, ) (*clusterNode, error) { state, err := c.state.Get(ctx) @@ -1805,8 +1803,11 @@ func (c *ClusterClient) cmdNode( return nil, err } - if c.opt.ReadOnly && cmdInfo != nil && cmdInfo.ReadOnly { - return c.slotReadOnlyNode(state, slot) + if c.opt.ReadOnly { + cmdInfo := c.cmdInfo(ctx, cmdName) + if cmdInfo != nil && cmdInfo.ReadOnly { + return c.slotReadOnlyNode(state, slot) + } } return state.slotMasterNode(slot) } diff --git a/ring.go b/ring.go index 367a542e..0c031b5a 100644 --- a/ring.go +++ b/ring.go @@ -678,21 +678,8 @@ func (c *Ring) cmdsInfo(ctx context.Context) (map[string]*CommandInfo, error) { return nil, firstErr } -func (c *Ring) cmdInfo(ctx context.Context, name string) *CommandInfo { - cmdsInfo, err := c.cmdsInfoCache.Get(ctx) - if err != nil { - return nil - } - info := cmdsInfo[name] - if info == nil { - internal.Logger.Printf(ctx, "info for cmd=%s not found", name) - } - return info -} - func (c *Ring) cmdShard(ctx context.Context, cmd Cmder) (*ringShard, error) { - cmdInfo := c.cmdInfo(ctx, cmd.Name()) - pos := cmdFirstKeyPos(cmd, cmdInfo) + pos := cmdFirstKeyPos(cmd) if pos == 0 { return c.sharding.Random() } @@ -760,8 +747,7 @@ func (c *Ring) generalProcessPipeline( cmdsMap := make(map[string][]Cmder) for _, cmd := range cmds { - cmdInfo := c.cmdInfo(ctx, cmd.Name()) - hash := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo)) + hash := cmd.stringArg(cmdFirstKeyPos(cmd)) if hash != "" { hash = c.sharding.Hash(hash) } From 716906addaa475a699df1d26869db99128fb1e80 Mon Sep 17 00:00:00 2001 From: ccx Date: Sun, 17 Dec 2023 21:34:17 +0800 Subject: [PATCH 11/11] docs: correct the format error of the url in 'Connecting via a redis url' section (#2789) * docs: correct the format error of the url in 'Connecting via a redis url' section * docs: change secret to password in redis url exmaple --------- Co-authored-by: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8965b915..b08330df 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ import ( var ctx = context.Background() func ExampleClient() { - url := "redis://localhost:6379?password=hello&protocol=3" + url := "redis://user:password@localhost:6379/0?protocol=3" opts, err := redis.ParseURL(url) if err != nil { panic(err)