-
Notifications
You must be signed in to change notification settings - Fork 2
/
lists.go
102 lines (79 loc) · 2.62 KB
/
lists.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package redis
import (
"context"
"reflect"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"libs.altipla.consulting/errors"
)
type StringsList struct {
db *Database
key string
}
func (list *StringsList) Len(ctx context.Context) (int64, error) {
return list.db.Cmdable(ctx).LLen(list.key).Result()
}
func (list *StringsList) GetRange(ctx context.Context, start, end int64) ([]string, error) {
return list.db.Cmdable(ctx).LRange(list.key, start, end).Result()
}
func (list *StringsList) GetAll(ctx context.Context) ([]string, error) {
return list.GetRange(ctx, 0, -1)
}
func (list *StringsList) Add(ctx context.Context, values []string) error {
return list.db.Cmdable(ctx).LPush(list.key, values).Err()
}
func (list *StringsList) Remove(ctx context.Context, value string) error {
return list.db.Cmdable(ctx).LRem(list.key, 1, value).Err()
}
type ProtoList struct {
db *Database
key string
}
func (list *ProtoList) Len(ctx context.Context) (int64, error) {
return list.db.Cmdable(ctx).LLen(list.key).Result()
}
func (list *ProtoList) GetRange(ctx context.Context, start, end int64, result interface{}) error {
rt := reflect.TypeOf(result)
rv := reflect.ValueOf(result)
msg := reflect.TypeOf((*proto.Message)(nil)).Elem()
if rt.Kind() != reflect.Ptr || rt.Elem().Kind() != reflect.Slice || !rt.Elem().Elem().Implements(msg) {
return errors.Errorf("expected a pointer to a slice for the result, received %T", result)
}
dest := reflect.MakeSlice(rt.Elem(), 0, 0)
redisResult, err := list.db.Cmdable(ctx).LRange(list.key, start, end).Result()
if err != nil {
return errors.Trace(err)
}
for _, item := range redisResult {
value := reflect.New(rt.Elem().Elem().Elem())
if err := unmarshalProto(item, value.Interface().(proto.Message)); err != nil {
return errors.Trace(err)
}
dest = reflect.Append(dest, value)
}
rv.Elem().Set(dest)
return nil
}
func (list *ProtoList) GetAll(ctx context.Context, result interface{}) error {
return list.GetRange(ctx, 0, -1, result)
}
func (list *ProtoList) Add(ctx context.Context, values ...proto.Message) error {
m := new(jsonpb.Marshaler)
members := make([]interface{}, len(values))
for i, value := range values {
encoded, err := m.MarshalToString(value)
if err != nil {
return errors.Trace(err)
}
members[i] = encoded
}
return list.db.Cmdable(ctx).LPush(list.key, members...).Err()
}
func (list *ProtoList) Remove(ctx context.Context, value proto.Message) error {
m := new(jsonpb.Marshaler)
encoded, err := m.MarshalToString(value)
if err != nil {
return errors.Trace(err)
}
return list.db.Cmdable(ctx).LRem(list.key, 1, encoded).Err()
}