From a7bd993c0c3841a2e0143bc8ff1035f763896d4d Mon Sep 17 00:00:00 2001 From: CrazyZard <33921085+CrazyZard@users.noreply.github.com> Date: Wed, 15 Dec 2021 13:15:39 +0800 Subject: [PATCH] commit missing method for redis (#1325) * commit `decr ` `decrby` `lindex` missing method for redis * fix(store_test):TestRedis_DecrBy * add unit tests for redis commands. And put the functions in alphabetical order * put the functions in alphabetical order * add `lindex` unit test * sort func --- core/stores/kv/store.go | 30 ++++++++++++++++++++++ core/stores/kv/store_test.go | 35 +++++++++++++++++++++++++ core/stores/redis/redis.go | 45 +++++++++++++++++++++++++++++++++ core/stores/redis/redis_test.go | 31 +++++++++++++++++++++++ 4 files changed, 141 insertions(+) diff --git a/core/stores/kv/store.go b/core/stores/kv/store.go index aa0a499a..c43dcb9f 100644 --- a/core/stores/kv/store.go +++ b/core/stores/kv/store.go @@ -16,6 +16,8 @@ var ErrNoRedisNode = errors.New("no redis node") type ( // Store interface represents a KV store. Store interface { + Decr(key string) (int64, error) + Decrby(key string, increment int64) (int64, error) Del(keys ...string) (int, error) Eval(script, key string, args ...interface{}) (interface{}, error) Exists(key string) (bool, error) @@ -37,6 +39,7 @@ type ( Incr(key string) (int64, error) Incrby(key string, increment int64) (int64, error) Llen(key string) (int, error) + Lindex(key string, index int64) (string, error) Lpop(key string) (string, error) Lpush(key string, values ...interface{}) (int, error) Lrange(key string, start, stop int) ([]string, error) @@ -102,6 +105,24 @@ func NewStore(c KvConf) Store { } } +func (cs clusterStore) Decr(key string) (int64, error) { + node, err := cs.getRedis(key) + if err != nil { + return 0, err + } + + return node.Decr(key) +} + +func (cs clusterStore) Decrby(key string, increment int64) (int64, error) { + node, err := cs.getRedis(key) + if err != nil { + return 0, err + } + + return node.Decrby(key, increment) +} + func (cs clusterStore) Del(keys ...string) (int, error) { var val int var be errorx.BatchError @@ -303,6 +324,15 @@ func (cs clusterStore) Llen(key string) (int, error) { return node.Llen(key) } +func (cs clusterStore) Lindex(key string, index int64) (string, error) { + node, err := cs.getRedis(key) + if err != nil { + return "", err + } + + return node.Lindex(key, index) +} + func (cs clusterStore) Lpop(key string) (string, error) { node, err := cs.getRedis(key) if err != nil { diff --git a/core/stores/kv/store_test.go b/core/stores/kv/store_test.go index c26a4231..ee7cd047 100644 --- a/core/stores/kv/store_test.go +++ b/core/stores/kv/store_test.go @@ -17,6 +17,36 @@ var ( s2, _ = miniredis.Run() ) +func TestRedis_Decr(t *testing.T) { + store := clusterStore{dispatcher: hash.NewConsistentHash()} + _, err := store.Decr("a") + assert.NotNil(t, err) + + runOnCluster(t, func(client Store) { + val, err := client.Decr("a") + assert.Nil(t, err) + assert.Equal(t, int64(-1), val) + val, err = client.Decr("a") + assert.Nil(t, err) + assert.Equal(t, int64(-2), val) + }) +} + +func TestRedis_DecrBy(t *testing.T) { + store := clusterStore{dispatcher: hash.NewConsistentHash()} + _, err := store.Incrby("a", 2) + assert.NotNil(t, err) + + runOnCluster(t, func(client Store) { + val, err := client.Decrby("a", 2) + assert.Nil(t, err) + assert.Equal(t, int64(-2), val) + val, err = client.Decrby("a", 3) + assert.Nil(t, err) + assert.Equal(t, int64(-5), val) + }) +} + func TestRedis_Exists(t *testing.T) { store := clusterStore{dispatcher: hash.NewConsistentHash()} _, err := store.Exists("foo") @@ -234,6 +264,8 @@ func TestRedis_List(t *testing.T) { assert.NotNil(t, err) _, err = store.Lrem("key", 0, "val") assert.NotNil(t, err) + _, err = store.Lindex("key", 0) + assert.NotNil(t, err) runOnCluster(t, func(client Store) { val, err := client.Lpush("key", "value1", "value2") @@ -245,6 +277,9 @@ func TestRedis_List(t *testing.T) { val, err = client.Llen("key") assert.Nil(t, err) assert.Equal(t, 4, val) + value, err := client.Lindex("key", 0) + assert.Nil(t, err) + assert.Equal(t, "value2", value) vals, err := client.Lrange("key", 0, 10) assert.Nil(t, err) assert.EqualValues(t, []string{"value2", "value1", "value3", "value4"}, vals) diff --git a/core/stores/redis/redis.go b/core/stores/redis/redis.go index 3fa001c4..d6fad308 100644 --- a/core/stores/redis/redis.go +++ b/core/stores/redis/redis.go @@ -238,6 +238,36 @@ func (s *Redis) BlpopEx(redisNode RedisNode, key string) (string, bool, error) { return vals[1], true, nil } +// Decr is the implementation of redis decr command. +func (s *Redis) Decr(key string) (val int64, err error) { + err = s.brk.DoWithAcceptable(func() error { + conn, err := getRedis(s) + if err != nil { + return err + } + + val, err = conn.Decr(key).Result() + return err + }, acceptable) + + return +} + +// Decrby is the implementation of redis decrby command. +func (s *Redis) Decrby(key string, increment int64) (val int64, err error) { + err = s.brk.DoWithAcceptable(func() error { + conn, err := getRedis(s) + if err != nil { + return err + } + + val, err = conn.DecrBy(key, increment).Result() + return err + }, acceptable) + + return +} + // Del deletes keys. func (s *Redis) Del(keys ...string) (val int, err error) { err = s.brk.DoWithAcceptable(func() error { @@ -765,6 +795,21 @@ func (s *Redis) Llen(key string) (val int, err error) { return } +// Lindex is the implementation of redis lindex command. +func (s *Redis) Lindex(key string, index int64) (val string, err error) { + err = s.brk.DoWithAcceptable(func() error { + conn, err := getRedis(s) + if err != nil { + return err + } + + val, err = conn.LIndex(key, index).Result() + return err + }, acceptable) + + return +} + // Lpop is the implementation of redis lpop command. func (s *Redis) Lpop(key string) (val string, err error) { err = s.brk.DoWithAcceptable(func() error { diff --git a/core/stores/redis/redis_test.go b/core/stores/redis/redis_test.go index 1e9251e1..49aee638 100644 --- a/core/stores/redis/redis_test.go +++ b/core/stores/redis/redis_test.go @@ -14,6 +14,32 @@ import ( "github.com/tal-tech/go-zero/core/stringx" ) +func TestRedis_Decr(t *testing.T) { + runOnRedis(t, func(client *Redis) { + _, err := New(client.Addr, badType()).Decr("a") + assert.NotNil(t, err) + val, err := client.Decr("a") + assert.Nil(t, err) + assert.Equal(t, int64(-1), val) + val, err = client.Decr("a") + assert.Nil(t, err) + assert.Equal(t, int64(-2), val) + }) +} + +func TestRedis_DecrBy(t *testing.T) { + runOnRedis(t, func(client *Redis) { + _, err := New(client.Addr, badType()).Decrby("a", 2) + assert.NotNil(t, err) + val, err := client.Decrby("a", 2) + assert.Nil(t, err) + assert.Equal(t, int64(-2), val) + val, err = client.Decrby("a", 3) + assert.Nil(t, err) + assert.Equal(t, int64(-5), val) + }) +} + func TestRedis_Exists(t *testing.T) { runOnRedis(t, func(client *Redis) { _, err := New(client.Addr, badType()).Exists("a") @@ -295,6 +321,11 @@ func TestRedis_List(t *testing.T) { val, err = client.Llen("key") assert.Nil(t, err) assert.Equal(t, 4, val) + _, err = New(client.Addr, badType()).Lindex("key", 1) + assert.NotNil(t, err) + value, err := client.Lindex("key", 0) + assert.Nil(t, err) + assert.Equal(t, "value2", value) vals, err := client.Lrange("key", 0, 10) assert.Nil(t, err) assert.EqualValues(t, []string{"value2", "value1", "value3", "value4"}, vals)