Skip to content

Commit

Permalink
feature: get multiple with redis pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
Francisco committed Nov 30, 2022
1 parent 984b85e commit f981512
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
21 changes: 21 additions & 0 deletions keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type (
Get(key string) (any, error)
GetOrLock(key string) (any, *redsync.Mutex, error)
GetOrSet(key string, fn GetterFn, opts ...func(Item)) ([]byte, error)
GetMultiple(keys []string) ([]any, error)
Store(*redsync.Mutex, Item) error
StoreWithoutBlocking(Item) error
StoreMultiWithoutBlocking([]Item) error
Expand Down Expand Up @@ -155,6 +156,26 @@ func (k *keeper) Get(key string) (cachedItem any, err error) {
return nil, nil
}

func (k *keeper) GetMultiple(keys []string) (cachedItems []any, err error) {
if k.disableCaching {
return
}
c := k.connPool.Get()
c.Send("MULTI")
for _, key := range keys {
err = c.Send("GET", key)
if err != nil {
return
}
}
r, err := c.Do("EXEC")
if err != nil {
return nil, err
}

return redigo.Values(r, err)
}

// GetOrLock :nodoc:
func (k *keeper) GetOrLock(key string) (cachedItem any, mutex *redsync.Mutex, err error) {
if k.disableCaching {
Expand Down
39 changes: 37 additions & 2 deletions keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import (
"testing"
"time"

"github.com/stretchr/testify/require"

redigo "github.com/gomodule/redigo/redis"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/alicebob/miniredis/v2"
)
Expand Down Expand Up @@ -1166,3 +1165,39 @@ func TestHashScan_Empty(t *testing.T) {
assert.Empty(t, result)
assert.EqualValues(t, 0, cursor)
}

func TestGetMultiple(t *testing.T) {
k := NewKeeper()

m, err := miniredis.Run()
assert.NoError(t, err)

r := newRedisConn(m.Addr())
k.SetConnectionPool(r)
k.SetLockConnectionPool(r)
k.SetWaitTime(1 * time.Second) // override wait time to 1 second

keys := []string{"a", "b", "c"}
items := map[string]string{"a": "A", "b": "B", "c": "C"}
for key, val := range items {
k.StoreWithoutBlocking(NewItem(key, val))
}

t.Run("success", func(t *testing.T) {
res, err := k.GetMultiple(keys)
assert.NoError(t, err)
for i, key := range keys {
assert.EqualValues(t, items[key], res[i])
}
})

t.Run("success with missing cache", func(t *testing.T) {
keys2 := append(keys, "d")
res, err := k.GetMultiple(keys2)
assert.NoError(t, err)
for i, key := range keys {
assert.EqualValues(t, items[key], res[i])
}
assert.EqualValues(t, res[len(res)-1], nil)
})
}

0 comments on commit f981512

Please sign in to comment.