Skip to content

Commit

Permalink
Merge pull request #188 from rueian/improve-rueidis-store
Browse files Browse the repository at this point in the history
Make rueidis store to be more user-friendly and be more performant
  • Loading branch information
eko authored Dec 11, 2022
2 parents 4635b6a + d38a813 commit 24ff431
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 46 deletions.
2 changes: 1 addition & 1 deletion store/rueidis/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.19
require (
github.com/eko/gocache/lib/v4 v4.1.1
github.com/golang/mock v1.6.0
github.com/rueian/rueidis v0.0.86
github.com/rueian/rueidis v0.0.89
github.com/stretchr/testify v1.8.1
)

Expand Down
4 changes: 2 additions & 2 deletions store/rueidis/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY=
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rueian/rueidis v0.0.86 h1:RdzZzYnECg27zwdBHL2JN1XPVfaZclSjx6gzAQuCF/o=
github.com/rueian/rueidis v0.0.86/go.mod h1:LiKWMM/QnILwRfDZIhSIXi4vQqZ/UZy4+/aNkSCt8XA=
github.com/rueian/rueidis v0.0.89 h1:Q2TbuNXMJ2d2NegQ47uOoGOGPZLQwRuL0oX/dAlCh6k=
github.com/rueian/rueidis v0.0.89/go.mod h1:LiKWMM/QnILwRfDZIhSIXi4vQqZ/UZy4+/aNkSCt8XA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand Down
62 changes: 27 additions & 35 deletions store/rueidis/rueidis.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ const (

// RueidisStore is a store for Redis
type RueidisStore struct {
client rueidis.Client
options *lib_store.Options
cacheCompat rueidiscompat.CacheCompat
compat rueidiscompat.Cmdable
client rueidis.Client
options *lib_store.Options
}

// NewRueidis creates a new store to Redis instance(s)
Expand All @@ -37,43 +35,39 @@ func NewRueidis(client rueidis.Client, options ...lib_store.Option) *RueidisStor
}

return &RueidisStore{
client: client,
cacheCompat: rueidiscompat.NewAdapter(client).Cache(appliedOptions.ClientSideCacheExpiration),
compat: rueidiscompat.NewAdapter(client),
options: appliedOptions,
client: client,
options: appliedOptions,
}
}

// Get returns data stored from a given key
func (s *RueidisStore) Get(ctx context.Context, key any) (any, error) {
object := s.client.DoCache(ctx, s.client.B().Get().Key(key.(string)).Cache(), s.options.ClientSideCacheExpiration)
if object.RedisError() != nil && object.RedisError().IsNil() {
return nil, lib_store.NotFoundWithCause(object.Error())
cmd := s.client.B().Get().Key(key.(string)).Cache()
res := s.client.DoCache(ctx, cmd, s.options.ClientSideCacheExpiration)
str, err := res.ToString()
if rueidis.IsRedisNil(err) {
err = lib_store.NotFoundWithCause(err)
}
return object, object.Error()
return str, err
}

// GetWithTTL returns data stored from a given key and its corresponding TTL
func (s *RueidisStore) GetWithTTL(ctx context.Context, key any) (any, time.Duration, error) {
// get object first
object, err := s.Get(ctx, key)
if err != nil {
return nil, 0, err
cmd := s.client.B().Get().Key(key.(string)).Cache()
res := s.client.DoCache(ctx, cmd, s.options.ClientSideCacheExpiration)
str, err := res.ToString()
if rueidis.IsRedisNil(err) {
err = lib_store.NotFoundWithCause(err)
}

// get TTL and return
ttl, err := s.cacheCompat.TTL(ctx, key.(string)).Result()
if err != nil {
return nil, 0, err
}

return object, ttl, err
return str, time.Duration(res.CacheTTL()) * time.Second, err
}

// Set defines data in Redis for given key identifier
func (s *RueidisStore) Set(ctx context.Context, key any, value any, options ...lib_store.Option) error {
opts := lib_store.ApplyOptionsWithDefault(s.options, options...)
err := s.compat.Set(ctx, key.(string), value, opts.Expiration).Err()
ttl := int64(opts.Expiration.Seconds())
cmd := s.client.B().Set().Key(key.(string)).Value(value.(string)).ExSeconds(ttl).Build()
err := s.client.Do(ctx, cmd).Error()
if err != nil {
return err
}
Expand All @@ -86,17 +80,19 @@ func (s *RueidisStore) Set(ctx context.Context, key any, value any, options ...l
}

func (s *RueidisStore) setTags(ctx context.Context, key any, tags []string) {
ttl := 720 * time.Hour
for _, tag := range tags {
tagKey := fmt.Sprintf(RueidisTagPattern, tag)
s.compat.SAdd(ctx, tagKey, key.(string))
s.compat.Expire(ctx, tagKey, 720*time.Hour)
s.client.DoMulti(ctx,
s.client.B().Sadd().Key(tagKey).Member(key.(string)).Build(),
s.client.B().Expire().Key(tagKey).Seconds(int64(ttl.Seconds())).Build(),
)
}
}

// Delete removes data from Redis for given key identifier
func (s *RueidisStore) Delete(ctx context.Context, key any) error {
_, err := s.compat.Del(ctx, key.(string)).Result()
return err
return s.client.Do(ctx, s.client.B().Del().Key(key.(string)).Build()).Error()
}

// Invalidate invalidates some cache data in Redis for given options
Expand All @@ -107,7 +103,7 @@ func (s *RueidisStore) Invalidate(ctx context.Context, options ...lib_store.Inva
for _, tag := range tags {
tagKey := fmt.Sprintf(RueidisTagPattern, tag)

cacheKeys, err := s.cacheCompat.SMembers(ctx, tagKey).Result()
cacheKeys, err := s.client.Do(ctx, s.client.B().Smembers().Key(tagKey).Build()).AsStrSlice()
if err != nil {
continue
}
Expand All @@ -130,9 +126,5 @@ func (s *RueidisStore) GetType() string {

// Clear resets all data in the store
func (s *RueidisStore) Clear(ctx context.Context) error {
if err := s.compat.FlushAll(ctx).Err(); err != nil {
return err
}

return nil
return rueidiscompat.NewAdapter(s.client).FlushAll(ctx).Err()
}
4 changes: 2 additions & 2 deletions store/rueidis/rueidis_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func BenchmarkRueidisSet(b *testing.B) {
b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
for i := 0; i < b.N*n; i++ {
key := fmt.Sprintf("test-%d", n)
value := []byte(fmt.Sprintf("value-%d", n))
value := fmt.Sprintf("value-%d", n)

store.Set(ctx, key, value, lib_store.WithTags([]string{fmt.Sprintf("tag-%d", n)}))
}
Expand All @@ -51,7 +51,7 @@ func BenchmarkRueidisGet(b *testing.B) {
store := NewRueidis(ruedisClient, lib_store.WithExpiration(time.Hour*4))

key := "test"
value := []byte("value")
value := "value"

_ = store.Set(ctx, key, value)

Expand Down
17 changes: 11 additions & 6 deletions store/rueidis/rueidis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestRueidisGet(t *testing.T) {

// rueidis mock client
client := mock.NewClient(ctrl)
client.EXPECT().DoCache(ctx, mock.Match("GET", "my-key"), defaultClientSideCacheExpiration).Return(mock.Result(mock.RedisString("")))
client.EXPECT().DoCache(ctx, mock.Match("GET", "my-key"), defaultClientSideCacheExpiration).Return(mock.Result(mock.RedisString("my-value")))

store := NewRueidis(client)

Expand All @@ -46,7 +46,7 @@ func TestRueidisGet(t *testing.T) {

// Then
assert.Nil(t, err)
assert.NotNil(t, value)
assert.Equal(t, value, "my-value")
}

func TestRueidisGetNotFound(t *testing.T) {
Expand All @@ -66,7 +66,7 @@ func TestRueidisGetNotFound(t *testing.T) {

// Then
assert.NotNil(t, err)
assert.Nil(t, value)
assert.Equal(t, value, "")
}

func TestRueidisSet(t *testing.T) {
Expand Down Expand Up @@ -123,8 +123,13 @@ func TestRedisSetWithTags(t *testing.T) {

client := mock.NewClient(ctrl)
client.EXPECT().Do(ctx, mock.Match("SET", cacheKey, cacheValue, "EX", "10")).Return(mock.Result(mock.RedisString("")))
client.EXPECT().Do(ctx, mock.Match("SADD", "gocache_tag_tag1", "my-key")).Return(mock.Result(mock.RedisString("")))
client.EXPECT().Do(ctx, mock.Match("EXPIRE", "gocache_tag_tag1", "2592000")).Return(mock.Result(mock.RedisString("")))
client.EXPECT().DoMulti(ctx,
mock.Match("SADD", "gocache_tag_tag1", "my-key"),
mock.Match("EXPIRE", "gocache_tag_tag1", "2592000"),
).Return([]rueidis.RedisResult{
mock.Result(mock.RedisString("")),
mock.Result(mock.RedisString("")),
})

store := NewRueidis(client, lib_store.WithExpiration(time.Second*10))

Expand Down Expand Up @@ -162,7 +167,7 @@ func TestRedisInvalidate(t *testing.T) {
ctx := context.Background()

client := mock.NewClient(ctrl)
client.EXPECT().DoCache(ctx, mock.Match("SMEMBERS", "gocache_tag_tag1"), defaultClientSideCacheExpiration).Return(mock.Result(mock.RedisArray()))
client.EXPECT().Do(ctx, mock.Match("SMEMBERS", "gocache_tag_tag1")).Return(mock.Result(mock.RedisArray()))
client.EXPECT().Do(ctx, mock.Match("DEL", "gocache_tag_tag1")).Return(mock.Result(mock.RedisInt64(1)))

store := NewRueidis(client)
Expand Down

0 comments on commit 24ff431

Please sign in to comment.