-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathredis.go
309 lines (258 loc) · 7.15 KB
/
redis.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
package main
import (
"context"
"errors"
"fmt"
"log"
"time"
"github.com/gomodule/redigo/redis"
)
type RedisConn struct {
conn redis.Conn
}
func NewConn(pool *redis.Pool) RedisConn {
return func() RedisConn {
return RedisConn{
conn: pool.Get(),
}
}()
}
func (c RedisConn) Close() {
c.conn.Close()
}
type RedisRequest struct {
conn RedisConn
command string
params []interface{}
wantResult bool
}
func (r RedisConn) NewRedisRequest() *RedisRequest {
return func() *RedisRequest {
return &RedisRequest{
conn: r,
}
}()
}
func (r RedisConn) do(commandName string, args ...interface{}) (reply interface{}, err error) {
return r.conn.Do(commandName, args...)
}
func (r RedisConn) doInt(commandName string, args ...interface{}) (reply int, err error) {
n, err := redis.Int(r.do(commandName, args...))
return n, err
}
func (r RedisConn) doInt64(commandName string, args ...interface{}) (reply int64, err error) {
n, err := redis.Int64(r.do(commandName, args...))
return n, err
}
func (r RedisConn) doString(commandName string, args ...interface{}) (reply string, err error) {
n, err := redis.String(r.do(commandName, args...))
return n, err
}
// Change command of the redis request struct
func (r *RedisRequest) Command(c string) {
}
// Add params into redis request struct
func (r *RedisRequest) Params(p []interface{}) {
}
// Set wantResult value into redis request struct
func (r *RedisRequest) WantResult(w bool) {
}
func (r *RedisRequest) GetBool(ctx context.Context) (bool, error) {
panic("Not implemented")
}
func (r *RedisRequest) GetInt(ctx context.Context) (bool, error) {
panic("Not implemented")
}
func (r *RedisRequest) GetString(ctx context.Context) (bool, error) {
panic("Not implemented")
}
func (r *RedisRequest) GetStringSlice(ctx context.Context) (bool, error) {
panic("Not implemented")
}
type RedisSetRequest struct {
conn RedisConn
key string
value interface{}
expireInSec int // Use one of the expiration parameters
expireAt time.Time // Will be used only if expireInSec is 0
}
func (r RedisConn) NewRedisSetRequest() *RedisSetRequest {
return func() *RedisSetRequest {
return &RedisSetRequest{
conn: r,
}
}()
}
// Set key of the redis set request struct
func (r *RedisSetRequest) Key(k string) *RedisSetRequest {
r.key = k
return r
}
// Add value into redis set request struct
func (r *RedisSetRequest) Value(v interface{}) *RedisSetRequest {
r.value = v
return r
}
// Set anount of seconds until value will be destroyed
func (r *RedisSetRequest) ExpireIn(s int) *RedisSetRequest {
r.expireInSec = s
return r
}
// Set expiration time (when the value will expire)
func (r *RedisSetRequest) ExpireAt(t time.Time) *RedisSetRequest {
r.expireAt = t
return r
}
func (r *RedisSetRequest) Set(ctx context.Context) error {
// Without expiration
if r.expireInSec == 0 && r.expireAt.IsZero() {
_, err := r.conn.do("SET", r.key, r.value)
return err
}
// With expiration
// Get number of seconds until expiration
s := func() int {
if r.expireInSec > 0 {
return r.expireInSec
}
if r.expireAt.After(time.Now()) {
return int(r.expireAt.Sub(time.Now()).Seconds())
}
return -2
}()
if s < 0 {
return errors.New("Expiration time is less than zero")
}
_, err := r.conn.do("SETEX", r.key, s, r.value)
return err
}
// Set desired wordlist of a person to the cache
func (r *RedisSetRequest) SetPersonList(PersonID int64, ListID WL) error {
if PersonID == 0 {
return errors.New("Invalid person's or list's ID")
}
if ListID >= endofwl || ListID < 0 {
return errors.New("ListID is invalid")
}
r.key = fmt.Sprintf("plist:%d", PersonID)
r.value = ListID
return r.Set(context.Background()) // TODO: use context in the future
}
// Set last action of a person to the cache
func (r *RedisSetRequest) SetLastAction(PersonID int64, action LastAction) error {
if PersonID == 0 {
return errors.New("Invalid person's ID")
}
r.key = fmt.Sprintf("lastact:%d", PersonID)
r.value = action
r.expireInSec = 3600 // one hour for making an action
return r.Set(context.Background()) // TODO: use context in the future
}
// Set number of words in the generated passwords for the person
func (r *RedisSetRequest) SetNumberOfWords(PersonID int64, n int) error {
if PersonID == 0 {
return errors.New("Invalid person's ID")
}
r.key = fmt.Sprintf("wordsn:%d", PersonID)
r.value = n
r.expireAt = time.Now().Add(365 * 24 * time.Hour) // To free some memory after a year
return r.Set(context.Background()) // TODO: use context in the future
}
// Set separator for the generated passwords for the person
func (r *RedisSetRequest) SetSeparator(PersonID int64, s string) error {
if PersonID == 0 {
return errors.New("Invalid person's ID")
}
r.key = fmt.Sprintf("sep:%d", PersonID)
r.value = s
r.expireAt = time.Now().Add(365 * 24 * time.Hour) // To free some memory after a year
return r.Set(context.Background()) // TODO: use context in the future
}
type RedisGetRequest struct {
conn RedisConn
id int64 // any id as a part of redis key (after colon)
key string // use key instead of id
}
func (r RedisConn) NewRedisGetRequest() *RedisGetRequest {
return func() *RedisGetRequest {
return &RedisGetRequest{
conn: r,
}
}()
}
// Set key for request
func (r *RedisGetRequest) Key(k string) *RedisGetRequest {
r.key = k
return r
}
// Set ID for request
func (r *RedisGetRequest) ID(id int64) *RedisGetRequest {
r.id = id
return r
}
// Get listID of person. Returns 0 if not found
func (r *RedisGetRequest) GetPersonList() WL {
if r.id == 0 {
n, err := r.conn.doInt("GET", r.key)
if err != nil {
log.Println("ERROR:", err)
return 0
}
return WL(n)
}
n, err := r.conn.doInt("GET", fmt.Sprintf("plist:%d", r.id))
if err != nil {
return 0
}
return WL(n)
}
func (r *RedisGetRequest) GetLastAction() (LastAction, error) {
la, err := r.conn.doString("GET", fmt.Sprintf("lastact:%d", r.id))
return LastAction(la), err
}
func (r *RedisGetRequest) GetWordsNumber() (int, error) {
n, err := r.conn.doInt("GET", fmt.Sprintf("wordsn:%d", r.id))
return n, err
}
func (r *RedisGetRequest) GetSeparator() (string, error) {
s, err := r.conn.doString("GET", fmt.Sprintf("sep:%d", r.id))
return s, err
}
type RedisDelRequest struct {
conn RedisConn
id int64 // any id as a part of redis key (after colon)
key string // use key instead of id
}
func (r RedisConn) NewRedisDelRequest() *RedisDelRequest {
return func() *RedisDelRequest {
return &RedisDelRequest{
conn: r,
}
}()
}
// Set key for request
func (r *RedisDelRequest) Key(k string) *RedisDelRequest {
r.key = k
return r
}
// Set ID for request
func (r *RedisDelRequest) ID(id int64) *RedisDelRequest {
r.id = id
return r
}
// Exec is used to delete value from cache.
//
// You have to specify Redis connection and key to use this function
func (r *RedisDelRequest) Exec() error {
_, err := r.conn.do("DEL", r.key)
return err
}
// You have to specify conn and id in order to use this function
func (r *RedisDelRequest) DeleteLastAction() error {
if r.id == 0 {
return errors.New("You have to specify id of a person")
}
r.Key(fmt.Sprintf("lastact:%d", r.id))
err := r.Exec()
return err
}