[wip] cleanup unused connections
Signed-off-by: Anton Nesterov <anton@demiurg.io>
This commit is contained in:
parent
43dd4e9234
commit
b1f9cead34
|
@ -10,61 +10,93 @@ import (
|
||||||
* DBAdapter
|
* DBAdapter
|
||||||
* Automatically creates connections for each database URL.
|
* Automatically creates connections for each database URL.
|
||||||
* Executes queries on the specified database.
|
* Executes queries on the specified database.
|
||||||
* TODO: Closes connections older than 2 minutes.
|
* Closes connections older than ConnectionLiveTime
|
||||||
**/
|
**/
|
||||||
type DBAdapter struct {
|
type DBAdapter struct {
|
||||||
Type string
|
Type string
|
||||||
MaxAttempts int
|
MaxAttempts int
|
||||||
_db map[string]*sql.DB
|
ConnectionLiveTime int
|
||||||
_connect_attempts map[string]int
|
dbs *DBMap
|
||||||
_connect_time map[string]int64
|
}
|
||||||
|
|
||||||
|
type DBMap struct {
|
||||||
|
Connections map[string]*sql.DB
|
||||||
|
ConnectionAttempts map[string]int
|
||||||
|
ConnectionTime map[string]int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *DBAdapter) Open(url string) (*sql.DB, error) {
|
func (a *DBAdapter) Open(url string) (*sql.DB, error) {
|
||||||
if a._db == nil {
|
defer a.CleanUp()
|
||||||
a._db = make(map[string]*sql.DB)
|
|
||||||
}
|
|
||||||
if a._connect_attempts == nil {
|
|
||||||
a._connect_attempts = make(map[string]int)
|
|
||||||
}
|
|
||||||
if a._connect_time == nil {
|
|
||||||
a._connect_time = make(map[string]int64)
|
|
||||||
}
|
|
||||||
if a.MaxAttempts == 0 {
|
if a.MaxAttempts == 0 {
|
||||||
a.MaxAttempts = 6
|
a.MaxAttempts = 6
|
||||||
}
|
}
|
||||||
if _, ok := a._db[url]; !ok {
|
if a.ConnectionLiveTime == 0 {
|
||||||
a._db[url], _ = sql.Open(a.Type, url)
|
a.ConnectionLiveTime = 120
|
||||||
|
}
|
||||||
|
if a.dbs == nil {
|
||||||
|
a.dbs = &DBMap{
|
||||||
|
Connections: make(map[string]*sql.DB),
|
||||||
|
ConnectionAttempts: make(map[string]int),
|
||||||
|
ConnectionTime: make(map[string]int64),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connections := a.dbs.Connections
|
||||||
|
attempts := a.dbs.ConnectionAttempts
|
||||||
|
lastHits := a.dbs.ConnectionTime
|
||||||
|
|
||||||
|
lastHits[url] = time.Now().Unix()
|
||||||
|
if _, ok := connections[url]; !ok {
|
||||||
|
connections[url], _ = sql.Open(a.Type, url)
|
||||||
} else {
|
} else {
|
||||||
err := a._db[url].Ping()
|
err := connections[url].Ping()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a._db[url] = nil
|
connections[url] = nil
|
||||||
a._connect_attempts[url]++
|
attempts[url]++
|
||||||
time.Sleep(time.Duration(5) * time.Second)
|
time.Sleep(time.Duration(5) * time.Second)
|
||||||
if a._connect_attempts[url] > a.MaxAttempts {
|
if attempts[url] > a.MaxAttempts {
|
||||||
return nil, fmt.Errorf(`failed to connect to "%s"`, url)
|
return nil, fmt.Errorf(
|
||||||
|
`failed to connect to "%s", after %v attempts`,
|
||||||
|
url,
|
||||||
|
a.MaxAttempts,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return a.Open(url)
|
return a.Open(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a._connect_attempts[url] = 0
|
a.dbs.ConnectionAttempts[url] = 0
|
||||||
a._connect_time[url] = time.Now().Unix()
|
return a.dbs.Connections[url], nil
|
||||||
return a._db[url], nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *DBAdapter) GetDB(url string) *sql.DB {
|
func (a *DBAdapter) GetDB(url string) *sql.DB {
|
||||||
if a._db == nil {
|
if a.dbs == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return a._db[url]
|
return a.dbs.Connections[url]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *DBAdapter) Close() {
|
func (a *DBAdapter) Close() {
|
||||||
for _, db := range a._db {
|
for _, db := range a.dbs.Connections {
|
||||||
db.Close()
|
db.Close()
|
||||||
}
|
}
|
||||||
a._db = nil
|
a.dbs = nil
|
||||||
a._connect_attempts = nil
|
}
|
||||||
|
|
||||||
|
func (a *DBAdapter) CleanUp() {
|
||||||
|
if a.dbs == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastHits := a.dbs.ConnectionTime
|
||||||
|
liveTime := a.ConnectionLiveTime
|
||||||
|
for url, db := range a.dbs.Connections {
|
||||||
|
if time.Now().Unix()-lastHits[url] > int64(liveTime) {
|
||||||
|
db.Close()
|
||||||
|
delete(a.dbs.Connections, url)
|
||||||
|
delete(a.dbs.ConnectionAttempts, url)
|
||||||
|
delete(a.dbs.ConnectionTime, url)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *DBAdapter) Query(req Query) (*sql.Rows, error) {
|
func (a *DBAdapter) Query(req Query) (*sql.Rows, error) {
|
||||||
|
|
Loading…
Reference in a new issue