dal/pkg/adapter/DBAdapter.go
Anton Nesterov 25f3e18f4a
[wip] adapter
Signed-off-by: Anton Nesterov <anton@demiurg.io>
2024-08-11 16:29:53 +02:00

93 lines
1.9 KiB
Go

package adapter
import (
"database/sql"
"fmt"
"time"
)
/**
* DBAdapter
* Automatically creates connections for each database URL.
* Executes queries on the specified database.
* TODO: Closes connections older than 2 minutes.
**/
type DBAdapter struct {
Type string
MaxAttempts int
_db map[string]*sql.DB
_connect_attempts map[string]int
_connect_time map[string]int64
}
func (a *DBAdapter) Open(url string) (*sql.DB, error) {
if a._db == nil {
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 {
a.MaxAttempts = 6
}
if _, ok := a._db[url]; !ok {
a._db[url], _ = sql.Open(a.Type, url)
} else {
err := a._db[url].Ping()
if err != nil {
a._db[url] = nil
a._connect_attempts[url]++
time.Sleep(time.Duration(5) * time.Second)
if a._connect_attempts[url] > a.MaxAttempts {
return nil, fmt.Errorf(`failed to connect to "%s"`, url)
}
return a.Open(url)
}
}
a._connect_attempts[url] = 0
a._connect_time[url] = time.Now().Unix()
return a._db[url], nil
}
func (a *DBAdapter) GetDB(url string) *sql.DB {
if a._db == nil {
return nil
}
return a._db[url]
}
func (a *DBAdapter) Close() {
for _, db := range a._db {
db.Close()
}
a._db = nil
a._connect_attempts = nil
}
func (a *DBAdapter) Query(req Query) (*sql.Rows, error) {
db, err := a.Open(req.Db)
if err != nil {
return nil, err
}
sfmt, err := db.Prepare(req.Expression)
if err != nil {
return nil, err
}
return sfmt.Query(req.Data...)
}
func (a *DBAdapter) Exec(req Query) (sql.Result, error) {
db, err := a.Open(req.Db)
if err != nil {
return nil, err
}
sfmt, err := db.Prepare(req.Expression)
if err != nil {
return nil, err
}
return sfmt.Exec(req.Data...)
}