diff --git a/redis/pool.go b/redis/pool.go index d7bb71e0..e64a4155 100644 --- a/redis/pool.go +++ b/redis/pool.go @@ -139,6 +139,10 @@ type Pool struct { // closed. TestOnBorrow func(c Conn, t time.Time) error + // Lifo is a boolean value which determines the order in which the connections + // idle connection in the pool method, True: pushBack, False: pushFront, default False + Lifo bool + // Maximum number of idle connections in the pool. MaxIdle int @@ -210,17 +214,7 @@ func (p *Pool) GetContext(ctx context.Context) (Conn, error) { } // Prune stale connections at the back of the idle list. - if p.IdleTimeout > 0 { - n := p.idle.count - for i := 0; i < n && p.idle.back != nil && p.idle.back.t.Add(p.IdleTimeout).Before(nowFunc()); i++ { - pc := p.idle.back - p.idle.popBack() - p.mu.Unlock() - pc.c.Close() - p.mu.Lock() - p.active-- - } - } + p.pruneConn() // Get idle connection from the front of idle list. for p.idle.front != nil { @@ -264,6 +258,32 @@ func (p *Pool) GetContext(ctx context.Context) (Conn, error) { return &activeConn{p: p, pc: &poolConn{c: c, created: nowFunc()}}, nil } +func (p *Pool) pruneConn() { + if p.IdleTimeout <= 0 { + return + } + n := p.idle.count + if p.Lifo { + for i := 0; i < n && p.idle.front != nil && p.idle.front.t.Add(p.IdleTimeout).Before(nowFunc()); i++ { + pc := p.idle.front + p.idle.popFront() + p.mu.Unlock() + pc.c.Close() + p.mu.Lock() + p.active-- + } + } else { + for i := 0; i < n && p.idle.back != nil && p.idle.back.t.Add(p.IdleTimeout).Before(nowFunc()); i++ { + pc := p.idle.back + p.idle.popBack() + p.mu.Unlock() + pc.c.Close() + p.mu.Lock() + p.active-- + } + } +} + // PoolStats contains pool statistics. type PoolStats struct { // ActiveCount is the number of connections in the pool. The count includes @@ -403,10 +423,21 @@ func (p *Pool) put(pc *poolConn, forceClose bool) error { p.mu.Lock() if !p.closed && !forceClose { pc.t = nowFunc() - p.idle.pushFront(pc) + + if p.Lifo { + p.idle.pushBack(pc) + } else { + p.idle.pushFront(pc) + } + if p.idle.count > p.MaxIdle { - pc = p.idle.back - p.idle.popBack() + if p.Lifo { + pc = p.idle.front + p.idle.popFront() + } else { + pc = p.idle.back + p.idle.popBack() + } } else { pc = nil } @@ -641,6 +672,20 @@ func (l *idleList) pushFront(pc *poolConn) { l.count++ } +// idle connect push list back +func (l *idleList) pushBack(pc *poolConn) { + pc.next = nil + if l.count == 0 { + l.front = pc + pc.prev = nil + } else { + pc.prev = l.back + l.back.next = pc + } + l.back = pc + l.count++ +} + func (l *idleList) popFront() { pc := l.front l.count--