refract package gredis

This commit is contained in:
John Guo
2021-09-23 21:23:22 +08:00
parent 6fa0ad5793
commit 6eee72b336
14 changed files with 389 additions and 223 deletions

View File

@ -14,33 +14,10 @@
package gredis
import (
"context"
"github.com/gogf/gf/container/gvar"
"github.com/gogf/gf/errors/gcode"
"github.com/gogf/gf/errors/gerror"
"time"
)
// Redis client.
type Redis struct {
adapter Adapter
}
// Config is redis configuration.
type Config struct {
Host string `json:"host"`
Port int `json:"port"`
Db int `json:"db"`
Pass string `json:"pass"` // Password for AUTH.
MaxIdle int `json:"maxIdle"` // Maximum number of connections allowed to be idle (default is 10)
MaxActive int `json:"maxActive"` // Maximum number of connections limit (default is 0 means no limit).
IdleTimeout time.Duration `json:"idleTimeout"` // Maximum idle time for connection (default is 10 seconds, not allowed to be set to 0)
MaxConnLifetime time.Duration `json:"maxConnLifetime"` // Maximum lifetime of the connection (default is 30 seconds, not allowed to be set to 0)
ConnectTimeout time.Duration `json:"connectTimeout"` // Dial connection timeout.
TLS bool `json:"tls"` // Specifies the config to use when a TLS connection is dialed.
TLSSkipVerify bool `json:"tlsSkipVerify"` // Disables server name verification when connecting over TLS.
}
func New(config ...*Config) (*Redis, error) {
if len(config) > 0 {
return &Redis{adapter: NewAdapterRedigo(config[0])}, nil
@ -58,45 +35,3 @@ func New(config ...*Config) (*Redis, error) {
func NewWithAdapter(adapter Adapter) *Redis {
return &Redis{adapter: adapter}
}
func (r *Redis) SetAdapter(adapter Adapter) {
r.adapter = adapter
}
// Conn returns a raw underlying connection object,
// which expose more methods to communicate with server.
// **You should call Close function manually if you do not use this connection any further.**
func (r *Redis) Conn(ctx context.Context) (Conn, error) {
return r.adapter.Conn(ctx)
}
// Stats returns pool's statistics.
func (r *Redis) Stats(ctx context.Context) (Stats, error) {
return r.adapter.Stats(ctx)
}
// Do sends a command to the server and returns the received reply.
// Do automatically get a connection from pool, and close it when the reply received.
// It does not really "close" the connection, but drops it back to the connection pool.
func (r *Redis) Do(ctx context.Context, command string, args ...interface{}) (*gvar.Var, error) {
conn, err := r.Conn(ctx)
if err != nil {
return nil, err
}
defer conn.Close(ctx)
if len(args) > 0 {
lastElement := args[len(args)-1]
switch option := lastElement.(type) {
case Option:
return conn.Do(ctx, command, args, &option)
case *Option:
return conn.Do(ctx, command, args, option)
default:
return conn.Do(ctx, command, args, nil)
}
}
return conn.Do(ctx, command, args, nil)
}

View File

@ -28,7 +28,6 @@ import (
type AdapterRedigo struct {
pool *redis.Pool // Underlying connection pool.
config *Config // Configuration.
group string // Configuration group.
}
const (
@ -86,12 +85,12 @@ func NewAdapterRedigo(config *Config) *AdapterRedigo {
intlog.Printf(context.TODO(), `open new connection, config:%+v`, config)
// AUTH
if len(config.Pass) > 0 {
if _, err := c.Do("AUTH", config.Pass); err != nil {
if _, err = c.Do("AUTH", config.Pass); err != nil {
return nil, err
}
}
// DB
if _, err := c.Do("SELECT", config.Db); err != nil {
if _, err = c.Do("SELECT", config.Db); err != nil {
return nil, err
}
return c, nil

View File

@ -68,7 +68,7 @@ func (c *localAdapterRedisConn) Do(ctx context.Context, command string, args []i
// Receive receives a single reply as gvar.Var from the Redis server.
func (c *localAdapterRedisConn) Receive(ctx context.Context, option *Option) (*gvar.Var, error) {
if option == nil {
option = &Option{}
option = defaultOption()
}
return resultToVar(c.ReceiveWithTimeout(option.ReadTimeout))
}

View File

@ -11,6 +11,7 @@ import (
"github.com/gogf/gf/errors/gcode"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/intlog"
"time"
"github.com/gogf/gf/container/gmap"
"github.com/gogf/gf/text/gregex"
@ -18,6 +19,21 @@ import (
"github.com/gogf/gf/util/gconv"
)
// Config is redis configuration.
type Config struct {
Host string `json:"host"`
Port int `json:"port"`
Db int `json:"db"`
Pass string `json:"pass"` // Password for AUTH.
MaxIdle int `json:"maxIdle"` // Maximum number of connections allowed to be idle (default is 10)
MaxActive int `json:"maxActive"` // Maximum number of connections limit (default is 0 means no limit).
IdleTimeout time.Duration `json:"idleTimeout"` // Maximum idle time for connection (default is 10 seconds, not allowed to be set to 0)
MaxConnLifetime time.Duration `json:"maxConnLifetime"` // Maximum lifetime of the connection (default is 30 seconds, not allowed to be set to 0)
ConnectTimeout time.Duration `json:"connectTimeout"` // Dial connection timeout.
TLS bool `json:"tls"` // Specifies the config to use when a TLS connection is dialed.
TLSSkipVerify bool `json:"tlsSkipVerify"` // Disables server name verification when connecting over TLS.
}
const (
DefaultGroupName = "default" // Default configuration group name.
DefaultRedisPort = 6379 // Default redis port configuration if not passed.

View File

@ -6,7 +6,11 @@
package gredis
import "github.com/gogf/gf/container/gmap"
import (
"context"
"github.com/gogf/gf/container/gmap"
"github.com/gogf/gf/internal/intlog"
)
var (
// Instance map
@ -23,8 +27,11 @@ func Instance(name ...string) *Redis {
}
v := instances.GetOrSetFuncLock(group, func() interface{} {
if config, ok := GetConfig(group); ok {
r := NewAdapterRedigo(config)
r.group = group
r, err := New(config)
if err != nil {
intlog.Error(context.TODO(), err)
return nil
}
return r
}
return nil

View File

@ -0,0 +1,86 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gredis
import (
"context"
"github.com/gogf/gf/container/gvar"
"github.com/gogf/gf/errors/gcode"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/intlog"
)
// Redis client.
type Redis struct {
adapter Adapter
}
const (
errorNilRedis = `the Redis object is nil`
)
func (r *Redis) SetAdapter(adapter Adapter) {
if r == nil {
return
}
r.adapter = adapter
}
func (r *Redis) GetAdapter() Adapter {
if r == nil {
return nil
}
return r.adapter
}
// Conn returns a raw underlying connection object,
// which expose more methods to communicate with server.
// **You should call Close function manually if you do not use this connection any further.**
func (r *Redis) Conn(ctx context.Context) (*RedisConn, error) {
if r == nil {
return nil, gerror.NewCode(gcode.CodeInvalidParameter, errorNilRedis)
}
conn, err := r.adapter.Conn(ctx)
if err != nil {
return nil, err
}
return &RedisConn{conn: conn}, nil
}
// Stats returns pool's statistics.
func (r *Redis) Stats(ctx context.Context) (Stats, error) {
if r == nil {
return nil, gerror.NewCode(gcode.CodeInvalidParameter, errorNilRedis)
}
return r.adapter.Stats(ctx)
}
// Do sends a command to the server and returns the received reply.
// Do automatically get a connection from pool, and close it when the reply received.
// It does not really "close" the connection, but drops it back to the connection pool.
func (r *Redis) Do(ctx context.Context, command string, args ...interface{}) (*gvar.Var, error) {
if r == nil {
return nil, gerror.NewCode(gcode.CodeInvalidParameter, errorNilRedis)
}
conn, err := r.Conn(ctx)
if err != nil {
return nil, err
}
defer func() {
if err := conn.Close(ctx); err != nil {
intlog.Error(ctx, err)
}
}()
return conn.Do(ctx, command, args...)
}
func (r *Redis) Close(ctx context.Context) error {
if r == nil {
return gerror.NewCode(gcode.CodeInvalidParameter, errorNilRedis)
}
return r.adapter.Close(ctx)
}

View File

@ -0,0 +1,38 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gredis
import (
"context"
"github.com/gogf/gf/container/gvar"
)
type RedisConn struct {
conn Conn
}
func (c *RedisConn) Do(ctx context.Context, command string, args ...interface{}) (reply *gvar.Var, err error) {
args, option := parseArgsToArgsAndOption(args)
return c.conn.Do(ctx, command, args, option)
}
// Receive receives a single reply as gvar.Var from the Redis server.
func (c *RedisConn) Receive(ctx context.Context, option ...*Option) (*gvar.Var, error) {
var (
usedOption *Option
)
if len(option) > 0 {
usedOption = option[0]
} else {
usedOption = defaultOption()
}
return c.conn.Receive(ctx, usedOption)
}
func (c *RedisConn) Close(ctx context.Context) error {
return c.conn.Close(ctx)
}

View File

@ -0,0 +1,25 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gredis
func defaultOption() *Option {
return &Option{}
}
func parseArgsToArgsAndOption(arguments []interface{}) (args []interface{}, option *Option) {
if length := len(arguments); length > 0 {
lastElement := arguments[length-1]
switch result := lastElement.(type) {
case Option:
return arguments[:length-1], &result
case *Option:
return arguments[:length-1], result
}
}
return arguments, defaultOption()
}

View File

@ -22,37 +22,42 @@ func TestConn_DoWithTimeout(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNil(redis)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
conn, err := redis.Conn(ctx)
t.AssertNil(err)
defer conn.Close(ctx)
_, err := conn.Do(ctx, "set", "test", "123", &gredis.Option{ReadTimeout: time.Second})
_, err = conn.Do(ctx, "set", "test", "123", &gredis.Option{ReadTimeout: time.Second})
t.Assert(err, nil)
defer conn.DoWithTimeout(time.Second, "del", "test")
defer conn.Do(ctx, "del", "test")
r, err := conn.DoWithTimeout(time.Second, "get", "test")
r, err := conn.Do(ctx, "get", "test", &gredis.Option{ReadTimeout: time.Second})
t.Assert(err, nil)
t.Assert(r, "123")
t.Assert(r.String(), "123")
})
}
func TestConn_ReceiveVarWithTimeout(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis := gredis.New(config)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
conn := redis.Conn()
defer conn.Close()
defer redis.Close(ctx)
_, err := conn.DoVarWithTimeout(time.Second, "Subscribe", "gf")
t.Assert(err, nil)
conn, err := redis.Conn(ctx)
t.AssertNil(err)
defer conn.Close(ctx)
v, err := redis.DoVarWithTimeout(time.Second, "PUBLISH", "gf", "test")
_, err = conn.Do(ctx, "Subscribe", "gf", &gredis.Option{ReadTimeout: time.Second})
t.AssertNil(err)
v, err := redis.Do(ctx, "PUBLISH", "gf", "test", &gredis.Option{ReadTimeout: time.Second})
t.Assert(err, nil)
t.Assert(v.String(), "1")
v, _ = conn.ReceiveVar()
v, _ = conn.Receive(ctx)
t.Assert(len(v.Strings()), 3)
t.Assert(v.Strings()[2], "test")
})

View File

@ -31,27 +31,32 @@ var (
func Test_NewClose(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis := gredis.New(config)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
err := redis.Close()
t.Assert(err, nil)
err = redis.Close(ctx)
t.AssertNil(err)
})
}
func Test_Do(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis := gredis.New(config)
defer redis.Close()
_, err := redis.Do("SET", "k", "v")
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
_, err = redis.Do(ctx, "SET", "k", "v")
t.Assert(err, nil)
r, err := redis.Do("GET", "k")
r, err := redis.Do(ctx, "GET", "k")
t.Assert(err, nil)
t.Assert(r, []byte("v"))
_, err = redis.Do("DEL", "k")
_, err = redis.Do(ctx, "DEL", "k")
t.Assert(err, nil)
r, err = redis.Do("GET", "k")
r, err = redis.Do(ctx, "GET", "k")
t.Assert(err, nil)
t.Assert(r, nil)
})
@ -59,26 +64,30 @@ func Test_Do(t *testing.T) {
func Test_Stats(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis := gredis.New(config)
defer redis.Close()
redis.SetMaxIdle(2)
redis.SetMaxActive(100)
redis.SetIdleTimeout(500 * time.Millisecond)
redis.SetMaxConnLifetime(500 * time.Millisecond)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
array := make([]*gredis.Conn, 0)
array := make([]*gredis.RedisConn, 0)
for i := 0; i < 10; i++ {
array = append(array, redis.Conn())
conn, err := redis.Conn(ctx)
t.AssertNil(err)
array = append(array, conn)
}
stats := redis.Stats()
t.Assert(stats.ActiveCount, 10)
t.Assert(stats.IdleCount, 0)
stats, err := redis.Stats(ctx)
t.AssertNil(err)
t.Assert(stats.ActiveCount(), 10)
t.Assert(stats.IdleCount(), 0)
for i := 0; i < 10; i++ {
array[i].Close()
t.AssertNil(array[i].Close(ctx))
}
stats = redis.Stats()
t.Assert(stats.ActiveCount, 2)
t.Assert(stats.IdleCount, 2)
stats, err = redis.Stats(ctx)
t.AssertNil(err)
t.Assert(stats.ActiveCount(), 10)
t.Assert(stats.IdleCount(), 10)
//time.Sleep(3000*time.Millisecond)
//stats = redis.Stats()
//fmt.Println(stats)
@ -89,23 +98,27 @@ func Test_Stats(t *testing.T) {
func Test_Conn(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis := gredis.New(config)
defer redis.Close()
conn := redis.Conn()
defer conn.Close()
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
conn, err := redis.Conn(ctx)
t.AssertNil(err)
defer conn.Close(ctx)
key := gconv.String(gtime.TimestampNano())
value := []byte("v")
r, err := conn.Do("SET", key, value)
r, err := conn.Do(ctx, "SET", key, value)
t.Assert(err, nil)
r, err = conn.Do("GET", key)
r, err = conn.Do(ctx, "GET", key)
t.Assert(err, nil)
t.Assert(r, value)
_, err = conn.Do("DEL", key)
_, err = conn.Do(ctx, "DEL", key)
t.Assert(err, nil)
r, err = conn.Do("GET", key)
r, err = conn.Do(ctx, "GET", key)
t.Assert(err, nil)
t.Assert(r, nil)
})
@ -116,22 +129,24 @@ func Test_Instance(t *testing.T) {
group := "my-test"
gredis.SetConfig(config, group)
defer gredis.RemoveConfig(group)
redis := gredis.Instance(group)
defer redis.Close()
defer redis.Close(ctx)
conn := redis.Conn()
defer conn.Close()
conn, err := redis.Conn(ctx)
t.AssertNil(err)
defer conn.Close(ctx)
_, err := conn.Do("SET", "k", "v")
_, err = conn.Do(ctx, "SET", "k", "v")
t.Assert(err, nil)
r, err := conn.Do("GET", "k")
r, err := conn.Do(ctx, "GET", "k")
t.Assert(err, nil)
t.Assert(r, []byte("v"))
_, err = conn.Do("DEL", "k")
_, err = conn.Do(ctx, "DEL", "k")
t.Assert(err, nil)
r, err = conn.Do("GET", "k")
r, err = conn.Do(ctx, "GET", "k")
t.Assert(err, nil)
t.Assert(r, nil)
})
@ -145,8 +160,12 @@ func Test_Error(t *testing.T) {
Db: 1,
ConnectTimeout: time.Second,
}
redis := gredis.New(config1)
_, err := redis.Do("info")
redis, err := gredis.New(config1)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
_, err = redis.Do(ctx, "info")
t.AssertNE(err, nil)
config1 = &gredis.Config{
@ -154,35 +173,43 @@ func Test_Error(t *testing.T) {
Port: 6379,
Db: 100,
}
redis = gredis.New(config1)
_, err = redis.Do("info")
redis, err = gredis.New(config1)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
_, err = redis.Do(ctx, "info")
t.AssertNE(err, nil)
redis = gredis.Instance("gf")
t.Assert(redis == nil, true)
gredis.ClearConfig()
redis = gredis.New(config)
defer redis.Close()
_, err = redis.DoVar("SET", "k", "v")
redis, err = gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
_, err = redis.Do(ctx, "SET", "k", "v")
t.Assert(err, nil)
v, err := redis.DoVar("GET", "k")
v, err := redis.Do(ctx, "GET", "k")
t.Assert(err, nil)
t.Assert(v.String(), "v")
conn := redis.Conn()
defer conn.Close()
_, err = conn.DoVar("SET", "k", "v")
conn, err := redis.Conn(ctx)
t.AssertNil(err)
defer conn.Close(ctx)
_, err = conn.Do(ctx, "SET", "k", "v")
t.Assert(err, nil)
_, err = conn.DoVar("Subscribe", "gf")
_, err = conn.Do(ctx, "Subscribe", "gf")
t.Assert(err, nil)
_, err = redis.DoVar("PUBLISH", "gf", "test")
_, err = redis.Do(ctx, "PUBLISH", "gf", "test")
t.Assert(err, nil)
v, _ = conn.ReceiveVar()
v, _ = conn.Receive(ctx)
t.Assert(len(v.Strings()), 3)
t.Assert(v.Strings()[2], "test")
@ -192,23 +219,27 @@ func Test_Error(t *testing.T) {
func Test_Bool(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis := gredis.New(config)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
defer func() {
redis.Do("DEL", "key-true")
redis.Do("DEL", "key-false")
redis.Do(ctx, "DEL", "key-true")
redis.Do(ctx, "DEL", "key-false")
}()
_, err := redis.Do("SET", "key-true", true)
_, err = redis.Do(ctx, "SET", "key-true", true)
t.Assert(err, nil)
_, err = redis.Do("SET", "key-false", false)
_, err = redis.Do(ctx, "SET", "key-false", false)
t.Assert(err, nil)
r, err := redis.DoVar("GET", "key-true")
r, err := redis.Do(ctx, "GET", "key-true")
t.Assert(err, nil)
t.Assert(r.Bool(), true)
r, err = redis.DoVar("GET", "key-false")
r, err = redis.Do(ctx, "GET", "key-false")
t.Assert(err, nil)
t.Assert(r.Bool(), false)
})
@ -216,14 +247,18 @@ func Test_Bool(t *testing.T) {
func Test_Int(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis := gredis.New(config)
key := guid.S()
defer redis.Do("DEL", key)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
_, err := redis.Do("SET", key, 1)
key := guid.S()
defer redis.Do(ctx, "DEL", key)
_, err = redis.Do(ctx, "SET", key, 1)
t.Assert(err, nil)
r, err := redis.DoVar("GET", key)
r, err := redis.Do(ctx, "GET", key)
t.Assert(err, nil)
t.Assert(r.Int(), 1)
})
@ -231,14 +266,18 @@ func Test_Int(t *testing.T) {
func Test_HSet(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
redis := gredis.New(config)
key := guid.S()
defer redis.Do("DEL", key)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
_, err := redis.Do("HSET", key, "name", "john")
key := guid.S()
defer redis.Do(ctx, "DEL", key)
_, err = redis.Do(ctx, "HSET", key, "name", "john")
t.Assert(err, nil)
r, err := redis.DoVar("HGETALL", key)
r, err := redis.Do(ctx, "HGETALL", key)
t.Assert(err, nil)
t.Assert(r.Strings(), g.ArrayStr{"name", "john"})
})
@ -247,18 +286,20 @@ func Test_HSet(t *testing.T) {
func Test_HGetAll1(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
key = guid.S()
redis = gredis.New(config)
key = guid.S()
)
defer redis.Do("DEL", key)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
defer redis.Do(ctx, "DEL", key)
_, err = redis.Do("HSET", key, "id", 100)
_, err = redis.Do(ctx, "HSET", key, "id", 100)
t.Assert(err, nil)
_, err = redis.Do("HSET", key, "name", "john")
_, err = redis.Do(ctx, "HSET", key, "name", "john")
t.Assert(err, nil)
r, err := redis.DoVar("HGETALL", key)
r, err := redis.Do(ctx, "HGETALL", key)
t.Assert(err, nil)
t.Assert(r.Map(), g.MapStrAny{
"id": 100,
@ -270,18 +311,20 @@ func Test_HGetAll1(t *testing.T) {
func Test_HGetAll2(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
key = guid.S()
redis = gredis.New(config)
key = guid.S()
)
defer redis.Do("DEL", key)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
defer redis.Do(ctx, "DEL", key)
_, err = redis.Do("HSET", key, "id", 100)
_, err = redis.Do(ctx, "HSET", key, "id", 100)
t.Assert(err, nil)
_, err = redis.Do("HSET", key, "name", "john")
_, err = redis.Do(ctx, "HSET", key, "name", "john")
t.Assert(err, nil)
result, err := redis.DoVar("HGETALL", key)
result, err := redis.Do(ctx, "HGETALL", key)
t.Assert(err, nil)
t.Assert(gconv.Uint(result.MapStrVar()["id"]), 100)
@ -293,20 +336,22 @@ func Test_HMSet(t *testing.T) {
// map
gtest.C(t, func(t *gtest.T) {
var (
err error
key = guid.S()
redis = gredis.New(config)
data = g.Map{
key = guid.S()
data = g.Map{
"name": "gf",
"sex": 0,
"score": 100,
}
)
defer redis.Do("DEL", key)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
defer redis.Do(ctx, "DEL", key)
_, err = redis.Do("HMSET", append(g.Slice{key}, gutil.MapToSlice(data)...)...)
_, err = redis.Do(ctx, "HMSET", append(g.Slice{key}, gutil.MapToSlice(data)...)...)
t.Assert(err, nil)
v, err := redis.DoVar("HMGET", key, "name")
v, err := redis.Do(ctx, "HMGET", key, "name")
t.Assert(err, nil)
t.Assert(v.Slice(), g.Slice{data["name"]})
})
@ -318,48 +363,53 @@ func Test_HMSet(t *testing.T) {
Score int `json:"score"`
}
var (
err error
key = guid.S()
redis = gredis.New(config)
data = &User{
key = guid.S()
data = &User{
Name: "gf",
Sex: 0,
Score: 100,
}
)
defer redis.Do("DEL", key)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
defer redis.Do(ctx, "DEL", key)
_, err = redis.Do("HMSET", append(g.Slice{key}, gutil.StructToSlice(data)...)...)
_, err = redis.Do(ctx, "HMSET", append(g.Slice{key}, gutil.StructToSlice(data)...)...)
t.Assert(err, nil)
v, err := redis.DoVar("HMGET", key, "name")
v, err := redis.Do(ctx, "HMGET", key, "name")
t.Assert(err, nil)
t.Assert(v.Slice(), g.Slice{data.Name})
})
}
func Test_Auto_Marshal(t *testing.T) {
var (
err error
redis = gredis.New(config)
key = guid.S()
)
defer redis.Do("DEL", key)
type User struct {
Id int
Name string
}
gtest.C(t, func(t *gtest.T) {
var (
key = guid.S()
)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Close(ctx)
defer redis.Do(ctx, "DEL", key)
type User struct {
Id int
Name string
}
user := &User{
Id: 10000,
Name: "john",
}
_, err = redis.Do("SET", key, user)
_, err = redis.Do(ctx, "SET", key, user)
t.Assert(err, nil)
r, err := redis.DoVar("GET", key)
r, err := redis.Do(ctx, "GET", key)
t.Assert(err, nil)
t.Assert(r.Map(), g.MapStrAny{
"Id": user.Id,
@ -374,22 +424,20 @@ func Test_Auto_Marshal(t *testing.T) {
}
func Test_Auto_MarshalSlice(t *testing.T) {
var (
err error
redis = gredis.New(config)
key = guid.S()
)
defer redis.Do("DEL", key)
type User struct {
Id int
Name string
}
gtest.C(t, func(t *gtest.T) {
var (
key = "user-slice"
)
redis, err := gredis.New(config)
t.AssertNil(err)
t.AssertNE(redis, nil)
defer redis.Do(ctx, "DEL", key)
type User struct {
Id int
Name string
}
var (
result *gvar.Var
key = "user-slice"
users1 = []User{
{
Id: 1,
@ -402,10 +450,10 @@ func Test_Auto_MarshalSlice(t *testing.T) {
}
)
_, err = redis.Do("SET", key, users1)
_, err = redis.Do(ctx, "SET", key, users1)
t.Assert(err, nil)
result, err = redis.DoVar("GET", key)
result, err = redis.Do(ctx, "GET", key)
t.Assert(err, nil)
var users2 []User

View File

@ -239,7 +239,7 @@ func (s *Session) Size() int {
// Contains checks whether key exist in the session.
func (s *Session) Contains(key string) bool {
s.init()
return s.Get(key) != nil
return !s.Get(key).IsNil()
}
// IsDirty checks whether there's any data changes in the session.

View File

@ -46,21 +46,24 @@ func (s *StorageRedisHashTable) New(ctx context.Context, ttl time.Duration) (id
// Get retrieves session value with given key.
// It returns nil if the key does not exist in the session.
func (s *StorageRedisHashTable) Get(ctx context.Context, id string, key string) (value interface{}, err error) {
value, err = s.redis.Do(ctx, "HGET", s.key(id), key)
if value != nil {
value = gconv.String(value)
v, err := s.redis.Do(ctx, "HGET", s.key(id), key)
if err != nil {
return nil, err
}
return
if v.IsNil() {
return nil, nil
}
return v.String(), nil
}
// GetMap retrieves all key-value pairs as map from storage.
func (s *StorageRedisHashTable) GetMap(ctx context.Context, id string) (data map[string]interface{}, err error) {
r, err := s.redis.Do(ctx, "HGETALL", s.key(id))
v, err := s.redis.Do(ctx, "HGETALL", s.key(id))
if err != nil {
return nil, err
}
data = make(map[string]interface{})
array := r.Interfaces()
array := v.Interfaces()
for i := 0; i < len(array); i += 2 {
if array[i+1] != nil {
data[gconv.String(array[i])] = gconv.String(array[i+1])

View File

@ -18,9 +18,10 @@ import (
)
func Test_StorageRedisHashTable(t *testing.T) {
redis, err := gredis.NewFromStr("127.0.0.1:6379,0")
config, _ := gredis.ConfigFromStr("127.0.0.1:6379,0")
redis, err := gredis.New(config)
gtest.C(t, func(t *gtest.T) {
t.Assert(err, nil)
t.AssertNil(err)
})
storage := gsession.NewStorageRedisHashTable(redis)
@ -80,7 +81,8 @@ func Test_StorageRedisHashTable(t *testing.T) {
}
func Test_StorageRedisHashTablePrefix(t *testing.T) {
redis, err := gredis.NewFromStr("127.0.0.1:6379,0")
config, _ := gredis.ConfigFromStr("127.0.0.1:6379,0")
redis, err := gredis.New(config)
gtest.C(t, func(t *gtest.T) {
t.Assert(err, nil)
})

View File

@ -18,7 +18,8 @@ import (
)
func Test_StorageRedis(t *testing.T) {
redis, err := gredis.NewFromStr("127.0.0.1:6379,0")
config, _ := gredis.ConfigFromStr("127.0.0.1:6379,0")
redis, err := gredis.New(config)
gtest.Assert(err, nil)
storage := gsession.NewStorageRedis(redis)
@ -79,7 +80,8 @@ func Test_StorageRedis(t *testing.T) {
}
func Test_StorageRedisPrefix(t *testing.T) {
redis, err := gredis.NewFromStr("127.0.0.1:6379,0")
config, _ := gredis.ConfigFromStr("127.0.0.1:6379,0")
redis, err := gredis.New(config)
gtest.Assert(err, nil)
prefix := "s_"