From 711143687c9f065d8266363b424a7e1d7f7a768e Mon Sep 17 00:00:00 2001
From: ofekshenawa <ofek.shenawa@redis.com>
Date: Fri, 20 Sep 2024 16:13:13 +0300
Subject: [PATCH 1/7] Initial testing

---
 go.mod        |  2 +-
 redis.go      |  2 +-
 redis_test.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index bd13d7453..c1d9037ac 100644
--- a/go.mod
+++ b/go.mod
@@ -10,6 +10,6 @@ require (
 )
 
 retract (
-	v9.5.3 // This version was accidentally released. Please use version 9.6.0 instead.
 	v9.5.4 // This version was accidentally released. Please use version 9.6.0 instead.
+	v9.5.3 // This version was accidentally released. Please use version 9.6.0 instead.
 )
diff --git a/redis.go b/redis.go
index c8b500809..9d6049284 100644
--- a/redis.go
+++ b/redis.go
@@ -431,7 +431,7 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool
 			return false, err
 		}
 	}
-
+	panic(cmd.firstKeyPos())
 	retryTimeout := uint32(0)
 	if err := c.withConn(ctx, func(ctx context.Context, cn *pool.Conn) error {
 		if err := cn.WithWriter(c.context(ctx), c.opt.WriteTimeout, func(wr *proto.Writer) error {
diff --git a/redis_test.go b/redis_test.go
index ef2125452..e0fb026e7 100644
--- a/redis_test.go
+++ b/redis_test.go
@@ -6,6 +6,7 @@ import (
 	"errors"
 	"fmt"
 	"net"
+	"strconv"
 	"testing"
 	"time"
 
@@ -633,3 +634,55 @@ var _ = Describe("Hook with MinIdleConns", func() {
 		}))
 	})
 })
+
+var _ = Describe("Command Name", func() {
+	var client *redis.Client
+
+	BeforeEach(func() {
+		client = redis.NewClient(redisOptions())
+		Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
+	})
+
+	AfterEach(func() {
+		err := client.Close()
+		Expect(err).NotTo(HaveOccurred())
+	})
+
+	It("should return key name", func() {
+		mSet := client.MSet(ctx, "key1", "hello1", "key2", "hello2")
+		Expect(mSet.Err()).NotTo(HaveOccurred())
+		Expect(mSet.Val()).To(Equal("OK"))
+		Expect(mSet.Args()).To(Equal([]string{"MSET", "key1", "hello1", "key2", "hello2"}))
+
+		mGet := client.MGet(ctx, "key1", "key2", "_")
+		Expect(mGet.Err()).NotTo(HaveOccurred())
+		Expect(mGet.Val()).To(Equal([]interface{}{"hello1", "hello2", nil}))
+
+		// MSet struct
+		type set struct {
+			Set1 string                 `redis:"set1"`
+			Set2 int16                  `redis:"set2"`
+			Set3 time.Duration          `redis:"set3"`
+			Set4 interface{}            `redis:"set4"`
+			Set5 map[string]interface{} `redis:"-"`
+		}
+		mSet = client.MSet(ctx, &set{
+			Set1: "val1",
+			Set2: 1024,
+			Set3: 2 * time.Millisecond,
+			Set4: nil,
+			Set5: map[string]interface{}{"k1": 1},
+		})
+		Expect(mSet.Err()).NotTo(HaveOccurred())
+		Expect(mSet.Val()).To(Equal("OK"))
+
+		mGet = client.MGet(ctx, "set1", "set2", "set3", "set4")
+		Expect(mGet.Err()).NotTo(HaveOccurred())
+		Expect(mGet.Val()).To(Equal([]interface{}{
+			"val1",
+			"1024",
+			strconv.Itoa(int(2 * time.Millisecond.Nanoseconds())),
+			"",
+		}))
+	})
+})

From 249510cbb5837e03ab6e003f568b793023cc984a Mon Sep 17 00:00:00 2001
From: ofekshenawa <ofek.shenawa@redis.com>
Date: Fri, 20 Sep 2024 17:28:54 +0300
Subject: [PATCH 2/7] Create extractKeys function

---
 command.go | 24 ++++++++++++++++++++++++
 redis.go   |  2 +-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/command.go b/command.go
index 4ced2979d..3deaec109 100644
--- a/command.go
+++ b/command.go
@@ -119,6 +119,30 @@ func cmdString(cmd Cmder, val interface{}) string {
 	return util.BytesToString(b)
 }
 
+func extractKeys(cmd Cmder) []string {
+	firstKeyPos := cmdFirstKeyPos(cmd)
+	if firstKeyPos == -1 {
+		return nil
+	}
+	internal.Logger.Printf(context.Background(), "firstKeyPos: %d", firstKeyPos)
+	args := cmd.Args()
+	keys := []string{}
+
+	switch cmd.Name() {
+	case "MGET", "MSET":
+		for i := int(firstKeyPos); i < len(args); i += 2 {
+			keys = append(keys, cmd.stringArg(i))
+		}
+
+	default:
+		if int(firstKeyPos) < len(args) {
+			keys = append(keys, cmd.stringArg(firstKeyPos))
+		}
+	}
+
+	return keys
+}
+
 //------------------------------------------------------------------------------
 
 type baseCmd struct {
diff --git a/redis.go b/redis.go
index 9d6049284..0705c7446 100644
--- a/redis.go
+++ b/redis.go
@@ -431,7 +431,7 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool
 			return false, err
 		}
 	}
-	panic(cmd.firstKeyPos())
+	internal.Logger.Printf(ctx, "redis: keys in command %s", extractKeys(cmd))
 	retryTimeout := uint32(0)
 	if err := c.withConn(ctx, func(ctx context.Context, cn *pool.Conn) error {
 		if err := cn.WithWriter(c.context(ctx), c.opt.WriteTimeout, func(wr *proto.Writer) error {

From 5b30e4ecb835b52327484a4f82d71956fae97b49 Mon Sep 17 00:00:00 2001
From: ofekshenawa <ofek.shenawa@redis.com>
Date: Fri, 20 Sep 2024 18:44:49 +0300
Subject: [PATCH 3/7] Test extractKeys

---
 command.go       | 11 +++++++---
 commands_test.go | 23 +++++++++++++++++++++
 redis.go         |  2 +-
 redis_test.go    | 53 ------------------------------------------------
 4 files changed, 32 insertions(+), 57 deletions(-)

diff --git a/command.go b/command.go
index 3deaec109..d3cee9272 100644
--- a/command.go
+++ b/command.go
@@ -119,18 +119,23 @@ func cmdString(cmd Cmder, val interface{}) string {
 	return util.BytesToString(b)
 }
 
+// A wrapper around extract keys, just to make it easier to test.
+func GetKeys(cmd Cmder) []string {
+	return extractKeys(cmd)
+}
+
 func extractKeys(cmd Cmder) []string {
 	firstKeyPos := cmdFirstKeyPos(cmd)
 	if firstKeyPos == -1 {
 		return nil
 	}
-	internal.Logger.Printf(context.Background(), "firstKeyPos: %d", firstKeyPos)
+
 	args := cmd.Args()
 	keys := []string{}
 
 	switch cmd.Name() {
-	case "MGET", "MSET":
-		for i := int(firstKeyPos); i < len(args); i += 2 {
+	case "mget":
+		for i := int(firstKeyPos); i < len(args); i++ {
 			keys = append(keys, cmd.stringArg(i))
 		}
 
diff --git a/commands_test.go b/commands_test.go
index 9554bf9a9..1e493de4f 100644
--- a/commands_test.go
+++ b/commands_test.go
@@ -7279,6 +7279,29 @@ var _ = Describe("Commands", func() {
 	})
 })
 
+var _ = Describe("Get Keys from Command", func() {
+	var client *redis.Client
+
+	BeforeEach(func() {
+		client = redis.NewClient(redisOptions())
+		Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
+	})
+
+	AfterEach(func() {
+		Expect(client.Close()).NotTo(HaveOccurred())
+	})
+
+	It("returns the keys extracted from the command", func() {
+		cmd := redis.NewCmd(ctx, "SET", "key1", "value1")
+		keys := redis.GetKeys(cmd)
+		Expect(keys).To(Equal([]string{"key1"}))
+
+		cmd = redis.NewCmd(ctx, "MGET", "key1", "key2", "key3")
+		keys = redis.GetKeys(cmd)
+		Expect(keys).To(Equal([]string{"key1", "key2", "key3"}))
+	})
+})
+
 type numberStruct struct {
 	Number int
 }
diff --git a/redis.go b/redis.go
index 0705c7446..c8b500809 100644
--- a/redis.go
+++ b/redis.go
@@ -431,7 +431,7 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool
 			return false, err
 		}
 	}
-	internal.Logger.Printf(ctx, "redis: keys in command %s", extractKeys(cmd))
+
 	retryTimeout := uint32(0)
 	if err := c.withConn(ctx, func(ctx context.Context, cn *pool.Conn) error {
 		if err := cn.WithWriter(c.context(ctx), c.opt.WriteTimeout, func(wr *proto.Writer) error {
diff --git a/redis_test.go b/redis_test.go
index e0fb026e7..ef2125452 100644
--- a/redis_test.go
+++ b/redis_test.go
@@ -6,7 +6,6 @@ import (
 	"errors"
 	"fmt"
 	"net"
-	"strconv"
 	"testing"
 	"time"
 
@@ -634,55 +633,3 @@ var _ = Describe("Hook with MinIdleConns", func() {
 		}))
 	})
 })
-
-var _ = Describe("Command Name", func() {
-	var client *redis.Client
-
-	BeforeEach(func() {
-		client = redis.NewClient(redisOptions())
-		Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
-	})
-
-	AfterEach(func() {
-		err := client.Close()
-		Expect(err).NotTo(HaveOccurred())
-	})
-
-	It("should return key name", func() {
-		mSet := client.MSet(ctx, "key1", "hello1", "key2", "hello2")
-		Expect(mSet.Err()).NotTo(HaveOccurred())
-		Expect(mSet.Val()).To(Equal("OK"))
-		Expect(mSet.Args()).To(Equal([]string{"MSET", "key1", "hello1", "key2", "hello2"}))
-
-		mGet := client.MGet(ctx, "key1", "key2", "_")
-		Expect(mGet.Err()).NotTo(HaveOccurred())
-		Expect(mGet.Val()).To(Equal([]interface{}{"hello1", "hello2", nil}))
-
-		// MSet struct
-		type set struct {
-			Set1 string                 `redis:"set1"`
-			Set2 int16                  `redis:"set2"`
-			Set3 time.Duration          `redis:"set3"`
-			Set4 interface{}            `redis:"set4"`
-			Set5 map[string]interface{} `redis:"-"`
-		}
-		mSet = client.MSet(ctx, &set{
-			Set1: "val1",
-			Set2: 1024,
-			Set3: 2 * time.Millisecond,
-			Set4: nil,
-			Set5: map[string]interface{}{"k1": 1},
-		})
-		Expect(mSet.Err()).NotTo(HaveOccurred())
-		Expect(mSet.Val()).To(Equal("OK"))
-
-		mGet = client.MGet(ctx, "set1", "set2", "set3", "set4")
-		Expect(mGet.Err()).NotTo(HaveOccurred())
-		Expect(mGet.Val()).To(Equal([]interface{}{
-			"val1",
-			"1024",
-			strconv.Itoa(int(2 * time.Millisecond.Nanoseconds())),
-			"",
-		}))
-	})
-})

From c4cce2333ae1ad4927844fe59cbb962b27ab4050 Mon Sep 17 00:00:00 2001
From: ofekshenawa <ofek.shenawa@redis.com>
Date: Mon, 23 Sep 2024 01:04:53 +0300
Subject: [PATCH 4/7] Add keys method to Cmder

---
 command.go         | 13 ++++++++-----
 commands_test.go   | 15 +++++++--------
 string_commands.go | 23 +++++++++++++++++++++--
 3 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/command.go b/command.go
index d3cee9272..2e4d1a1ef 100644
--- a/command.go
+++ b/command.go
@@ -30,6 +30,9 @@ type Cmder interface {
 	// e.g. "set k v ex 10" -> "[set k v ex 10]".
 	Args() []interface{}
 
+	//all keys in command.
+	Keys() []string
+
 	// 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
@@ -119,11 +122,6 @@ func cmdString(cmd Cmder, val interface{}) string {
 	return util.BytesToString(b)
 }
 
-// A wrapper around extract keys, just to make it easier to test.
-func GetKeys(cmd Cmder) []string {
-	return extractKeys(cmd)
-}
-
 func extractKeys(cmd Cmder) []string {
 	firstKeyPos := cmdFirstKeyPos(cmd)
 	if firstKeyPos == -1 {
@@ -155,6 +153,7 @@ type baseCmd struct {
 	args         []interface{}
 	err          error
 	keyPos       int8
+	keys         []string
 	rawVal       interface{}
 	_readTimeout *time.Duration
 }
@@ -188,6 +187,10 @@ func (cmd *baseCmd) Args() []interface{} {
 	return cmd.args
 }
 
+func (cmd *baseCmd) Keys() []string {
+	return cmd.keys
+}
+
 func (cmd *baseCmd) stringArg(pos int) string {
 	if pos < 0 || pos >= len(cmd.args) {
 		return ""
diff --git a/commands_test.go b/commands_test.go
index 1e493de4f..dd78f1d19 100644
--- a/commands_test.go
+++ b/commands_test.go
@@ -7279,8 +7279,9 @@ var _ = Describe("Commands", func() {
 	})
 })
 
-var _ = Describe("Get Keys from Command", func() {
+var _ = Describe("Get Keys from Commands", func() {
 	var client *redis.Client
+	var ctx = context.TODO()
 
 	BeforeEach(func() {
 		client = redis.NewClient(redisOptions())
@@ -7291,14 +7292,12 @@ var _ = Describe("Get Keys from Command", func() {
 		Expect(client.Close()).NotTo(HaveOccurred())
 	})
 
-	It("returns the keys extracted from the command", func() {
-		cmd := redis.NewCmd(ctx, "SET", "key1", "value1")
-		keys := redis.GetKeys(cmd)
-		Expect(keys).To(Equal([]string{"key1"}))
+	It("should test string commands", func() {
+		setCmd := client.Set(ctx, "key1", "val1", 0)
+		Expect(setCmd.Keys()).To(Equal([]string{"key1"}))
 
-		cmd = redis.NewCmd(ctx, "MGET", "key1", "key2", "key3")
-		keys = redis.GetKeys(cmd)
-		Expect(keys).To(Equal([]string{"key1", "key2", "key3"}))
+		getCmd := client.MGet(ctx, "key1", "key2", "key3")
+		Expect(getCmd.Keys()).To(Equal([]string{"key1", "key2", "key3"}))
 	})
 })
 
diff --git a/string_commands.go b/string_commands.go
index eff5880dc..bf84418ee 100644
--- a/string_commands.go
+++ b/string_commands.go
@@ -32,18 +32,21 @@ type StringCmdable interface {
 
 func (c cmdable) Append(ctx context.Context, key, value string) *IntCmd {
 	cmd := NewIntCmd(ctx, "append", key, value)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
 
 func (c cmdable) Decr(ctx context.Context, key string) *IntCmd {
 	cmd := NewIntCmd(ctx, "decr", key)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
 
 func (c cmdable) DecrBy(ctx context.Context, key string, decrement int64) *IntCmd {
 	cmd := NewIntCmd(ctx, "decrby", key, decrement)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -51,18 +54,21 @@ func (c cmdable) DecrBy(ctx context.Context, key string, decrement int64) *IntCm
 // Get Redis `GET key` command. It returns redis.Nil error when key does not exist.
 func (c cmdable) Get(ctx context.Context, key string) *StringCmd {
 	cmd := NewStringCmd(ctx, "get", key)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
 
 func (c cmdable) GetRange(ctx context.Context, key string, start, end int64) *StringCmd {
 	cmd := NewStringCmd(ctx, "getrange", key, start, end)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
 
 func (c cmdable) GetSet(ctx context.Context, key string, value interface{}) *StringCmd {
 	cmd := NewStringCmd(ctx, "getset", key, value)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -83,6 +89,7 @@ func (c cmdable) GetEx(ctx context.Context, key string, expiration time.Duration
 	}
 
 	cmd := NewStringCmd(ctx, args...)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -90,24 +97,28 @@ func (c cmdable) GetEx(ctx context.Context, key string, expiration time.Duration
 // GetDel redis-server version >= 6.2.0.
 func (c cmdable) GetDel(ctx context.Context, key string) *StringCmd {
 	cmd := NewStringCmd(ctx, "getdel", key)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
 
 func (c cmdable) Incr(ctx context.Context, key string) *IntCmd {
 	cmd := NewIntCmd(ctx, "incr", key)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
 
 func (c cmdable) IncrBy(ctx context.Context, key string, value int64) *IntCmd {
 	cmd := NewIntCmd(ctx, "incrby", key, value)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
 
 func (c cmdable) IncrByFloat(ctx context.Context, key string, value float64) *FloatCmd {
 	cmd := NewFloatCmd(ctx, "incrbyfloat", key, value)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -125,6 +136,7 @@ func (c cmdable) MGet(ctx context.Context, keys ...string) *SliceCmd {
 		args[1+i] = key
 	}
 	cmd := NewSliceCmd(ctx, args...)
+	cmd.keys = append(cmd.keys, keys...)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -139,6 +151,7 @@ func (c cmdable) MSet(ctx context.Context, values ...interface{}) *StatusCmd {
 	args[0] = "mset"
 	args = appendArgs(args, values)
 	cmd := NewStatusCmd(ctx, args...)
+	// cmd.keys = append(cmd.keys, keys...)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -153,6 +166,7 @@ func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd {
 	args[0] = "msetnx"
 	args = appendArgs(args, values)
 	cmd := NewBoolCmd(ctx, args...)
+	// cmd.keys = append(cmd.keys, keys...)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -179,6 +193,7 @@ func (c cmdable) Set(ctx context.Context, key string, value interface{}, expirat
 	}
 
 	cmd := NewStatusCmd(ctx, args...)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -230,6 +245,7 @@ func (c cmdable) SetArgs(ctx context.Context, key string, value interface{}, a S
 	}
 
 	cmd := NewStatusCmd(ctx, args...)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -237,6 +253,7 @@ func (c cmdable) SetArgs(ctx context.Context, key string, value interface{}, a S
 // SetEx Redis `SETEx key expiration value` command.
 func (c cmdable) SetEx(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd {
 	cmd := NewStatusCmd(ctx, "setex", key, formatSec(ctx, expiration), value)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -261,7 +278,7 @@ func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expir
 			cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "nx")
 		}
 	}
-
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -285,19 +302,21 @@ func (c cmdable) SetXX(ctx context.Context, key string, value interface{}, expir
 			cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "xx")
 		}
 	}
-
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
 
 func (c cmdable) SetRange(ctx context.Context, key string, offset int64, value string) *IntCmd {
 	cmd := NewIntCmd(ctx, "setrange", key, offset, value)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }
 
 func (c cmdable) StrLen(ctx context.Context, key string) *IntCmd {
 	cmd := NewIntCmd(ctx, "strlen", key)
+	cmd.keys = append(cmd.keys, key)
 	_ = c(ctx, cmd)
 	return cmd
 }

From 8de72d6d3c4621d1d3cc7171bfc1da9d56ede11a Mon Sep 17 00:00:00 2001
From: ofekshenawa <ofek.shenawa@redis.com>
Date: Mon, 23 Sep 2024 01:32:35 +0300
Subject: [PATCH 5/7] Extract keys from string commands

---
 command.go         | 16 +++++++++++++++
 commands_test.go   | 51 ++++++++++++++++++++++++++++++++++++++++------
 string_commands.go |  4 ++--
 3 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/command.go b/command.go
index 2e4d1a1ef..a18589c9f 100644
--- a/command.go
+++ b/command.go
@@ -234,6 +234,22 @@ func (cmd *baseCmd) readRawReply(rd *proto.Reader) (err error) {
 	return err
 }
 
+// getInterleavedArguments returns arguments at even indices starting from index 0.
+func (cmd *baseCmd) getInterleavedArguments() []string {
+	return cmd.getInterleavedArgumentsWithOffset(0)
+}
+
+// getInterleavedArgumentsWithOffset returns arguments at even indices starting from the specified offset.
+func (cmd *baseCmd) getInterleavedArgumentsWithOffset(offset int) []string {
+	var matchingArguments []string
+	for i := offset; i < len(cmd.args); i += 2 {
+		if arg, ok := cmd.args[i].(string); ok {
+			matchingArguments = append(matchingArguments, arg)
+		}
+	}
+	return matchingArguments
+}
+
 //------------------------------------------------------------------------------
 
 type Cmd struct {
diff --git a/commands_test.go b/commands_test.go
index dd78f1d19..cf722a9e3 100644
--- a/commands_test.go
+++ b/commands_test.go
@@ -7279,7 +7279,7 @@ var _ = Describe("Commands", func() {
 	})
 })
 
-var _ = Describe("Get Keys from Commands", func() {
+var _ = Describe("Keys Extraction Tests", func() {
 	var client *redis.Client
 	var ctx = context.TODO()
 
@@ -7292,12 +7292,51 @@ var _ = Describe("Get Keys from Commands", func() {
 		Expect(client.Close()).NotTo(HaveOccurred())
 	})
 
-	It("should test string commands", func() {
-		setCmd := client.Set(ctx, "key1", "val1", 0)
-		Expect(setCmd.Keys()).To(Equal([]string{"key1"}))
+	// STRING COMMANDS
 
-		getCmd := client.MGet(ctx, "key1", "key2", "key3")
-		Expect(getCmd.Keys()).To(Equal([]string{"key1", "key2", "key3"}))
+	It("should test Append command", func() {
+		cmd := client.Append(ctx, "key1", "value")
+		Expect(cmd.Keys()).To(Equal([]string{"key1"}))
+	})
+
+	It("should test Decr command", func() {
+		cmd := client.Decr(ctx, "key1")
+		Expect(cmd.Keys()).To(Equal([]string{"key1"}))
+	})
+
+	It("should test Get command", func() {
+		cmd := client.Get(ctx, "key1")
+		Expect(cmd.Keys()).To(Equal([]string{"key1"}))
+	})
+
+	It("should test MGet command", func() {
+		cmd := client.MGet(ctx, "key1", "key2", "key3")
+		Expect(cmd.Keys()).To(Equal([]string{"key1", "key2", "key3"}))
+	})
+
+	It("should test Set command", func() {
+		cmd := client.Set(ctx, "key1", "value", time.Second)
+		Expect(cmd.Keys()).To(Equal([]string{"key1"}))
+	})
+
+	It("should test MSet command", func() {
+		cmd := client.MSet(ctx, "key1", "value1", "key2", "value2")
+		Expect(cmd.Keys()).To(Equal([]string{"key1", "key2"}))
+	})
+
+	It("should test IncrBy command", func() {
+		cmd := client.IncrBy(ctx, "key1", 10)
+		Expect(cmd.Keys()).To(Equal([]string{"key1"}))
+	})
+
+	It("should test SetNX command", func() {
+		cmd := client.SetNX(ctx, "key1", "value", time.Second)
+		Expect(cmd.Keys()).To(Equal([]string{"key1"}))
+	})
+
+	It("should test GetDel command", func() {
+		cmd := client.GetDel(ctx, "key1")
+		Expect(cmd.Keys()).To(Equal([]string{"key1"}))
 	})
 })
 
diff --git a/string_commands.go b/string_commands.go
index bf84418ee..292dfb320 100644
--- a/string_commands.go
+++ b/string_commands.go
@@ -151,7 +151,7 @@ func (c cmdable) MSet(ctx context.Context, values ...interface{}) *StatusCmd {
 	args[0] = "mset"
 	args = appendArgs(args, values)
 	cmd := NewStatusCmd(ctx, args...)
-	// cmd.keys = append(cmd.keys, keys...)
+	cmd.keys = append(cmd.keys, cmd.getInterleavedArgumentsWithOffset(1)...)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -166,7 +166,7 @@ func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd {
 	args[0] = "msetnx"
 	args = appendArgs(args, values)
 	cmd := NewBoolCmd(ctx, args...)
-	// cmd.keys = append(cmd.keys, keys...)
+	cmd.keys = append(cmd.keys, cmd.getInterleavedArgumentsWithOffset(1)...)
 	_ = c(ctx, cmd)
 	return cmd
 }

From be805cbe1070eb573ed88ed69d41be163e51ae67 Mon Sep 17 00:00:00 2001
From: ofekshenawa <ofek.shenawa@redis.com>
Date: Mon, 23 Sep 2024 01:34:38 +0300
Subject: [PATCH 6/7] Remove extractKeys function

---
 command.go | 24 ------------------------
 1 file changed, 24 deletions(-)

diff --git a/command.go b/command.go
index a18589c9f..d4323773b 100644
--- a/command.go
+++ b/command.go
@@ -122,30 +122,6 @@ func cmdString(cmd Cmder, val interface{}) string {
 	return util.BytesToString(b)
 }
 
-func extractKeys(cmd Cmder) []string {
-	firstKeyPos := cmdFirstKeyPos(cmd)
-	if firstKeyPos == -1 {
-		return nil
-	}
-
-	args := cmd.Args()
-	keys := []string{}
-
-	switch cmd.Name() {
-	case "mget":
-		for i := int(firstKeyPos); i < len(args); i++ {
-			keys = append(keys, cmd.stringArg(i))
-		}
-
-	default:
-		if int(firstKeyPos) < len(args) {
-			keys = append(keys, cmd.stringArg(firstKeyPos))
-		}
-	}
-
-	return keys
-}
-
 //------------------------------------------------------------------------------
 
 type baseCmd struct {

From a5fdfa2ec830724eec28969ac2663ac25d34b8ea Mon Sep 17 00:00:00 2001
From: ofekshenawa <ofek.shenawa@redis.com>
Date: Mon, 23 Sep 2024 01:37:41 +0300
Subject: [PATCH 7/7] Change getInterleavedArguments function

---
 command.go         | 4 ++--
 string_commands.go | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/command.go b/command.go
index d4323773b..1644b8ab3 100644
--- a/command.go
+++ b/command.go
@@ -210,9 +210,9 @@ func (cmd *baseCmd) readRawReply(rd *proto.Reader) (err error) {
 	return err
 }
 
-// getInterleavedArguments returns arguments at even indices starting from index 0.
+// getInterleavedArguments returns arguments at even indices starting from index 1.
 func (cmd *baseCmd) getInterleavedArguments() []string {
-	return cmd.getInterleavedArgumentsWithOffset(0)
+	return cmd.getInterleavedArgumentsWithOffset(1)
 }
 
 // getInterleavedArgumentsWithOffset returns arguments at even indices starting from the specified offset.
diff --git a/string_commands.go b/string_commands.go
index 292dfb320..d9d1d90a5 100644
--- a/string_commands.go
+++ b/string_commands.go
@@ -151,7 +151,7 @@ func (c cmdable) MSet(ctx context.Context, values ...interface{}) *StatusCmd {
 	args[0] = "mset"
 	args = appendArgs(args, values)
 	cmd := NewStatusCmd(ctx, args...)
-	cmd.keys = append(cmd.keys, cmd.getInterleavedArgumentsWithOffset(1)...)
+	cmd.keys = append(cmd.keys, cmd.getInterleavedArguments()...)
 	_ = c(ctx, cmd)
 	return cmd
 }
@@ -166,7 +166,7 @@ func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd {
 	args[0] = "msetnx"
 	args = appendArgs(args, values)
 	cmd := NewBoolCmd(ctx, args...)
-	cmd.keys = append(cmd.keys, cmd.getInterleavedArgumentsWithOffset(1)...)
+	cmd.keys = append(cmd.keys, cmd.getInterleavedArguments()...)
 	_ = c(ctx, cmd)
 	return cmd
 }