Skip to content

Commit 97836c3

Browse files
author
Kryvchun
committed
Add MaxConnLifetime
1 parent 2d7bb13 commit 97836c3

File tree

4 files changed

+73
-35
lines changed

4 files changed

+73
-35
lines changed

sonic/controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func newDriversHolder(
2020
opts.PoolMinConnections,
2121
opts.PoolMaxConnections,
2222
opts.PoolPingThreshold,
23+
opts.PoolMaxIdleLifetime,
2324
)
2425
if err != nil {
2526
return nil, err

sonic/driver.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ type driver struct {
3333
Port int
3434
Password string
3535

36+
lastUse time.Time
3637
lastPing time.Time
37-
channel Channel
38+
39+
channel Channel
3840
*connection
3941
}
4042

@@ -67,6 +69,7 @@ func (c *driver) Connect() error {
6769

6870
c.connection, err = newConnection(c)
6971
c.lastPing = time.Now()
72+
c.lastUse = time.Now()
7073

7174
return err
7275
}
@@ -102,10 +105,16 @@ func (c *driver) Ping() error {
102105
}
103106

104107
// softPing pings the connection if it wasn't pinged for a while.
105-
func (c *driver) softPing(threshold time.Duration) (ok bool) {
106-
if threshold <= 0 || time.Since(c.lastPing) < threshold {
107-
return true
108+
func (c *driver) checkConn(pingThreshold, maxLifetime time.Duration) (ok bool) {
109+
if maxLifetime > 0 && time.Since(c.lastUse) > maxLifetime {
110+
return false
111+
}
112+
113+
c.lastUse = time.Now()
114+
115+
if pingThreshold > 0 && time.Since(c.lastPing) > pingThreshold {
116+
return c.Ping() == nil
108117
}
109118

110-
return c.Ping() == nil
119+
return true
111120
}

sonic/options.go

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ package sonic
33
import "time"
44

55
type controllerOptions struct {
6-
Host string
7-
Port int
8-
Password string
9-
PoolMinConnections int
10-
PoolMaxConnections int
11-
PoolPingThreshold time.Duration
12-
Channel Channel
6+
Host string
7+
Port int
8+
Password string
9+
PoolMinConnections int
10+
PoolMaxConnections int
11+
PoolPingThreshold time.Duration
12+
PoolMaxIdleLifetime time.Duration
13+
Channel Channel
1314
}
1415

1516
func (o controllerOptions) With(optionSetters ...OptionSetter) controllerOptions {
@@ -32,9 +33,10 @@ func defaultOptions(
3233
Password: password,
3334
Channel: channel,
3435

35-
PoolMinConnections: 1,
36-
PoolMaxConnections: 16,
37-
PoolPingThreshold: time.Minute,
36+
PoolMinConnections: 1,
37+
PoolMaxConnections: 16,
38+
PoolMaxIdleLifetime: 5 * time.Minute,
39+
PoolPingThreshold: 0,
3840
}
3941
}
4042

@@ -60,9 +62,18 @@ func OptionPoolMinIdleConnections(val int) OptionSetter {
6062
// OptionPoolPingThreshold sets a minimum ping interval to ensure that
6163
// the connection is healthy before getting it from the pool.
6264
//
63-
// By default is 1m. For disabling set 0.
65+
// By default is 0s. For disabling set it to 0.
6466
func OptionPoolPingThreshold(val time.Duration) OptionSetter {
6567
return func(o *controllerOptions) {
6668
o.PoolPingThreshold = val
6769
}
6870
}
71+
72+
// OptionPoolMaxIdleLifetime sets a minimum lifetime of idle connection.
73+
//
74+
// By default is 5m. For disabling set it to 0.
75+
func OptionPoolMaxIdleLifetime(val time.Duration) OptionSetter {
76+
return func(o *controllerOptions) {
77+
o.PoolMaxIdleLifetime = val
78+
}
79+
}

sonic/pool.go

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ import (
55
"time"
66
)
77

8+
const recursionLimit = 8
9+
810
type driversPool struct {
9-
driverFactory *driverFactory
10-
drivers chan *driverWrapper
11-
pingThreshold time.Duration
11+
driverFactory *driverFactory
12+
drivers chan *driverWrapper
13+
pingThreshold time.Duration
14+
maxIdleLifetime time.Duration
1215

1316
isPoolClosedMu sync.RWMutex
1417
isPoolClosed bool
@@ -19,12 +22,14 @@ func newDriversPool(
1922
minIdle int,
2023
maxIdle int,
2124
pingThreshold time.Duration,
25+
maxIdleLifetime time.Duration,
2226
) (*driversPool, error) {
2327
dp := &driversPool{
2428
driverFactory: df,
2529
drivers: make(chan *driverWrapper, maxIdle),
2630

27-
pingThreshold: pingThreshold,
31+
pingThreshold: pingThreshold,
32+
maxIdleLifetime: maxIdleLifetime,
2833

2934
isPoolClosedMu: sync.RWMutex{},
3035
isPoolClosed: false,
@@ -55,15 +60,15 @@ func newDriversPool(
5560

5661
// put the connection back.
5762
func (p *driversPool) put(dw *driverWrapper) {
58-
if dw.closed {
63+
if dw.driver.closed {
5964
return
6065
}
6166

6267
p.isPoolClosedMu.RLock()
6368
defer p.isPoolClosedMu.RUnlock()
6469

6570
if p.isPoolClosed {
66-
dw.close()
71+
dw.driver.close()
6772

6873
return
6974
}
@@ -72,8 +77,8 @@ func (p *driversPool) put(dw *driverWrapper) {
7277
case p.drivers <- dw:
7378
default:
7479
// The pool is full.
75-
_ = dw.Quit()
76-
dw.close()
80+
_ = dw.driver.Quit()
81+
dw.driver.close()
7782
}
7883
}
7984

@@ -89,24 +94,36 @@ func (p *driversPool) Get() (*driverWrapper, error) {
8994
return nil, ErrClosed
9095
}
9196

97+
return p.getNextDriver(0)
98+
}
99+
100+
func (p *driversPool) getNextDriver(depth int) (*driverWrapper, error) {
101+
if depth > recursionLimit {
102+
return p.newDriver()
103+
}
104+
92105
select {
93106
case d := <-p.drivers:
94-
if !d.softPing(p.pingThreshold) {
95-
d.close()
107+
if !d.checkConn(p.pingThreshold, p.maxIdleLifetime) {
108+
d.driver.close()
96109

97-
return p.Get()
110+
return p.getNextDriver(depth + 1)
98111
}
99112

100113
return d, nil
101114
default:
102-
d := p.driverFactory.Build()
115+
return p.newDriver()
116+
}
117+
}
103118

104-
if err := d.Connect(); err != nil {
105-
return nil, err
106-
}
119+
func (p *driversPool) newDriver() (*driverWrapper, error) {
120+
d := p.driverFactory.Build()
107121

108-
return p.wrapDriver(d), nil
122+
if err := d.Connect(); err != nil {
123+
return nil, err
109124
}
125+
126+
return p.wrapDriver(d), nil
110127
}
111128

112129
// Close and quit all connections in the pool.
@@ -117,10 +134,10 @@ func (p *driversPool) Close() {
117134

118135
close(p.drivers)
119136
for dw := range p.drivers {
120-
if !dw.closed {
121-
_ = dw.Quit()
137+
if !dw.driver.closed {
138+
_ = dw.driver.Quit()
122139

123-
dw.close()
140+
dw.driver.close()
124141
}
125142
}
126143
}

0 commit comments

Comments
 (0)