-
Notifications
You must be signed in to change notification settings - Fork 0
/
backend_sql.go
108 lines (91 loc) · 2.34 KB
/
backend_sql.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package config
import (
"net/url"
"runtime"
"strconv"
"strings"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
"github.com/ory/hydra/pkg"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
type SQLConnection struct {
db *sqlx.DB
URL *url.URL
L logrus.FieldLogger
}
func cleanURLQuery(c *url.URL) *url.URL {
cleanurl := new(url.URL)
*cleanurl = *c
q := cleanurl.Query()
q.Del("max_conns")
q.Del("max_idle_conns")
q.Del("max_conn_lifetime")
cleanurl.RawQuery = q.Encode()
return cleanurl
}
func (c *SQLConnection) GetDatabase() *sqlx.DB {
if c.db != nil {
return c.db
}
var err error
clean := cleanURLQuery(c.URL)
if err = pkg.Retry(c.L, time.Second*15, time.Minute*2, func() error {
c.L.Infof("Connecting with %s", c.URL.Scheme+"://*:*@"+c.URL.Host+c.URL.Path+"?"+clean.RawQuery)
u := clean.String()
if clean.Scheme == "mysql" {
u = strings.Replace(u, "mysql://", "", -1)
}
if c.db, err = sqlx.Open(clean.Scheme, u); err != nil {
return errors.Errorf("Could not Connect to SQL: %s", err)
} else if err := c.db.Ping(); err != nil {
return errors.Errorf("Could not Connect to SQL: %s", err)
}
c.L.Infof("Connected to SQL!")
return nil
}); err != nil {
c.L.Fatalf("Could not Connect to SQL: %s", err)
}
maxConns := maxParallelism() * 2
if v := c.URL.Query().Get("max_conns"); v != "" {
s, err := strconv.ParseInt(v, 10, 64)
if err != nil {
c.L.Warnf("max_conns value %s could not be parsed to int: %s", v, err)
} else {
maxConns = int(s)
}
}
maxIdleConns := maxParallelism()
if v := c.URL.Query().Get("max_idle_conns"); v != "" {
s, err := strconv.ParseInt(v, 10, 64)
if err != nil {
c.L.Warnf("max_idle_conns value %s could not be parsed to int: %s", v, err)
} else {
maxIdleConns = int(s)
}
}
maxConnLifetime := time.Duration(0)
if v := c.URL.Query().Get("max_conn_lifetime"); v != "" {
s, err := time.ParseDuration(v)
if err != nil {
c.L.Warnf("max_conn_lifetime value %s could not be parsed to int: %s", v, err)
} else {
maxConnLifetime = s
}
}
c.db.SetMaxOpenConns(maxConns)
c.db.SetMaxIdleConns(maxIdleConns)
c.db.SetConnMaxLifetime(maxConnLifetime)
return c.db
}
func maxParallelism() int {
maxProcs := runtime.GOMAXPROCS(0)
numCPU := runtime.NumCPU()
if maxProcs < numCPU {
return maxProcs
}
return numCPU
}