/
list.go
60 lines (49 loc) · 1.29 KB
/
list.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package ro
import (
"context"
"reflect"
"github.com/gomodule/redigo/redis"
"github.com/pkg/errors"
"github.com/izumin5210/ro/rq"
)
// List implements the types.Store interface.
func (s *redisStore) List(ctx context.Context, dest interface{}, mods ...rq.Modifier) error {
dt := reflect.ValueOf(dest)
if dt.Kind() != reflect.Ptr || dt.IsNil() {
return errors.New("must pass a slice ptr")
}
dt = dt.Elem()
if dt.Kind() != reflect.Slice {
return errors.New("must pass a slice ptr")
}
keys, err := s.selectKeys(ctx, mods)
if err != nil {
return errors.Wrap(err, "failed to select query")
}
conn, err := s.pool.GetContext(ctx)
if err != nil {
return errors.Wrap(err, "failed to acquire a connection")
}
defer conn.Close()
for _, key := range keys {
err := conn.Send("HGETALL", key)
if err != nil {
return errors.Wrapf(err, "failed to send HGETALL %s", key)
}
}
conn.Flush()
vt := dt.Type().Elem().Elem()
for _, key := range keys {
v, err := redis.Values(conn.Receive())
if err != nil {
return errors.Wrap(err, "faild to receive or cast redis command result")
}
vv := reflect.New(vt)
err = redis.ScanStruct(v, vv.Interface())
if err != nil {
return errors.Wrapf(err, "faild to scan struct %s %x", key, v)
}
dt.Set(reflect.Append(dt, vv))
}
return nil
}