iris/sessions/sessiondb/redis/driver_goredis.go

210 lines
4.9 KiB
Go
Raw Normal View History

2020-10-04 15:50:21 +02:00
package redis
import (
stdContext "context"
"io"
"strconv"
"time"
"github.com/redis/go-redis/v9"
2020-10-04 15:50:21 +02:00
)
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.
2020-10-04 15:50:21 +02:00
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
2020-10-04 15:50:21 +02:00
// 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
2020-10-04 15:50:21 +02:00
}
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
2020-10-04 15:50:21 +02:00
}
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
}
2020-10-04 15:50:21 +02:00
// 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
}
2020-10-04 15:50:21 +02:00
if len(c.Clusters) > 0 {
r.Client = redis.NewClusterClient(r.mergeClusterOptions(c))
2020-10-04 15:50:21 +02:00
} else {
r.Client = redis.NewClient(r.mergeClientOptions(c))
2020-10-04 15:50:21 +02:00
}
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()
2020-10-04 15:50:21 +02:00
return pong == "PONG", err
}
// CloseConnection terminates the underline redis connection.
func (r *GoRedisDriver) CloseConnection() error {
return r.Client.Close()
2020-10-04 15:50:21 +02:00
}
// 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()
2020-10-04 15:50:21 +02:00
}
// 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()
2020-10-04 15:50:21 +02:00
}
// Exists reports whether a session exists or not.
func (r *GoRedisDriver) Exists(sid string) bool {
n, err := r.Client.Exists(defaultContext, sid).Result()
2020-10-04 15:50:21 +02:00
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()
2020-10-04 15:50:21 +02:00
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()
2020-10-04 15:50:21 +02:00
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()
2020-10-04 15:50:21 +02:00
}
// GetKeys returns all keys under the session.
func (r *GoRedisDriver) GetKeys(sid string) ([]string, error) {
return r.Client.HKeys(defaultContext, sid).Result()
2020-10-04 15:50:21 +02:00
}
// 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())
2020-10-04 15:50:21 +02:00
}
// 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()
2020-10-04 15:50:21 +02:00
}
return r.Client.HDel(defaultContext, sid, key).Err()
2020-10-04 15:50:21 +02:00
}