database/sql: add SetConnMaxIdleTime

Allow removing a connection from the connection pool after
it has been idle for a period of time, without regard to the
total lifespan of the connection.

Fixes #25232

Change-Id: Icff157b906769a2d2d45c67525e04a72feb8d832
Reviewed-on: https://go-review.googlesource.com/c/go/+/145758
Run-TryBot: Daniel Theophanes <kardianos@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Daniel Theophanes 2018-10-29 09:09:21 -07:00
parent 753011ebc3
commit 6c61a57cfc
2 changed files with 151 additions and 33 deletions

View file

@ -3593,6 +3593,61 @@ func TestStatsMaxIdleClosedTen(t *testing.T) {
}
}
func TestMaxIdleTime(t *testing.T) {
list := []struct {
wantMaxIdleTime time.Duration
wantIdleClosed int64
timeOffset time.Duration
}{
{time.Nanosecond, 1, 10 * time.Millisecond},
{time.Hour, 0, 10 * time.Millisecond},
}
baseTime := time.Unix(0, 0)
defer func() {
nowFunc = time.Now
}()
for _, item := range list {
nowFunc = func() time.Time {
return baseTime
}
t.Run(fmt.Sprintf("%v", item.wantMaxIdleTime), func(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
db.SetMaxOpenConns(1)
db.SetMaxIdleConns(1)
db.SetConnMaxIdleTime(item.wantMaxIdleTime)
db.SetConnMaxLifetime(0)
preMaxIdleClosed := db.Stats().MaxIdleTimeClosed
if err := db.Ping(); err != nil {
t.Fatal(err)
}
nowFunc = func() time.Time {
return baseTime.Add(item.timeOffset)
}
db.mu.Lock()
closing := db.connectionCleanerRunLocked()
db.mu.Unlock()
for _, c := range closing {
c.Close()
}
if g, w := int64(len(closing)), item.wantIdleClosed; g != w {
t.Errorf("got: %d; want %d closed conns", g, w)
}
st := db.Stats()
maxIdleClosed := st.MaxIdleTimeClosed - preMaxIdleClosed
if g, w := maxIdleClosed, item.wantIdleClosed; g != w {
t.Errorf(" got: %d; want %d max idle closed conns", g, w)
}
})
}
}
type nvcDriver struct {
fakeDriver
skipNamedValueCheck bool