-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
driver_goredis.go
209 lines (167 loc) · 4.88 KB
/
driver_goredis.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
package redis
import (
stdContext "context"
"io"
"strconv"
"time"
"github.com/redis/go-redis/v9"
)
type (
// Options is just a type alias for the go-redis Client Options.
Options = redis.Options
// ClusterOptions is just a type alias for the go-redis Cluster Client Options.
ClusterOptions = redis.ClusterOptions
)
// GoRedisClient is the interface which both
// go-redis's Client and Cluster Client implements.
type GoRedisClient interface {
redis.Cmdable // Commands.
io.Closer // CloseConnection.
}
// GoRedisDriver implements the Sessions Database Driver
// for the go-redis redis driver. See driver.go file.
type GoRedisDriver struct {
// Both Client and ClusterClient implements this interface.
// Custom one can be directly passed but if so, the
// Connect method does nothing (so all connection and client settings are ignored).
Client GoRedisClient
// Customize any go-redis fields manually
// before Connect.
ClientOptions Options
ClusterOptions ClusterOptions
}
var defaultContext = stdContext.Background()
func (r *GoRedisDriver) mergeClientOptions(c Config) *Options {
opts := r.ClientOptions
if opts.Addr == "" {
opts.Addr = c.Addr
}
if opts.Username == "" {
opts.Username = c.Username
}
if opts.Password == "" {
opts.Password = c.Password
}
if opts.DB == 0 {
opts.DB, _ = strconv.Atoi(c.Database)
}
if opts.ReadTimeout == 0 {
opts.ReadTimeout = c.Timeout
}
if opts.WriteTimeout == 0 {
opts.WriteTimeout = c.Timeout
}
if opts.Network == "" {
opts.Network = c.Network
}
if opts.TLSConfig == nil {
opts.TLSConfig = c.TLSConfig
}
if opts.PoolSize == 0 {
opts.PoolSize = c.MaxActive
}
return &opts
}
func (r *GoRedisDriver) mergeClusterOptions(c Config) *ClusterOptions {
opts := r.ClusterOptions
if opts.Username == "" {
opts.Username = c.Username
}
if opts.Password == "" {
opts.Password = c.Password
}
if opts.ReadTimeout == 0 {
opts.ReadTimeout = c.Timeout
}
if opts.WriteTimeout == 0 {
opts.WriteTimeout = c.Timeout
}
if opts.TLSConfig == nil {
opts.TLSConfig = c.TLSConfig
}
if opts.PoolSize == 0 {
opts.PoolSize = c.MaxActive
}
if len(opts.Addrs) == 0 {
opts.Addrs = c.Clusters
}
return &opts
}
// SetClient sets an existing go redis client to the sessions redis driver.
//
// Returns itself.
func (r *GoRedisDriver) SetClient(goRedisClient GoRedisClient) *GoRedisDriver {
r.Client = goRedisClient
return r
}
// Connect initializes the redis client.
func (r *GoRedisDriver) Connect(c Config) error {
if r.Client != nil { // if a custom one was given through SetClient.
return nil
}
if len(c.Clusters) > 0 {
r.Client = redis.NewClusterClient(r.mergeClusterOptions(c))
} else {
r.Client = redis.NewClient(r.mergeClientOptions(c))
}
return nil
}
// PingPong sends a ping message and reports whether
// the PONG message received successfully.
func (r *GoRedisDriver) PingPong() (bool, error) {
pong, err := r.Client.Ping(defaultContext).Result()
return pong == "PONG", err
}
// CloseConnection terminates the underline redis connection.
func (r *GoRedisDriver) CloseConnection() error {
return r.Client.Close()
}
// Set stores a "value" based on the session's "key".
// The value should be type of []byte, so unmarshal can happen.
func (r *GoRedisDriver) Set(sid, key string, value interface{}) error {
return r.Client.HSet(defaultContext, sid, key, value).Err()
}
// Get returns the associated value of the session's given "key".
func (r *GoRedisDriver) Get(sid, key string) (interface{}, error) {
return r.Client.HGet(defaultContext, sid, key).Bytes()
}
// Exists reports whether a session exists or not.
func (r *GoRedisDriver) Exists(sid string) bool {
n, err := r.Client.Exists(defaultContext, sid).Result()
if err != nil {
return false
}
return n > 0
}
// TTL returns any TTL value of the session.
func (r *GoRedisDriver) TTL(sid string) time.Duration {
dur, err := r.Client.TTL(defaultContext, sid).Result()
if err != nil {
return 0
}
return dur
}
// UpdateTTL sets expiration duration of the session.
func (r *GoRedisDriver) UpdateTTL(sid string, newLifetime time.Duration) error {
_, err := r.Client.Expire(defaultContext, sid, newLifetime).Result()
return err
}
// GetAll returns all the key values under the session.
func (r *GoRedisDriver) GetAll(sid string) (map[string]string, error) {
return r.Client.HGetAll(defaultContext, sid).Result()
}
// GetKeys returns all keys under the session.
func (r *GoRedisDriver) GetKeys(sid string) ([]string, error) {
return r.Client.HKeys(defaultContext, sid).Result()
}
// Len returns the total length of key-values of the session.
func (r *GoRedisDriver) Len(sid string) int {
return int(r.Client.HLen(defaultContext, sid).Val())
}
// Delete removes a value from the redis store.
func (r *GoRedisDriver) Delete(sid, key string) error {
if key == "" {
return r.Client.Del(defaultContext, sid).Err()
}
return r.Client.HDel(defaultContext, sid, key).Err()
}