mirror of https://github.com/go-redis/redis.git
Improve ReceiveMessage.
This commit is contained in:
parent
5efe0cceb6
commit
42141f11d1
3
multi.go
3
multi.go
|
@ -49,7 +49,8 @@ func (c *Client) Multi() *Multi {
|
||||||
func (c *Multi) putConn(cn *conn, ei error) {
|
func (c *Multi) putConn(cn *conn, ei error) {
|
||||||
var err error
|
var err error
|
||||||
if isBadConn(cn, ei) {
|
if isBadConn(cn, ei) {
|
||||||
err = c.base.connPool.Remove(nil) // nil to force removal
|
// Close current connection.
|
||||||
|
c.base.connPool.(*stickyConnPool).Reset()
|
||||||
} else {
|
} else {
|
||||||
err = c.base.connPool.Put(cn)
|
err = c.base.connPool.Put(cn)
|
||||||
}
|
}
|
||||||
|
|
15
pool.go
15
pool.go
|
@ -137,7 +137,7 @@ func newConnPool(opt *Options) *connPool {
|
||||||
p := &connPool{
|
p := &connPool{
|
||||||
dialer: newConnDialer(opt),
|
dialer: newConnDialer(opt),
|
||||||
|
|
||||||
rl: ratelimit.New(2*opt.getPoolSize(), time.Second),
|
rl: ratelimit.New(3*opt.getPoolSize(), time.Second),
|
||||||
opt: opt,
|
opt: opt,
|
||||||
conns: newConnList(opt.getPoolSize()),
|
conns: newConnList(opt.getPoolSize()),
|
||||||
freeConns: make(chan *conn, opt.getPoolSize()),
|
freeConns: make(chan *conn, opt.getPoolSize()),
|
||||||
|
@ -458,12 +458,8 @@ func (p *stickyConnPool) Remove(cn *conn) error {
|
||||||
if cn != nil && p.cn != cn {
|
if cn != nil && p.cn != cn {
|
||||||
panic("p.cn != cn")
|
panic("p.cn != cn")
|
||||||
}
|
}
|
||||||
if cn == nil {
|
|
||||||
return p.remove()
|
|
||||||
} else {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (p *stickyConnPool) Len() int {
|
func (p *stickyConnPool) Len() int {
|
||||||
defer p.mx.Unlock()
|
defer p.mx.Unlock()
|
||||||
|
@ -483,6 +479,15 @@ func (p *stickyConnPool) FreeLen() int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *stickyConnPool) Reset() (err error) {
|
||||||
|
p.mx.Lock()
|
||||||
|
if p.cn != nil {
|
||||||
|
err = p.remove()
|
||||||
|
}
|
||||||
|
p.mx.Unlock()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (p *stickyConnPool) Close() error {
|
func (p *stickyConnPool) Close() error {
|
||||||
defer p.mx.Unlock()
|
defer p.mx.Unlock()
|
||||||
p.mx.Lock()
|
p.mx.Lock()
|
||||||
|
|
50
pubsub.go
50
pubsub.go
|
@ -235,7 +235,7 @@ func (c *PubSub) Receive() (interface{}, error) {
|
||||||
|
|
||||||
func (c *PubSub) reconnect() {
|
func (c *PubSub) reconnect() {
|
||||||
// Close current connection.
|
// Close current connection.
|
||||||
c.connPool.Remove(nil) // nil to force removal
|
c.connPool.(*stickyConnPool).Reset()
|
||||||
|
|
||||||
if len(c.channels) > 0 {
|
if len(c.channels) > 0 {
|
||||||
if err := c.Subscribe(c.channels...); err != nil {
|
if err := c.Subscribe(c.channels...); err != nil {
|
||||||
|
@ -252,39 +252,41 @@ func (c *PubSub) reconnect() {
|
||||||
// ReceiveMessage returns a message or error. It automatically
|
// ReceiveMessage returns a message or error. It automatically
|
||||||
// reconnects to Redis in case of network errors.
|
// reconnects to Redis in case of network errors.
|
||||||
func (c *PubSub) ReceiveMessage() (*Message, error) {
|
func (c *PubSub) ReceiveMessage() (*Message, error) {
|
||||||
var badConn bool
|
var errNum int
|
||||||
for {
|
for {
|
||||||
msgi, err := c.ReceiveTimeout(5 * time.Second)
|
msgi, err := c.ReceiveTimeout(5 * time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
if !isNetworkError(err) {
|
||||||
if badConn {
|
|
||||||
c.reconnect()
|
|
||||||
badConn = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err := c.Ping("")
|
|
||||||
if err != nil {
|
|
||||||
c.reconnect()
|
|
||||||
} else {
|
|
||||||
badConn = true
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if isNetworkError(err) {
|
|
||||||
c.reconnect()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goodConn := errNum == 0
|
||||||
|
errNum++
|
||||||
|
|
||||||
|
if goodConn {
|
||||||
|
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||||
|
err := c.Ping("")
|
||||||
|
if err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Printf("redis: PubSub.Ping failed: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errNum > 2 {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
c.reconnect()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset error number.
|
||||||
|
errNum = 0
|
||||||
|
|
||||||
switch msg := msgi.(type) {
|
switch msg := msgi.(type) {
|
||||||
case *Subscription:
|
case *Subscription:
|
||||||
// Ignore.
|
// Ignore.
|
||||||
case *Pong:
|
case *Pong:
|
||||||
badConn = false
|
|
||||||
// Ignore.
|
// Ignore.
|
||||||
case *Message:
|
case *Message:
|
||||||
return msg, nil
|
return msg, nil
|
||||||
|
|
|
@ -260,9 +260,9 @@ var _ = Describe("PubSub", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
defer pubsub.Close()
|
defer pubsub.Close()
|
||||||
|
|
||||||
cn, _, err := pubsub.Pool().Get()
|
cn1, _, err := pubsub.Pool().Get()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
cn.SetNetConn(&badConn{
|
cn1.SetNetConn(&badConn{
|
||||||
readErr: errTimeout,
|
readErr: errTimeout,
|
||||||
writeErr: errTimeout,
|
writeErr: errTimeout,
|
||||||
})
|
})
|
||||||
|
@ -286,7 +286,7 @@ var _ = Describe("PubSub", func() {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should not panic on Close", func() {
|
It("should return on Close", func() {
|
||||||
pubsub, err := client.Subscribe("mychannel")
|
pubsub, err := client.Subscribe("mychannel")
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
defer pubsub.Close()
|
defer pubsub.Close()
|
||||||
|
@ -297,13 +297,20 @@ var _ = Describe("PubSub", func() {
|
||||||
defer GinkgoRecover()
|
defer GinkgoRecover()
|
||||||
|
|
||||||
wg.Done()
|
wg.Done()
|
||||||
|
|
||||||
_, err := pubsub.ReceiveMessage()
|
_, err := pubsub.ReceiveMessage()
|
||||||
Expect(err).To(MatchError("redis: client is closed"))
|
Expect(err).To(MatchError("redis: client is closed"))
|
||||||
|
|
||||||
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
err = pubsub.Close()
|
err = pubsub.Close()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue