mirror of
https://github.com/redis/go-redis.git
synced 2025-07-29 17:41:15 +03:00
Enable reaper on ClusterClient and add tests.
This commit is contained in:
@ -1,10 +1,18 @@
|
||||
package hashtag
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestGinkgoSuite(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "hashtag")
|
||||
}
|
||||
|
||||
var _ = Describe("CRC16", func() {
|
||||
|
||||
// http://redis.io/topics/cluster-spec#keys-distribution-model
|
||||
@ -23,3 +31,44 @@ var _ = Describe("CRC16", func() {
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
var _ = Describe("HashSlot", func() {
|
||||
|
||||
It("should calculate hash slots", func() {
|
||||
tests := []struct {
|
||||
key string
|
||||
slot int
|
||||
}{
|
||||
{"123456789", 12739},
|
||||
{"{}foo", 9500},
|
||||
{"foo{}", 5542},
|
||||
{"foo{}{bar}", 8363},
|
||||
{"", 10503},
|
||||
{"", 5176},
|
||||
{string([]byte{83, 153, 134, 118, 229, 214, 244, 75, 140, 37, 215, 215}), 5463},
|
||||
}
|
||||
// Empty keys receive random slot.
|
||||
rand.Seed(100)
|
||||
|
||||
for _, test := range tests {
|
||||
Expect(Slot(test.key)).To(Equal(test.slot), "for %s", test.key)
|
||||
}
|
||||
})
|
||||
|
||||
It("should extract keys from tags", func() {
|
||||
tests := []struct {
|
||||
one, two string
|
||||
}{
|
||||
{"foo{bar}", "bar"},
|
||||
{"{foo}bar", "foo"},
|
||||
{"{user1000}.following", "{user1000}.followers"},
|
||||
{"foo{{bar}}zap", "{bar"},
|
||||
{"foo{bar}{zap}", "bar"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
Expect(Slot(test.one)).To(Equal(Slot(test.two)), "for %s <-> %s", test.one, test.two)
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -25,8 +25,8 @@ var timers = sync.Pool{
|
||||
},
|
||||
}
|
||||
|
||||
// PoolStats contains pool state information and accumulated stats.
|
||||
type PoolStats struct {
|
||||
// Stats contains pool state information and accumulated stats.
|
||||
type Stats struct {
|
||||
Requests uint32 // number of times a connection was requested by the pool
|
||||
Hits uint32 // number of times free connection was found in the pool
|
||||
Timeouts uint32 // number of times a wait timeout occurred
|
||||
@ -41,7 +41,7 @@ type Pooler interface {
|
||||
Remove(*Conn, error) error
|
||||
Len() int
|
||||
FreeLen() int
|
||||
Stats() *PoolStats
|
||||
Stats() *Stats
|
||||
Close() error
|
||||
Closed() bool
|
||||
}
|
||||
@ -64,7 +64,7 @@ type ConnPool struct {
|
||||
freeConnsMu sync.Mutex
|
||||
freeConns []*Conn
|
||||
|
||||
stats PoolStats
|
||||
stats Stats
|
||||
|
||||
_closed int32 // atomic
|
||||
lastErr atomic.Value
|
||||
@ -173,16 +173,22 @@ func (p *ConnPool) Get() (*Conn, bool, error) {
|
||||
return nil, false, ErrPoolTimeout
|
||||
}
|
||||
|
||||
p.freeConnsMu.Lock()
|
||||
cn := p.popFree()
|
||||
p.freeConnsMu.Unlock()
|
||||
for {
|
||||
p.freeConnsMu.Lock()
|
||||
cn := p.popFree()
|
||||
p.freeConnsMu.Unlock()
|
||||
|
||||
if cn != nil {
|
||||
atomic.AddUint32(&p.stats.Hits, 1)
|
||||
if !cn.IsStale(p.idleTimeout) {
|
||||
return cn, false, nil
|
||||
if cn == nil {
|
||||
break
|
||||
}
|
||||
_ = p.closeConn(cn, errConnStale)
|
||||
|
||||
if cn.IsStale(p.idleTimeout) {
|
||||
p.remove(cn, errConnStale)
|
||||
continue
|
||||
}
|
||||
|
||||
atomic.AddUint32(&p.stats.Hits, 1)
|
||||
return cn, false, nil
|
||||
}
|
||||
|
||||
newcn, err := p.NewConn()
|
||||
@ -192,9 +198,6 @@ func (p *ConnPool) Get() (*Conn, bool, error) {
|
||||
}
|
||||
|
||||
p.connsMu.Lock()
|
||||
if cn != nil {
|
||||
p.removeConn(cn)
|
||||
}
|
||||
p.conns = append(p.conns, newcn)
|
||||
p.connsMu.Unlock()
|
||||
|
||||
@ -224,17 +227,13 @@ func (p *ConnPool) remove(cn *Conn, reason error) {
|
||||
_ = p.closeConn(cn, reason)
|
||||
|
||||
p.connsMu.Lock()
|
||||
p.removeConn(cn)
|
||||
p.connsMu.Unlock()
|
||||
}
|
||||
|
||||
func (p *ConnPool) removeConn(cn *Conn) {
|
||||
for i, c := range p.conns {
|
||||
if c == cn {
|
||||
p.conns = append(p.conns[:i], p.conns[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
p.connsMu.Unlock()
|
||||
}
|
||||
|
||||
// Len returns total number of connections.
|
||||
@ -253,14 +252,14 @@ func (p *ConnPool) FreeLen() int {
|
||||
return l
|
||||
}
|
||||
|
||||
func (p *ConnPool) Stats() *PoolStats {
|
||||
stats := PoolStats{}
|
||||
stats.Requests = atomic.LoadUint32(&p.stats.Requests)
|
||||
stats.Hits = atomic.LoadUint32(&p.stats.Hits)
|
||||
stats.Timeouts = atomic.LoadUint32(&p.stats.Timeouts)
|
||||
stats.TotalConns = uint32(p.Len())
|
||||
stats.FreeConns = uint32(p.FreeLen())
|
||||
return &stats
|
||||
func (p *ConnPool) Stats() *Stats {
|
||||
return &Stats{
|
||||
Requests: atomic.LoadUint32(&p.stats.Requests),
|
||||
Hits: atomic.LoadUint32(&p.stats.Hits),
|
||||
Timeouts: atomic.LoadUint32(&p.stats.Timeouts),
|
||||
TotalConns: uint32(p.Len()),
|
||||
FreeConns: uint32(p.FreeLen()),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ConnPool) Closed() bool {
|
||||
|
@ -42,7 +42,7 @@ func (p *SingleConnPool) FreeLen() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *SingleConnPool) Stats() *PoolStats {
|
||||
func (p *SingleConnPool) Stats() *Stats {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,9 @@ func (p *StickyConnPool) FreeLen() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *StickyConnPool) Stats() *PoolStats { return nil }
|
||||
func (p *StickyConnPool) Stats() *Stats {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *StickyConnPool) Close() error {
|
||||
defer p.mx.Unlock()
|
||||
|
Reference in New Issue
Block a user