From 69d355eb4ba722144fdbae21677d8a7ca2c600be Mon Sep 17 00:00:00 2001 From: #Suyghur Date: Wed, 4 Jan 2023 13:44:17 +0800 Subject: [PATCH] feat(redis): add zscan command implementation (#2729) (#2751) --- core/stores/redis/redis.go | 22 ++++++++++++++++++++++ core/stores/redis/redis_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/core/stores/redis/redis.go b/core/stores/redis/redis.go index 9cd47d2e..199fcd14 100644 --- a/core/stores/redis/redis.go +++ b/core/stores/redis/redis.go @@ -2017,6 +2017,28 @@ func (s *Redis) ZscoreCtx(ctx context.Context, key, value string) (val int64, er return } +// Zscan is the implementation of redis zscan command. +func (s *Redis) Zscan(key string, cursor uint64, match string, count int64) ( + keys []string, cur uint64, err error) { + return s.ZscanCtx(context.Background(), key, cursor, match, count) +} + +// ZscanCtx is the implementation of redis zscan command. +func (s *Redis) ZscanCtx(ctx context.Context, key string, cursor uint64, match string, count int64) ( + keys []string, cur uint64, err error) { + err = s.brk.DoWithAcceptable(func() error { + conn, err := getRedis(s) + if err != nil { + return err + } + + keys, cur, err = conn.ZScan(ctx, key, cursor, match, count).Result() + return err + }, acceptable) + + return +} + // Zrank is the implementation of redis zrank command. func (s *Redis) Zrank(key, field string) (int64, error) { return s.ZrankCtx(context.Background(), key, field) diff --git a/core/stores/redis/redis_test.go b/core/stores/redis/redis_test.go index 3dd2a576..8460481f 100644 --- a/core/stores/redis/redis_test.go +++ b/core/stores/redis/redis_test.go @@ -1090,6 +1090,36 @@ func TestRedisToPairs(t *testing.T) { }, pairs) } +func TestRedis_Zscan(t *testing.T) { + runOnRedis(t, func(client *Redis) { + key := "key" + for i := 0; i < 1550; i++ { + ok, err := client.Zadd(key, int64(i), "value_"+strconv.Itoa(i)) + assert.Nil(t, err) + assert.True(t, ok) + } + var cursor uint64 = 0 + sum := 0 + for { + _, _, err := New(client.Addr, badType()).Zscan(key, cursor, "value_*", 100) + assert.NotNil(t, err) + keys, next, err := client.Zscan(key, cursor, "value_*", 100) + assert.Nil(t, err) + sum += len(keys) + if next == 0 { + break + } + cursor = next + } + + assert.Equal(t, sum, 3100) + _, err := New(client.Addr, badType()).Del(key) + assert.NotNil(t, err) + _, err = client.Del(key) + assert.Nil(t, err) + }) +} + func TestRedisToStrings(t *testing.T) { vals := toStrings([]interface{}{1, 2}) assert.EqualValues(t, []string{"1", "2"}, vals)