diff --git a/conn.go b/conn.go index 6aedf00..dc38aa5 100644 --- a/conn.go +++ b/conn.go @@ -11,19 +11,11 @@ type PoolConn struct { hp *heapPool updatedTime time.Time unusable bool - closed bool } // Close put the connection back to pool if possible. // Executed by multi times is ok. func (pc *PoolConn) Close() error { - if pc.closed { - return nil - } - defer func() { - pc.closed = true - }() - if pc.unusable { return pc.close() } diff --git a/heap.go b/heap.go index 5ffc87f..0b4f28c 100644 --- a/heap.go +++ b/heap.go @@ -41,7 +41,7 @@ type heapPool struct { initialCap int maxCap int maxIdle int - idletime time.Duration + idleTime time.Duration maxLifetime time.Duration cleanerCh chan struct{} @@ -65,9 +65,9 @@ func NewHeapPool(config *PoolConfig) (Pool, error) { if config.MaxIdle > 0 { maxIdle = config.MaxIdle } - idletime := 2 * time.Minute + idleTime := 2 * time.Minute if config.Idletime > 0 { - idletime = config.Idletime + idleTime = config.Idletime } maxLifetime := 15 * time.Minute if config.MaxLifetime > 0 { @@ -78,7 +78,7 @@ func NewHeapPool(config *PoolConfig) (Pool, error) { initialCap: initialCap, maxCap: maxCap, maxIdle: maxIdle, - idletime: idletime, + idleTime: idleTime, maxLifetime: maxLifetime, cleanerCh: make(chan struct{}), factory: config.Factory, @@ -126,6 +126,7 @@ func (hp *heapPool) Get() (net.Conn, error) { hp.mu.Unlock() return pc, nil } + go pc.close() } hp.mu.Unlock() @@ -178,7 +179,7 @@ func (hp *heapPool) Len() int { } func (hp *heapPool) cleaner() { - ticker := time.NewTicker(hp.idletime / 2) + ticker := time.NewTicker(hp.idleTime / 2) defer ticker.Stop() for { select { @@ -189,11 +190,13 @@ func (hp *heapPool) cleaner() { pc := (*hp.freeConn)[0] interval := time.Now().Sub(pc.updatedTime) if interval >= hp.maxLifetime { - heap.Pop(hp.freeConn).(*PoolConn).close() + _p := heap.Pop(hp.freeConn).(*PoolConn) + go _p.close() continue } - if interval >= hp.idletime && hp.freeConn.Len() > hp.maxIdle { - heap.Pop(hp.freeConn).(*PoolConn).close() + if interval >= hp.idleTime && hp.freeConn.Len() > hp.maxIdle { + _p := heap.Pop(hp.freeConn).(*PoolConn) + go _p.close() continue } break diff --git a/heap_test.go b/heap_test.go index 781fabc..0d02dfe 100644 --- a/heap_test.go +++ b/heap_test.go @@ -31,11 +31,17 @@ func TestNew(t *testing.T) { func TestPool(t *testing.T) { p, _ := newHeapPool() + if p.Len() != InitialCap { + t.Errorf("pool len is invalid, excepted: %v, bug get: %v", InitialCap, p.Len()) + } conn, err := p.Get() if err != nil { t.Errorf("Get error: %s", err) } + if p.Len() != InitialCap-1 { + t.Errorf("pool len is invalid, excepted: %v, bug get: %v", InitialCap-1, p.Len()) + } _, ok := conn.(*PoolConn) if !ok { @@ -45,7 +51,6 @@ func TestPool(t *testing.T) { if err := conn.Close(); err != nil { t.Errorf("Pool Conn close error:%v", err) } - if p.Len() != InitialCap { t.Errorf("Pool size is invalid, size:%v", p.Len()) } @@ -58,6 +63,30 @@ func TestPool(t *testing.T) { } } +func TestHeapPool_Len(t *testing.T) { + p, _ := newHeapPool() + defer p.Close() + + for i := 1; i <= 50; i++ { + if p.Len() != InitialCap { + t.Errorf("pool len is invalid, excepted: %v, bug get: %v, i: %v", InitialCap, p.Len(), i) + } + + conn, err := p.Get() + if err != nil { + t.Errorf("Get error: %s", err) + } + if p.Len() != InitialCap-1 { + t.Errorf("pool len is invalid, excepted: %v, bug get: %v, i: %v", InitialCap-1, p.Len(), i) + } + + conn.Close() + if p.Len() != InitialCap { + t.Errorf("pool len is invalid, excepted: %v, bug get: %v, i: %v", InitialCap, p.Len(), i) + } + } +} + func TestPriorityQueue(t *testing.T) { p, _ := newHeapPool() conn1, err := p.Get()