diff options
| author | INADA Naoki <songofacandy@gmail.com> | 2015-03-03 21:27:07 +0900 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@golang.org> | 2015-12-02 17:38:31 +0000 |
| commit | 0c516c16328575ab78a4cce49874955dd590efa2 (patch) | |
| tree | ac5a5e86649358ae7a960fbb523b297c5e8f4490 /src/database/sql/sql_test.go | |
| parent | 2cb265d16c611aae56fd3f3ce87279a1f52f925a (diff) | |
| download | go-0c516c16328575ab78a4cce49874955dd590efa2.tar.xz | |
database/sql: Add DB.SetConnMaxLifetime
Long lived connections may make some DB operation difficult.
(e.g. retiring load balanced DB server.)
So SetConnMaxLifetime closes long lived connections.
It can be used to limit maximum idle time, too.
Closing idle connections reduces active connections while application is idle
and avoids connections are closed by server side (cause errBadConn while querying).
fixes #9851
Change-Id: I2e8e824219c1bee7f4b885d38ed96d11b7202b56
Reviewed-on: https://go-review.googlesource.com/6580
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/database/sql/sql_test.go')
| -rw-r--r-- | src/database/sql/sql_test.go | 131 |
1 files changed, 101 insertions, 30 deletions
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go index d835bc160a..48c872d8c6 100644 --- a/src/database/sql/sql_test.go +++ b/src/database/sql/sql_test.go @@ -142,6 +142,20 @@ func (db *DB) numFreeConns() int { return len(db.freeConn) } +// clearAllConns closes all connections in db. +func (db *DB) clearAllConns(t *testing.T) { + db.SetMaxIdleConns(0) + + if g, w := db.numFreeConns(), 0; g != w { + t.Errorf("free conns = %d; want %d", g, w) + } + + if n := db.numDepsPollUntil(0, time.Second); n > 0 { + t.Errorf("number of dependencies = %d; expected 0", n) + db.dumpDeps(t) + } +} + func (db *DB) dumpDeps(t *testing.T) { for fc := range db.dep { db.dumpDep(t, 0, fc, map[finalCloser]bool{}) @@ -991,16 +1005,7 @@ func TestMaxOpenConns(t *testing.T) { // Force the number of open connections to 0 so we can get an accurate // count for the test - db.SetMaxIdleConns(0) - - if g, w := db.numFreeConns(), 0; g != w { - t.Errorf("free conns = %d; want %d", g, w) - } - - if n := db.numDepsPollUntil(0, time.Second); n > 0 { - t.Errorf("number of dependencies = %d; expected 0", n) - db.dumpDeps(t) - } + db.clearAllConns(t) driver.mu.Lock() opens0 := driver.openCount @@ -1096,16 +1101,7 @@ func TestMaxOpenConns(t *testing.T) { db.dumpDeps(t) } - db.SetMaxIdleConns(0) - - if g, w := db.numFreeConns(), 0; g != w { - t.Errorf("free conns = %d; want %d", g, w) - } - - if n := db.numDepsPollUntil(0, time.Second); n > 0 { - t.Errorf("number of dependencies = %d; expected 0", n) - db.dumpDeps(t) - } + db.clearAllConns(t) } // Issue 9453: tests that SetMaxOpenConns can be lowered at runtime @@ -1263,6 +1259,90 @@ func TestStats(t *testing.T) { } } +func TestConnMaxLifetime(t *testing.T) { + t0 := time.Unix(1000000, 0) + offset := time.Duration(0) + + nowFunc = func() time.Time { return t0.Add(offset) } + defer func() { nowFunc = time.Now }() + + db := newTestDB(t, "magicquery") + defer closeDB(t, db) + + driver := db.driver.(*fakeDriver) + + // Force the number of open connections to 0 so we can get an accurate + // count for the test + db.clearAllConns(t) + + driver.mu.Lock() + opens0 := driver.openCount + closes0 := driver.closeCount + driver.mu.Unlock() + + db.SetMaxIdleConns(10) + db.SetMaxOpenConns(10) + + tx, err := db.Begin() + if err != nil { + t.Fatal(err) + } + + offset = time.Second + tx2, err := db.Begin() + if err != nil { + t.Fatal(err) + } + + tx.Commit() + tx2.Commit() + + driver.mu.Lock() + opens := driver.openCount - opens0 + closes := driver.closeCount - closes0 + driver.mu.Unlock() + + if opens != 2 { + t.Errorf("opens = %d; want 2", opens) + } + if closes != 0 { + t.Errorf("closes = %d; want 0", closes) + } + if g, w := db.numFreeConns(), 2; g != w { + t.Errorf("free conns = %d; want %d", g, w) + } + + // Expire first conn + offset = time.Second * 11 + db.SetConnMaxLifetime(time.Second * 10) + if err != nil { + t.Fatal(err) + } + + tx, err = db.Begin() + if err != nil { + t.Fatal(err) + } + tx2, err = db.Begin() + if err != nil { + t.Fatal(err) + } + tx.Commit() + tx2.Commit() + + driver.mu.Lock() + opens = driver.openCount - opens0 + closes = driver.closeCount - closes0 + driver.mu.Unlock() + + if opens != 3 { + t.Errorf("opens = %d; want 3", opens) + } + if closes != 1 { + t.Errorf("closes = %d; want 1", closes) + } +} + // golang.org/issue/5323 func TestStmtCloseDeps(t *testing.T) { if testing.Short() { @@ -1356,16 +1436,7 @@ func TestStmtCloseDeps(t *testing.T) { db.dumpDeps(t) } - db.SetMaxIdleConns(0) - - if g, w := db.numFreeConns(), 0; g != w { - t.Errorf("free conns = %d; want %d", g, w) - } - - if n := db.numDepsPollUntil(0, time.Second); n > 0 { - t.Errorf("number of dependencies = %d; expected 0", n) - db.dumpDeps(t) - } + db.clearAllConns(t) } // golang.org/issue/5046 |
