forked from mirror/redis
Improve deadlines support.
This commit is contained in:
parent
ce34e39219
commit
cc74e79eb7
|
@ -2,12 +2,20 @@ package redis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func formatFloat(f float64) string {
|
func formatFloat(f float64) string {
|
||||||
return strconv.FormatFloat(f, 'f', -1, 64)
|
return strconv.FormatFloat(f, 'f', -1, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readTimeout(sec int64) time.Duration {
|
||||||
|
if sec == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return time.Duration(sec+1) * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
func (c *Client) Auth(password string) *StatusReq {
|
func (c *Client) Auth(password string) *StatusReq {
|
||||||
|
@ -86,6 +94,7 @@ func (c *Client) Migrate(host, port, key string, db, timeout int64) *StatusReq {
|
||||||
strconv.FormatInt(db, 10),
|
strconv.FormatInt(db, 10),
|
||||||
strconv.FormatInt(timeout, 10),
|
strconv.FormatInt(timeout, 10),
|
||||||
)
|
)
|
||||||
|
req.setReadTimeout(readTimeout(timeout))
|
||||||
c.Process(req)
|
c.Process(req)
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
@ -493,6 +502,7 @@ func (c *Client) BLPop(timeout int64, keys ...string) *StringSliceReq {
|
||||||
args := append([]string{"BLPOP"}, keys...)
|
args := append([]string{"BLPOP"}, keys...)
|
||||||
args = append(args, strconv.FormatInt(timeout, 10))
|
args = append(args, strconv.FormatInt(timeout, 10))
|
||||||
req := NewStringSliceReq(args...)
|
req := NewStringSliceReq(args...)
|
||||||
|
req.setReadTimeout(readTimeout(timeout))
|
||||||
c.Process(req)
|
c.Process(req)
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
@ -501,6 +511,7 @@ func (c *Client) BRPop(timeout int64, keys ...string) *StringSliceReq {
|
||||||
args := append([]string{"BRPOP"}, keys...)
|
args := append([]string{"BRPOP"}, keys...)
|
||||||
args = append(args, strconv.FormatInt(timeout, 10))
|
args = append(args, strconv.FormatInt(timeout, 10))
|
||||||
req := NewStringSliceReq(args...)
|
req := NewStringSliceReq(args...)
|
||||||
|
req.setReadTimeout(readTimeout(timeout))
|
||||||
c.Process(req)
|
c.Process(req)
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
@ -512,6 +523,7 @@ func (c *Client) BRPopLPush(source, destination string, timeout int64) *StringRe
|
||||||
destination,
|
destination,
|
||||||
strconv.FormatInt(timeout, 10),
|
strconv.FormatInt(timeout, 10),
|
||||||
)
|
)
|
||||||
|
req.setReadTimeout(readTimeout(timeout))
|
||||||
c.Process(req)
|
c.Process(req)
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleTCPClient() {
|
func ExampleTCPClient() {
|
||||||
password := "" // no password set
|
client := redis.DialTCP(&redis.Options{
|
||||||
db := int64(-1) // use default DB
|
Addr: "localhost:6379",
|
||||||
client := redis.NewTCPClient("localhost:6379", password, db)
|
Password: "", // no password set
|
||||||
|
DB: 0, // use default DB
|
||||||
|
})
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
ping := client.Ping()
|
ping := client.Ping()
|
||||||
|
@ -19,7 +21,9 @@ func ExampleTCPClient() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleUnixClient() {
|
func ExampleUnixClient() {
|
||||||
client := redis.NewUnixClient("/tmp/redis.sock", "", -1)
|
client := redis.DialUnix(&redis.Options{
|
||||||
|
Addr: "/tmp/redis.sock",
|
||||||
|
})
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
ping := client.Ping()
|
ping := client.Ping()
|
||||||
|
@ -28,7 +32,9 @@ func ExampleUnixClient() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleSetGet() {
|
func ExampleSetGet() {
|
||||||
client := redis.NewTCPClient(":6379", "", -1)
|
client := redis.DialTCP(&redis.Options{
|
||||||
|
Addr: ":6379",
|
||||||
|
})
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
set := client.Set("foo", "bar")
|
set := client.Set("foo", "bar")
|
||||||
|
@ -42,7 +48,9 @@ func ExampleSetGet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExamplePipeline() {
|
func ExamplePipeline() {
|
||||||
client := redis.NewTCPClient(":6379", "", -1)
|
client := redis.DialTCP(&redis.Options{
|
||||||
|
Addr: ":6379",
|
||||||
|
})
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
var set *redis.StatusReq
|
var set *redis.StatusReq
|
||||||
|
@ -78,7 +86,9 @@ func transaction(multi *redis.MultiClient) ([]redis.Req, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleTransaction() {
|
func ExampleTransaction() {
|
||||||
client := redis.NewTCPClient(":6379", "", -1)
|
client := redis.DialTCP(&redis.Options{
|
||||||
|
Addr: ":6379",
|
||||||
|
})
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
client.Del("key")
|
client.Del("key")
|
||||||
|
@ -97,7 +107,9 @@ func ExampleTransaction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExamplePubSub() {
|
func ExamplePubSub() {
|
||||||
client := redis.NewTCPClient(":6379", "", -1)
|
client := redis.DialTCP(&redis.Options{
|
||||||
|
Addr: ":6379",
|
||||||
|
})
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
pubsub, err := client.PubSubClient()
|
pubsub, err := client.PubSubClient()
|
||||||
|
@ -126,7 +138,9 @@ func Get(client *redis.Client, key string) *redis.StringReq {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleCustomCommand() {
|
func ExampleCustomCommand() {
|
||||||
client := redis.NewTCPClient(":6379", "", -1)
|
client := redis.DialTCP(&redis.Options{
|
||||||
|
Addr: ":6379",
|
||||||
|
})
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
get := Get(client, "key_does_not_exist")
|
get := Get(client, "key_does_not_exist")
|
||||||
|
|
|
@ -14,10 +14,8 @@ func (c *Client) MultiClient() (*MultiClient, error) {
|
||||||
return &MultiClient{
|
return &MultiClient{
|
||||||
Client: &Client{
|
Client: &Client{
|
||||||
baseClient: &baseClient{
|
baseClient: &baseClient{
|
||||||
|
opt: c.opt,
|
||||||
connPool: newSingleConnPool(c.connPool, nil, true),
|
connPool: newSingleConnPool(c.connPool, nil, true),
|
||||||
|
|
||||||
password: c.password,
|
|
||||||
db: c.db,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
@ -8,11 +8,9 @@ func (c *Client) PipelineClient() (*PipelineClient, error) {
|
||||||
return &PipelineClient{
|
return &PipelineClient{
|
||||||
Client: &Client{
|
Client: &Client{
|
||||||
baseClient: &baseClient{
|
baseClient: &baseClient{
|
||||||
|
opt: c.opt,
|
||||||
connPool: c.connPool,
|
connPool: c.connPool,
|
||||||
|
|
||||||
password: c.password,
|
|
||||||
db: c.db,
|
|
||||||
|
|
||||||
reqs: make([]Req, 0),
|
reqs: make([]Req, 0),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
20
v2/pool.go
20
v2/pool.go
|
@ -28,12 +28,9 @@ type conn struct {
|
||||||
readTimeout, writeTimeout time.Duration
|
readTimeout, writeTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConn(netcn net.Conn, readTimeout, writeTimeout time.Duration) *conn {
|
func newConn(netcn net.Conn) *conn {
|
||||||
cn := &conn{
|
cn := &conn{
|
||||||
Cn: netcn,
|
Cn: netcn,
|
||||||
|
|
||||||
readTimeout: readTimeout,
|
|
||||||
writeTimeout: writeTimeout,
|
|
||||||
}
|
}
|
||||||
cn.Rd = bufio.NewReaderSize(cn, 1024)
|
cn.Rd = bufio.NewReaderSize(cn, 1024)
|
||||||
return cn
|
return cn
|
||||||
|
@ -42,6 +39,8 @@ func newConn(netcn net.Conn, readTimeout, writeTimeout time.Duration) *conn {
|
||||||
func (cn *conn) Read(b []byte) (int, error) {
|
func (cn *conn) Read(b []byte) (int, error) {
|
||||||
if cn.readTimeout != 0 {
|
if cn.readTimeout != 0 {
|
||||||
cn.Cn.SetReadDeadline(time.Now().Add(cn.readTimeout))
|
cn.Cn.SetReadDeadline(time.Now().Add(cn.readTimeout))
|
||||||
|
} else {
|
||||||
|
cn.Cn.SetReadDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
return cn.Cn.Read(b)
|
return cn.Cn.Read(b)
|
||||||
}
|
}
|
||||||
|
@ -49,6 +48,8 @@ func (cn *conn) Read(b []byte) (int, error) {
|
||||||
func (cn *conn) Write(b []byte) (int, error) {
|
func (cn *conn) Write(b []byte) (int, error) {
|
||||||
if cn.writeTimeout != 0 {
|
if cn.writeTimeout != 0 {
|
||||||
cn.Cn.SetWriteDeadline(time.Now().Add(cn.writeTimeout))
|
cn.Cn.SetWriteDeadline(time.Now().Add(cn.writeTimeout))
|
||||||
|
} else {
|
||||||
|
cn.Cn.SetReadDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
return cn.Cn.Write(b)
|
return cn.Cn.Write(b)
|
||||||
}
|
}
|
||||||
|
@ -70,7 +71,7 @@ type connPool struct {
|
||||||
func newConnPool(
|
func newConnPool(
|
||||||
dial func() (net.Conn, error),
|
dial func() (net.Conn, error),
|
||||||
maxSize int,
|
maxSize int,
|
||||||
readTimeout, writeTimeout, idleTimeout time.Duration,
|
idleTimeout time.Duration,
|
||||||
) *connPool {
|
) *connPool {
|
||||||
return &connPool{
|
return &connPool{
|
||||||
dial: dial,
|
dial: dial,
|
||||||
|
@ -78,11 +79,8 @@ func newConnPool(
|
||||||
cond: sync.NewCond(&sync.Mutex{}),
|
cond: sync.NewCond(&sync.Mutex{}),
|
||||||
conns: list.New(),
|
conns: list.New(),
|
||||||
|
|
||||||
maxSize: maxSize,
|
maxSize: maxSize,
|
||||||
|
idleTimeout: idleTimeout,
|
||||||
readTimeout: readTimeout,
|
|
||||||
writeTimeout: writeTimeout,
|
|
||||||
idleTimeout: idleTimeout,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +108,7 @@ func (p *connPool) Get() (*conn, bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
p.size++
|
p.size++
|
||||||
return newConn(rw, p.readTimeout, p.writeTimeout), true, nil
|
return newConn(rw), true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
elem := p.conns.Front()
|
elem := p.conns.Front()
|
||||||
|
|
|
@ -15,10 +15,8 @@ type PubSubClient struct {
|
||||||
func (c *Client) PubSubClient() (*PubSubClient, error) {
|
func (c *Client) PubSubClient() (*PubSubClient, error) {
|
||||||
return &PubSubClient{
|
return &PubSubClient{
|
||||||
baseClient: &baseClient{
|
baseClient: &baseClient{
|
||||||
|
opt: c.opt,
|
||||||
connPool: newSingleConnPool(c.connPool, nil, false),
|
connPool: newSingleConnPool(c.connPool, nil, false),
|
||||||
|
|
||||||
password: c.password,
|
|
||||||
db: c.db,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
ch: make(chan *Message),
|
ch: make(chan *Message),
|
||||||
|
|
25
v2/redis.go
25
v2/redis.go
|
@ -17,8 +17,7 @@ var Logger = log.New(os.Stdout, "redis: ", log.Ldate|log.Ltime)
|
||||||
type baseClient struct {
|
type baseClient struct {
|
||||||
connPool pool
|
connPool pool
|
||||||
|
|
||||||
password string
|
opt *Options
|
||||||
db int64
|
|
||||||
|
|
||||||
reqs []Req
|
reqs []Req
|
||||||
reqsMtx sync.Mutex
|
reqsMtx sync.Mutex
|
||||||
|
@ -40,8 +39,8 @@ func (c *baseClient) conn() (*conn, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isNew && (c.password != "" || c.db > 0) {
|
if isNew && (c.opt.Password != "" || c.opt.DB > 0) {
|
||||||
if err = c.init(cn, c.password, c.db); err != nil {
|
if err = c.init(cn, c.opt.Password, c.opt.DB); err != nil {
|
||||||
c.removeConn(cn)
|
c.removeConn(cn)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -102,8 +101,17 @@ func (c *baseClient) run(req Req) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.writeReq(cn, req)
|
cn.writeTimeout = c.opt.WriteTimeout
|
||||||
if err != nil {
|
if timeout := req.writeTimeout(); timeout != nil {
|
||||||
|
cn.writeTimeout = *timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
cn.readTimeout = c.opt.ReadTimeout
|
||||||
|
if timeout := req.readTimeout(); timeout != nil {
|
||||||
|
cn.readTimeout = *timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.writeReq(cn, req); err != nil {
|
||||||
c.removeConn(cn)
|
c.removeConn(cn)
|
||||||
req.SetErr(err)
|
req.SetErr(err)
|
||||||
return
|
return
|
||||||
|
@ -173,12 +181,11 @@ type Client struct {
|
||||||
func newClient(opt *Options, dial func() (net.Conn, error)) *Client {
|
func newClient(opt *Options, dial func() (net.Conn, error)) *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
baseClient: &baseClient{
|
baseClient: &baseClient{
|
||||||
password: opt.Password,
|
opt: opt,
|
||||||
db: opt.DB,
|
|
||||||
|
|
||||||
connPool: newConnPool(
|
connPool: newConnPool(
|
||||||
dial, opt.getPoolSize(),
|
dial, opt.getPoolSize(),
|
||||||
opt.ReadTimeout, opt.WriteTimeout, opt.IdleTimeout,
|
opt.IdleTimeout,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
260
v2/redis_test.go
260
v2/redis_test.go
|
@ -34,7 +34,9 @@ type RedisShutdownTest struct {
|
||||||
var _ = Suite(&RedisShutdownTest{})
|
var _ = Suite(&RedisShutdownTest{})
|
||||||
|
|
||||||
func (t *RedisShutdownTest) SetUpTest(c *C) {
|
func (t *RedisShutdownTest) SetUpTest(c *C) {
|
||||||
t.client = redis.NewTCPClient(redisAddr, "", -1)
|
t.client = redis.DialTCP(&redis.Options{
|
||||||
|
Addr: redisAddr,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *RedisShutdownTest) TestShutdown(c *C) {
|
func (t *RedisShutdownTest) TestShutdown(c *C) {
|
||||||
|
@ -56,14 +58,18 @@ type RedisConnectorTest struct{}
|
||||||
var _ = Suite(&RedisConnectorTest{})
|
var _ = Suite(&RedisConnectorTest{})
|
||||||
|
|
||||||
func (t *RedisConnectorTest) TestTCPConnector(c *C) {
|
func (t *RedisConnectorTest) TestTCPConnector(c *C) {
|
||||||
client := redis.NewTCPClient(":6379", "", -1)
|
client := redis.DialTCP(&redis.Options{
|
||||||
|
Addr: ":6379",
|
||||||
|
})
|
||||||
ping := client.Ping()
|
ping := client.Ping()
|
||||||
c.Check(ping.Err(), IsNil)
|
c.Check(ping.Err(), IsNil)
|
||||||
c.Check(ping.Val(), Equals, "PONG")
|
c.Check(ping.Val(), Equals, "PONG")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *RedisConnectorTest) TestUnixConnector(c *C) {
|
func (t *RedisConnectorTest) TestUnixConnector(c *C) {
|
||||||
client := redis.NewUnixClient("/tmp/redis.sock", "", -1)
|
client := redis.DialUnix(&redis.Options{
|
||||||
|
Addr: "/tmp/redis.sock",
|
||||||
|
})
|
||||||
ping := client.Ping()
|
ping := client.Ping()
|
||||||
c.Check(ping.Err(), IsNil)
|
c.Check(ping.Err(), IsNil)
|
||||||
c.Check(ping.Val(), Equals, "PONG")
|
c.Check(ping.Val(), Equals, "PONG")
|
||||||
|
@ -71,147 +77,147 @@ func (t *RedisConnectorTest) TestUnixConnector(c *C) {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
type RedisConnPoolTest struct {
|
// type RedisConnPoolTest struct {
|
||||||
dialedConns, closedConns int64
|
// dialedConns, closedConns int64
|
||||||
|
|
||||||
client *redis.Client
|
// client *redis.Client
|
||||||
}
|
// }
|
||||||
|
|
||||||
var _ = Suite(&RedisConnPoolTest{})
|
// var _ = Suite(&RedisConnPoolTest{})
|
||||||
|
|
||||||
func (t *RedisConnPoolTest) SetUpTest(c *C) {
|
// func (t *RedisConnPoolTest) SetUpTest(c *C) {
|
||||||
if t.client == nil {
|
// if t.client == nil {
|
||||||
dial := func() (net.Conn, error) {
|
// dial := func() (net.Conn, error) {
|
||||||
t.dialedConns++
|
// t.dialedConns++
|
||||||
return net.Dial("tcp", redisAddr)
|
// return net.Dial("tcp", redisAddr)
|
||||||
}
|
// }
|
||||||
close := func(conn net.Conn) error {
|
// close := func(conn net.Conn) error {
|
||||||
t.closedConns++
|
// t.closedConns++
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
t.client = (&redis.ClientFactory{
|
// t.client = (&redis.ClientFactory{
|
||||||
Dial: dial,
|
// Dial: dial,
|
||||||
Close: close,
|
// Close: close,
|
||||||
}).New()
|
// }).New()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (t *RedisConnPoolTest) TearDownTest(c *C) {
|
// func (t *RedisConnPoolTest) TearDownTest(c *C) {
|
||||||
t.resetRedis(c)
|
// t.resetRedis(c)
|
||||||
t.resetClient(c)
|
// t.resetClient(c)
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (t *RedisConnPoolTest) resetRedis(c *C) {
|
// func (t *RedisConnPoolTest) resetRedis(c *C) {
|
||||||
// This is much faster than Flushall.
|
// // This is much faster than Flushall.
|
||||||
c.Assert(t.client.Select(1).Err(), IsNil)
|
// c.Assert(t.client.Select(1).Err(), IsNil)
|
||||||
c.Assert(t.client.FlushDb().Err(), IsNil)
|
// c.Assert(t.client.FlushDb().Err(), IsNil)
|
||||||
c.Assert(t.client.Select(0).Err(), IsNil)
|
// c.Assert(t.client.Select(0).Err(), IsNil)
|
||||||
c.Assert(t.client.FlushDb().Err(), IsNil)
|
// c.Assert(t.client.FlushDb().Err(), IsNil)
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (t *RedisConnPoolTest) resetClient(c *C) {
|
// func (t *RedisConnPoolTest) resetClient(c *C) {
|
||||||
t.client.Close()
|
// t.client.Close()
|
||||||
c.Check(t.closedConns, Equals, t.dialedConns)
|
// c.Check(t.closedConns, Equals, t.dialedConns)
|
||||||
t.dialedConns, t.closedConns = 0, 0
|
// t.dialedConns, t.closedConns = 0, 0
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (t *RedisConnPoolTest) TestConnPoolMaxSize(c *C) {
|
// func (t *RedisConnPoolTest) TestConnPoolMaxSize(c *C) {
|
||||||
wg := &sync.WaitGroup{}
|
// wg := &sync.WaitGroup{}
|
||||||
for i := 0; i < 1000; i++ {
|
// for i := 0; i < 1000; i++ {
|
||||||
wg.Add(1)
|
// wg.Add(1)
|
||||||
go func() {
|
// go func() {
|
||||||
ping := t.client.Ping()
|
// ping := t.client.Ping()
|
||||||
c.Assert(ping.Err(), IsNil)
|
// c.Assert(ping.Err(), IsNil)
|
||||||
c.Assert(ping.Val(), Equals, "PONG")
|
// c.Assert(ping.Val(), Equals, "PONG")
|
||||||
wg.Done()
|
// wg.Done()
|
||||||
}()
|
// }()
|
||||||
}
|
// }
|
||||||
wg.Wait()
|
// wg.Wait()
|
||||||
|
|
||||||
c.Assert(t.client.Close(), IsNil)
|
// c.Assert(t.client.Close(), IsNil)
|
||||||
c.Assert(t.dialedConns, Equals, int64(10))
|
// c.Assert(t.dialedConns, Equals, int64(10))
|
||||||
c.Assert(t.closedConns, Equals, int64(10))
|
// c.Assert(t.closedConns, Equals, int64(10))
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (t *RedisConnPoolTest) TestConnPoolMaxSizeOnPipelineClient(c *C) {
|
// func (t *RedisConnPoolTest) TestConnPoolMaxSizeOnPipelineClient(c *C) {
|
||||||
wg := &sync.WaitGroup{}
|
// wg := &sync.WaitGroup{}
|
||||||
for i := 0; i < 1000; i++ {
|
// for i := 0; i < 1000; i++ {
|
||||||
wg.Add(1)
|
// wg.Add(1)
|
||||||
go func() {
|
// go func() {
|
||||||
pipeline, err := t.client.PipelineClient()
|
// pipeline, err := t.client.PipelineClient()
|
||||||
c.Assert(err, IsNil)
|
// c.Assert(err, IsNil)
|
||||||
|
|
||||||
ping := pipeline.Ping()
|
// ping := pipeline.Ping()
|
||||||
reqs, err := pipeline.RunQueued()
|
// reqs, err := pipeline.RunQueued()
|
||||||
c.Assert(err, IsNil)
|
// c.Assert(err, IsNil)
|
||||||
c.Assert(reqs, HasLen, 1)
|
// c.Assert(reqs, HasLen, 1)
|
||||||
c.Assert(ping.Err(), IsNil)
|
// c.Assert(ping.Err(), IsNil)
|
||||||
c.Assert(ping.Val(), Equals, "PONG")
|
// c.Assert(ping.Val(), Equals, "PONG")
|
||||||
|
|
||||||
c.Assert(pipeline.Close(), IsNil)
|
// c.Assert(pipeline.Close(), IsNil)
|
||||||
|
|
||||||
wg.Done()
|
// wg.Done()
|
||||||
}()
|
// }()
|
||||||
}
|
// }
|
||||||
wg.Wait()
|
// wg.Wait()
|
||||||
|
|
||||||
c.Assert(t.client.Close(), IsNil)
|
// c.Assert(t.client.Close(), IsNil)
|
||||||
c.Assert(t.dialedConns, Equals, int64(10))
|
// c.Assert(t.dialedConns, Equals, int64(10))
|
||||||
c.Assert(t.closedConns, Equals, int64(10))
|
// c.Assert(t.closedConns, Equals, int64(10))
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (t *RedisConnPoolTest) TestConnPoolMaxSizeOnMultiClient(c *C) {
|
// func (t *RedisConnPoolTest) TestConnPoolMaxSizeOnMultiClient(c *C) {
|
||||||
wg := &sync.WaitGroup{}
|
// wg := &sync.WaitGroup{}
|
||||||
for i := 0; i < 1000; i++ {
|
// for i := 0; i < 1000; i++ {
|
||||||
wg.Add(1)
|
// wg.Add(1)
|
||||||
go func() {
|
// go func() {
|
||||||
multi, err := t.client.MultiClient()
|
// multi, err := t.client.MultiClient()
|
||||||
c.Assert(err, IsNil)
|
// c.Assert(err, IsNil)
|
||||||
|
|
||||||
var ping *redis.StatusReq
|
// var ping *redis.StatusReq
|
||||||
reqs, err := multi.Exec(func() {
|
// reqs, err := multi.Exec(func() {
|
||||||
ping = multi.Ping()
|
// ping = multi.Ping()
|
||||||
})
|
// })
|
||||||
c.Assert(err, IsNil)
|
// c.Assert(err, IsNil)
|
||||||
c.Assert(reqs, HasLen, 1)
|
// c.Assert(reqs, HasLen, 1)
|
||||||
c.Assert(ping.Err(), IsNil)
|
// c.Assert(ping.Err(), IsNil)
|
||||||
c.Assert(ping.Val(), Equals, "PONG")
|
// c.Assert(ping.Val(), Equals, "PONG")
|
||||||
|
|
||||||
c.Assert(multi.Close(), IsNil)
|
// c.Assert(multi.Close(), IsNil)
|
||||||
|
|
||||||
wg.Done()
|
// wg.Done()
|
||||||
}()
|
// }()
|
||||||
}
|
// }
|
||||||
wg.Wait()
|
// wg.Wait()
|
||||||
|
|
||||||
c.Assert(t.client.Close(), IsNil)
|
// c.Assert(t.client.Close(), IsNil)
|
||||||
c.Assert(t.dialedConns, Equals, int64(10))
|
// c.Assert(t.dialedConns, Equals, int64(10))
|
||||||
c.Assert(t.closedConns, Equals, int64(10))
|
// c.Assert(t.closedConns, Equals, int64(10))
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (t *RedisConnPoolTest) TestConnPoolMaxSizeOnPubSubClient(c *C) {
|
// func (t *RedisConnPoolTest) TestConnPoolMaxSizeOnPubSubClient(c *C) {
|
||||||
wg := &sync.WaitGroup{}
|
// wg := &sync.WaitGroup{}
|
||||||
for i := 0; i < 1000; i++ {
|
// for i := 0; i < 1000; i++ {
|
||||||
wg.Add(1)
|
// wg.Add(1)
|
||||||
go func() {
|
// go func() {
|
||||||
pubsub, err := t.client.PubSubClient()
|
// pubsub, err := t.client.PubSubClient()
|
||||||
c.Assert(err, IsNil)
|
// c.Assert(err, IsNil)
|
||||||
|
|
||||||
_, err = pubsub.Subscribe()
|
// _, err = pubsub.Subscribe()
|
||||||
c.Assert(err, IsNil)
|
// c.Assert(err, IsNil)
|
||||||
|
|
||||||
c.Assert(pubsub.Close(), IsNil)
|
// c.Assert(pubsub.Close(), IsNil)
|
||||||
|
|
||||||
wg.Done()
|
// wg.Done()
|
||||||
}()
|
// }()
|
||||||
}
|
// }
|
||||||
wg.Wait()
|
// wg.Wait()
|
||||||
|
|
||||||
c.Assert(t.client.Close(), IsNil)
|
// c.Assert(t.client.Close(), IsNil)
|
||||||
c.Assert(t.dialedConns, Equals, int64(1000))
|
// c.Assert(t.dialedConns, Equals, int64(1000))
|
||||||
c.Assert(t.closedConns, Equals, int64(1000))
|
// c.Assert(t.closedConns, Equals, int64(1000))
|
||||||
}
|
// }
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -225,7 +231,9 @@ func Test(t *testing.T) { TestingT(t) }
|
||||||
|
|
||||||
func (t *RedisTest) SetUpTest(c *C) {
|
func (t *RedisTest) SetUpTest(c *C) {
|
||||||
if t.client == nil {
|
if t.client == nil {
|
||||||
t.client = redis.NewTCPClient(":6379", "", -1)
|
t.client = redis.DialTCP(&redis.Options{
|
||||||
|
Addr: ":6379",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +337,9 @@ func (t *RedisTest) TestConnPoolRemovesBrokenConn(c *C) {
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(conn.Close(), IsNil)
|
c.Assert(conn.Close(), IsNil)
|
||||||
|
|
||||||
client := redis.NewTCPClient(redisAddr, "", -1)
|
client := redis.DialTCP(&redis.Options{
|
||||||
|
Addr: redisAddr,
|
||||||
|
})
|
||||||
defer func() {
|
defer func() {
|
||||||
c.Assert(client.Close(), IsNil)
|
c.Assert(client.Close(), IsNil)
|
||||||
}()
|
}()
|
||||||
|
@ -1304,9 +1314,9 @@ func (t *RedisTest) TestCmdListsBRPopBlocks(c *C) {
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
started <- true
|
started <- true
|
||||||
bRPop := t.client.BRPop(0, "list")
|
brpop := t.client.BRPop(0, "list")
|
||||||
c.Assert(bRPop.Err(), IsNil)
|
c.Assert(brpop.Err(), IsNil)
|
||||||
c.Assert(bRPop.Val(), DeepEquals, []string{"list", "a"})
|
c.Assert(brpop.Val(), DeepEquals, []string{"list", "a"})
|
||||||
done <- true
|
done <- true
|
||||||
}()
|
}()
|
||||||
<-started
|
<-started
|
||||||
|
|
22
v2/req.go
22
v2/req.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Req interface {
|
type Req interface {
|
||||||
|
@ -13,6 +14,9 @@ type Req interface {
|
||||||
Err() error
|
Err() error
|
||||||
SetVal(interface{})
|
SetVal(interface{})
|
||||||
IfaceVal() interface{}
|
IfaceVal() interface{}
|
||||||
|
|
||||||
|
writeTimeout() *time.Duration
|
||||||
|
readTimeout() *time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -22,6 +26,8 @@ type baseReq struct {
|
||||||
|
|
||||||
val interface{}
|
val interface{}
|
||||||
err error
|
err error
|
||||||
|
|
||||||
|
_writeTimeout, _readTimeout *time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBaseReq(args ...string) *baseReq {
|
func newBaseReq(args ...string) *baseReq {
|
||||||
|
@ -76,6 +82,22 @@ func (r *baseReq) String() string {
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *baseReq) readTimeout() *time.Duration {
|
||||||
|
return r._readTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *baseReq) setReadTimeout(d time.Duration) {
|
||||||
|
r._readTimeout = &d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *baseReq) writeTimeout() *time.Duration {
|
||||||
|
return r._writeTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *baseReq) setWriteTimeout(d time.Duration) {
|
||||||
|
r._writeTimeout = &d
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
type IfaceReq struct {
|
type IfaceReq struct {
|
||||||
|
|
Loading…
Reference in New Issue