Skip to content

Commit ff875b5

Browse files
authored
Merge branch 'master' into load-balance-search-commands-to-shards
2 parents 68d8dc6 + c176672 commit ff875b5

File tree

7 files changed

+530
-2
lines changed

7 files changed

+530
-2
lines changed

command.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4666,6 +4666,83 @@ func (cmd *SlowLogCmd) Clone() Cmder {
46664666

46674667
//-----------------------------------------------------------------------
46684668

4669+
type Latency struct {
4670+
Name string
4671+
Time time.Time
4672+
Latest time.Duration
4673+
Max time.Duration
4674+
}
4675+
4676+
type LatencyCmd struct {
4677+
baseCmd
4678+
val []Latency
4679+
}
4680+
4681+
var _ Cmder = (*LatencyCmd)(nil)
4682+
4683+
func NewLatencyCmd(ctx context.Context, args ...interface{}) *LatencyCmd {
4684+
return &LatencyCmd{
4685+
baseCmd: baseCmd{
4686+
ctx: ctx,
4687+
args: args,
4688+
},
4689+
}
4690+
}
4691+
4692+
func (cmd *LatencyCmd) SetVal(val []Latency) {
4693+
cmd.val = val
4694+
}
4695+
4696+
func (cmd *LatencyCmd) Val() []Latency {
4697+
return cmd.val
4698+
}
4699+
4700+
func (cmd *LatencyCmd) Result() ([]Latency, error) {
4701+
return cmd.val, cmd.err
4702+
}
4703+
4704+
func (cmd *LatencyCmd) String() string {
4705+
return cmdString(cmd, cmd.val)
4706+
}
4707+
4708+
func (cmd *LatencyCmd) readReply(rd *proto.Reader) error {
4709+
n, err := rd.ReadArrayLen()
4710+
if err != nil {
4711+
return err
4712+
}
4713+
cmd.val = make([]Latency, n)
4714+
for i := 0; i < len(cmd.val); i++ {
4715+
nn, err := rd.ReadArrayLen()
4716+
if err != nil {
4717+
return err
4718+
}
4719+
if nn < 3 {
4720+
return fmt.Errorf("redis: got %d elements in latency get, expected at least 3", nn)
4721+
}
4722+
if cmd.val[i].Name, err = rd.ReadString(); err != nil {
4723+
return err
4724+
}
4725+
createdAt, err := rd.ReadInt()
4726+
if err != nil {
4727+
return err
4728+
}
4729+
cmd.val[i].Time = time.Unix(createdAt, 0)
4730+
latest, err := rd.ReadInt()
4731+
if err != nil {
4732+
return err
4733+
}
4734+
cmd.val[i].Latest = time.Duration(latest) * time.Millisecond
4735+
maximum, err := rd.ReadInt()
4736+
if err != nil {
4737+
return err
4738+
}
4739+
cmd.val[i].Max = time.Duration(maximum) * time.Millisecond
4740+
}
4741+
return nil
4742+
}
4743+
4744+
//-----------------------------------------------------------------------
4745+
46694746
type MapStringInterfaceCmd struct {
46704747
baseCmd
46714748

commands.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,13 @@ type Cmdable interface {
211211
ShutdownNoSave(ctx context.Context) *StatusCmd
212212
SlaveOf(ctx context.Context, host, port string) *StatusCmd
213213
SlowLogGet(ctx context.Context, num int64) *SlowLogCmd
214+
SlowLogLen(ctx context.Context) *IntCmd
215+
SlowLogReset(ctx context.Context) *StatusCmd
214216
Time(ctx context.Context) *TimeCmd
215217
DebugObject(ctx context.Context, key string) *StringCmd
216218
MemoryUsage(ctx context.Context, key string, samples ...int) *IntCmd
219+
Latency(ctx context.Context) *LatencyCmd
220+
LatencyReset(ctx context.Context, events ...interface{}) *StatusCmd
217221

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

@@ -673,6 +677,34 @@ func (c cmdable) SlowLogGet(ctx context.Context, num int64) *SlowLogCmd {
673677
return cmd
674678
}
675679

680+
func (c cmdable) SlowLogLen(ctx context.Context) *IntCmd {
681+
cmd := NewIntCmd(ctx, "slowlog", "len")
682+
_ = c(ctx, cmd)
683+
return cmd
684+
}
685+
686+
func (c cmdable) SlowLogReset(ctx context.Context) *StatusCmd {
687+
cmd := NewStatusCmd(ctx, "slowlog", "reset")
688+
_ = c(ctx, cmd)
689+
return cmd
690+
}
691+
692+
func (c cmdable) Latency(ctx context.Context) *LatencyCmd {
693+
cmd := NewLatencyCmd(ctx, "latency", "latest")
694+
_ = c(ctx, cmd)
695+
return cmd
696+
}
697+
698+
func (c cmdable) LatencyReset(ctx context.Context, events ...interface{}) *StatusCmd {
699+
args := make([]interface{}, 2+len(events))
700+
args[0] = "latency"
701+
args[1] = "reset"
702+
copy(args[2:], events)
703+
cmd := NewStatusCmd(ctx, args...)
704+
_ = c(ctx, cmd)
705+
return cmd
706+
}
707+
676708
func (c cmdable) Sync(_ context.Context) {
677709
panic("not implemented")
678710
}

commands_test.go

Lines changed: 240 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,137 @@ var _ = Describe("Commands", func() {
19521952
Expect(mSetNX.Val()).To(Equal(true))
19531953
})
19541954

1955+
It("should MSetEX", func() {
1956+
SkipBeforeRedisVersion(8.3, "MSetEX is available since redis 8.4")
1957+
args := redis.MSetEXArgs{
1958+
Expiration: &redis.ExpirationOption{
1959+
Mode: redis.EX,
1960+
Value: 1,
1961+
},
1962+
}
1963+
mSetEX := client.MSetEX(ctx, args, "key1", "hello1", "key2", "hello2")
1964+
Expect(mSetEX.Err()).NotTo(HaveOccurred())
1965+
Expect(mSetEX.Val()).To(Equal(int64(1)))
1966+
1967+
// Verify keys were set
1968+
val1 := client.Get(ctx, "key1")
1969+
Expect(val1.Err()).NotTo(HaveOccurred())
1970+
Expect(val1.Val()).To(Equal("hello1"))
1971+
1972+
val2 := client.Get(ctx, "key2")
1973+
Expect(val2.Err()).NotTo(HaveOccurred())
1974+
Expect(val2.Val()).To(Equal("hello2"))
1975+
1976+
// Verify TTL was set
1977+
ttl1 := client.TTL(ctx, "key1")
1978+
Expect(ttl1.Err()).NotTo(HaveOccurred())
1979+
Expect(ttl1.Val()).To(BeNumerically(">", 0))
1980+
Expect(ttl1.Val()).To(BeNumerically("<=", 1*time.Second))
1981+
1982+
ttl2 := client.TTL(ctx, "key2")
1983+
Expect(ttl2.Err()).NotTo(HaveOccurred())
1984+
Expect(ttl2.Val()).To(BeNumerically(">", 0))
1985+
Expect(ttl2.Val()).To(BeNumerically("<=", 1*time.Second))
1986+
})
1987+
1988+
It("should MSetEX with NX mode", func() {
1989+
SkipBeforeRedisVersion(8.3, "MSetEX is available since redis 8.4")
1990+
1991+
client.Set(ctx, "key1", "existing", 0)
1992+
1993+
// Try to set with NX mode - should fail because key1 exists
1994+
args := redis.MSetEXArgs{
1995+
Condition: redis.NX,
1996+
Expiration: &redis.ExpirationOption{
1997+
Mode: redis.EX,
1998+
Value: 1,
1999+
},
2000+
}
2001+
mSetEX := client.MSetEX(ctx, args, "key1", "new1", "key2", "new2")
2002+
Expect(mSetEX.Err()).NotTo(HaveOccurred())
2003+
Expect(mSetEX.Val()).To(Equal(int64(0)))
2004+
2005+
val1 := client.Get(ctx, "key1")
2006+
Expect(val1.Err()).NotTo(HaveOccurred())
2007+
Expect(val1.Val()).To(Equal("existing"))
2008+
2009+
val2 := client.Get(ctx, "key2")
2010+
Expect(val2.Err()).To(Equal(redis.Nil))
2011+
2012+
client.Del(ctx, "key1")
2013+
2014+
// Now try with NX mode when keys don't exist - should succeed
2015+
mSetEX = client.MSetEX(ctx, args, "key1", "new1", "key2", "new2")
2016+
Expect(mSetEX.Err()).NotTo(HaveOccurred())
2017+
Expect(mSetEX.Val()).To(Equal(int64(1)))
2018+
2019+
val1 = client.Get(ctx, "key1")
2020+
Expect(val1.Err()).NotTo(HaveOccurred())
2021+
Expect(val1.Val()).To(Equal("new1"))
2022+
2023+
val2 = client.Get(ctx, "key2")
2024+
Expect(val2.Err()).NotTo(HaveOccurred())
2025+
Expect(val2.Val()).To(Equal("new2"))
2026+
})
2027+
2028+
It("should MSetEX with XX mode", func() {
2029+
SkipBeforeRedisVersion(8.3, "MSetEX is available since redis 8.4")
2030+
2031+
args := redis.MSetEXArgs{
2032+
Condition: redis.XX,
2033+
Expiration: &redis.ExpirationOption{
2034+
Mode: redis.EX,
2035+
Value: 1,
2036+
},
2037+
}
2038+
mSetEX := client.MSetEX(ctx, args, "key1", "new1", "key2", "new2")
2039+
Expect(mSetEX.Err()).NotTo(HaveOccurred())
2040+
Expect(mSetEX.Val()).To(Equal(int64(0)))
2041+
2042+
client.Set(ctx, "key1", "existing1", 0)
2043+
client.Set(ctx, "key2", "existing2", 0)
2044+
2045+
mSetEX = client.MSetEX(ctx, args, "key1", "new1", "key2", "new2")
2046+
Expect(mSetEX.Err()).NotTo(HaveOccurred())
2047+
Expect(mSetEX.Val()).To(Equal(int64(1)))
2048+
2049+
val1 := client.Get(ctx, "key1")
2050+
Expect(val1.Err()).NotTo(HaveOccurred())
2051+
Expect(val1.Val()).To(Equal("new1"))
2052+
2053+
val2 := client.Get(ctx, "key2")
2054+
Expect(val2.Err()).NotTo(HaveOccurred())
2055+
Expect(val2.Val()).To(Equal("new2"))
2056+
2057+
ttl1 := client.TTL(ctx, "key1")
2058+
Expect(ttl1.Err()).NotTo(HaveOccurred())
2059+
Expect(ttl1.Val()).To(BeNumerically(">", 0))
2060+
})
2061+
2062+
It("should MSetEX with map", func() {
2063+
SkipBeforeRedisVersion(8.3, "MSetEX is available since redis 8.4")
2064+
args := redis.MSetEXArgs{
2065+
Expiration: &redis.ExpirationOption{
2066+
Mode: redis.EX,
2067+
Value: 1,
2068+
},
2069+
}
2070+
mSetEX := client.MSetEX(ctx, args, map[string]interface{}{
2071+
"key1": "value1",
2072+
"key2": "value2",
2073+
})
2074+
Expect(mSetEX.Err()).NotTo(HaveOccurred())
2075+
Expect(mSetEX.Val()).To(Equal(int64(1)))
2076+
2077+
val1 := client.Get(ctx, "key1")
2078+
Expect(val1.Err()).NotTo(HaveOccurred())
2079+
Expect(val1.Val()).To(Equal("value1"))
2080+
2081+
val2 := client.Get(ctx, "key2")
2082+
Expect(val2.Err()).NotTo(HaveOccurred())
2083+
Expect(val2.Val()).To(Equal("value2"))
2084+
})
2085+
19552086
It("should SetWithArgs with TTL", func() {
19562087
args := redis.SetArgs{
19572088
TTL: 500 * time.Millisecond,
@@ -8180,7 +8311,7 @@ var _ = Describe("Commands", func() {
81808311
})
81818312
})
81828313

8183-
Describe("SlowLogGet", func() {
8314+
Describe("SlowLog", func() {
81848315
It("returns slow query result", func() {
81858316
const key = "slowlog-log-slower-than"
81868317

@@ -8197,6 +8328,114 @@ var _ = Describe("Commands", func() {
81978328
Expect(err).NotTo(HaveOccurred())
81988329
Expect(len(result)).NotTo(BeZero())
81998330
})
8331+
8332+
It("returns the number of slow queries", Label("NonRedisEnterprise"), func() {
8333+
// Reset slowlog
8334+
err := client.SlowLogReset(ctx).Err()
8335+
Expect(err).NotTo(HaveOccurred())
8336+
8337+
const key = "slowlog-log-slower-than"
8338+
8339+
old := client.ConfigGet(ctx, key).Val()
8340+
// first slowlog entry is the config set command itself
8341+
client.ConfigSet(ctx, key, "0")
8342+
defer client.ConfigSet(ctx, key, old[key])
8343+
8344+
// Set a key to trigger a slow query, and this is the second slowlog entry
8345+
client.Set(ctx, "test", "true", 0)
8346+
result, err := client.SlowLogLen(ctx).Result()
8347+
Expect(err).NotTo(HaveOccurred())
8348+
Expect(result).Should(Equal(int64(2)))
8349+
8350+
// Reset slowlog
8351+
err = client.SlowLogReset(ctx).Err()
8352+
Expect(err).NotTo(HaveOccurred())
8353+
8354+
// Check if slowlog is empty, this is the first slowlog entry after reset
8355+
result, err = client.SlowLogLen(ctx).Result()
8356+
Expect(err).NotTo(HaveOccurred())
8357+
Expect(result).Should(Equal(int64(1)))
8358+
})
8359+
})
8360+
8361+
Describe("Latency", Label("NonRedisEnterprise"), func() {
8362+
It("returns latencies", func() {
8363+
const key = "latency-monitor-threshold"
8364+
8365+
old := client.ConfigGet(ctx, key).Val()
8366+
client.ConfigSet(ctx, key, "1")
8367+
defer client.ConfigSet(ctx, key, old[key])
8368+
8369+
err := client.Do(ctx, "DEBUG", "SLEEP", 0.01).Err()
8370+
Expect(err).NotTo(HaveOccurred())
8371+
8372+
result, err := client.Latency(ctx).Result()
8373+
Expect(err).NotTo(HaveOccurred())
8374+
Expect(len(result)).NotTo(BeZero())
8375+
})
8376+
8377+
It("reset all latencies", func() {
8378+
const key = "latency-monitor-threshold"
8379+
8380+
result, err := client.Latency(ctx).Result()
8381+
// reset all latencies
8382+
err = client.LatencyReset(ctx).Err()
8383+
Expect(err).NotTo(HaveOccurred())
8384+
8385+
old := client.ConfigGet(ctx, key).Val()
8386+
client.ConfigSet(ctx, key, "1")
8387+
defer client.ConfigSet(ctx, key, old[key])
8388+
8389+
// get latency after reset
8390+
result, err = client.Latency(ctx).Result()
8391+
Expect(err).NotTo(HaveOccurred())
8392+
Expect(len(result)).Should(Equal(0))
8393+
8394+
// create a new latency
8395+
err = client.Do(ctx, "DEBUG", "SLEEP", 0.01).Err()
8396+
Expect(err).NotTo(HaveOccurred())
8397+
8398+
// get latency after create a new latency
8399+
result, err = client.Latency(ctx).Result()
8400+
Expect(err).NotTo(HaveOccurred())
8401+
Expect(len(result)).Should(Equal(1))
8402+
8403+
// reset all latencies again
8404+
err = client.LatencyReset(ctx).Err()
8405+
Expect(err).NotTo(HaveOccurred())
8406+
8407+
// get latency after reset again
8408+
result, err = client.Latency(ctx).Result()
8409+
Expect(err).NotTo(HaveOccurred())
8410+
Expect(len(result)).Should(Equal(0))
8411+
})
8412+
8413+
It("reset latencies by add event name args", func() {
8414+
const key = "latency-monitor-threshold"
8415+
8416+
old := client.ConfigGet(ctx, key).Val()
8417+
client.ConfigSet(ctx, key, "1")
8418+
defer client.ConfigSet(ctx, key, old[key])
8419+
8420+
result, err := client.Latency(ctx).Result()
8421+
Expect(err).NotTo(HaveOccurred())
8422+
Expect(len(result)).Should(Equal(0))
8423+
8424+
err = client.Do(ctx, "DEBUG", "SLEEP", 0.01).Err()
8425+
Expect(err).NotTo(HaveOccurred())
8426+
8427+
result, err = client.Latency(ctx).Result()
8428+
Expect(err).NotTo(HaveOccurred())
8429+
Expect(len(result)).Should(Equal(1))
8430+
8431+
// reset latency by event name
8432+
err = client.LatencyReset(ctx, result[0].Name).Err()
8433+
Expect(err).NotTo(HaveOccurred())
8434+
8435+
result, err = client.Latency(ctx).Result()
8436+
Expect(err).NotTo(HaveOccurred())
8437+
Expect(len(result)).Should(Equal(0))
8438+
})
82008439
})
82018440
})
82028441

0 commit comments

Comments
 (0)