forked from botlabs-gg/yagpdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
redisutils.go
145 lines (123 loc) · 3.14 KB
/
redisutils.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package common
import (
"encoding/json"
"fmt"
"github.com/mediocregopher/radix.v2/redis"
"strings"
"time"
)
// GetRedisReplies is a helper func when using redis pipelines
// It retrieves n amount of replies and returns the first error it finds (but still continues to retrieve replies after that)
func GetRedisReplies(client *redis.Client, n int) ([]*redis.Resp, error) {
var err error
out := make([]*redis.Resp, n)
for i := 0; i < n; i++ {
reply := client.PipeResp()
out[i] = reply
if reply.Err != nil && err == nil {
err = reply.Err
}
}
return out, err
}
type RedisCmd struct {
Name string
Args []interface{}
}
// SafeRedisCommands Will do the following commands and stop if an error occurs
func SafeRedisCommands(client *redis.Client, cmds []*RedisCmd) ([]*redis.Resp, error) {
out := make([]*redis.Resp, 0)
for _, cmd := range cmds {
reply := client.Cmd(cmd.Name, cmd.Args...)
out = append(out, reply)
if reply.Err != nil {
return out, reply.Err
}
}
return out, nil
}
func RedisDialFunc(network, addr string) (client *redis.Client, err error) {
for {
client, err = redis.DialTimeout(network, addr, time.Second*10)
if err != nil {
errStr := err.Error()
if strings.Contains(errStr, "socket: too many open files") ||
strings.Contains(errStr, "cannot assign requested address") {
// Sleep for 100 milliseconds and try again
time.Sleep(time.Millisecond * 100)
continue
} else {
return
}
} else {
break
}
}
return
}
func GenID(client *redis.Client, key string) string {
idInt, err := client.Cmd("INCR", key).Int64()
if err != nil {
panic(err)
}
return fmt.Sprintf("r%d", idInt)
}
// GetRedisJson executes a get redis command and unmarshals the value into out
func GetRedisJson(client *redis.Client, key string, out interface{}) error {
reply := client.Cmd("GET", key)
if reply.IsType(redis.Nil) {
return nil
}
raw, err := reply.Bytes()
if err != nil {
return err
}
err = json.Unmarshal(raw, out)
return err
}
// GetRedisJson executes a get redis command and unmarshals the value into out
func GetRedisJsonDefault(client *redis.Client, key string, out interface{}) error {
reply := client.Cmd("GET", key)
if reply.IsType(redis.Nil) {
return nil
}
raw, err := reply.Bytes()
if err != nil {
return err
}
err = json.Unmarshal(raw, out)
return err
}
// SetRedisJson marshals the value and runs a set redis command for key
func SetRedisJson(client *redis.Client, key string, value interface{}) error {
serialized, err := json.Marshal(value)
if err != nil {
return err
}
err = client.Cmd("SET", key, serialized).Err
return err
}
func MustGetRedisClient() *redis.Client {
client, err := RedisPool.Get()
if err != nil {
panic("Failed retrieving redis client from pool: " + err.Error())
}
return client
}
func RedisBool(resp *redis.Resp) (b bool, err error) {
if resp.Err != nil {
return false, resp.Err
}
if resp.IsType(redis.Nil) {
return false, nil
}
if resp.IsType(redis.Int) {
i, err := resp.Int()
return i > 0, err
}
if resp.IsType(redis.Str) {
s, err := resp.Str()
return (s != "" && s != "false" && s != "0"), err
}
panic("Unknown redis reply type")
}