Skip to content

Commit 4aafc01

Browse files
authored
NO-ISSUE Code refactoring (#13)
1 parent 28dab12 commit 4aafc01

File tree

10 files changed

+199
-285
lines changed

10 files changed

+199
-285
lines changed

balancer.go

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package mssqlx
22

33
import (
44
"context"
5+
"fmt"
56
"sync/atomic"
67
"time"
78
)
@@ -22,7 +23,7 @@ type balancer struct {
2223

2324
// new balancer and start health checkers
2425
func newBalancer(ctx context.Context, numHealthChecker int, numDbInstance int, isWsrep bool) *balancer {
25-
if numHealthChecker <= 0 {
26+
if numHealthChecker < 2 {
2627
numHealthChecker = 2 // at least two checkers
2728
}
2829

@@ -71,55 +72,42 @@ func (c *balancer) get(shouldBalancing bool) *wrapper {
7172
}
7273

7374
// failure make a db node become failure and auto health tracking
74-
func (c *balancer) failure(w *wrapper) {
75+
func (c *balancer) failure(w *wrapper, err error) {
7576
if c.dbs.remove(w) { // remove this node
76-
c.sendFailure(w)
77-
}
78-
}
79-
80-
func (c *balancer) sendFailure(w *wrapper) {
81-
select {
82-
case <-c.ctx.Done():
83-
return
77+
reportError(fmt.Sprintf("deactive connection:[%s] for health checking due to error", w.dsn), err)
8478

85-
case c.fail <- w: // give to health checker
79+
select {
80+
case <-c.ctx.Done():
81+
case c.fail <- w:
82+
}
8683
}
8784
}
8885

8986
// healthChecker daemon to check health of db connection
9087
func (c *balancer) healthChecker() {
91-
doneCh := c.ctx.Done()
92-
93-
var db *wrapper
9488
for {
9589
select {
96-
case <-doneCh:
90+
case <-c.ctx.Done():
9791
return
9892

99-
case db = <-c.fail:
93+
case db := <-c.fail:
10094
if ping(db) == nil && (!c.isWsrep || db.checkWsrepReady()) {
10195
c.dbs.add(db)
10296
continue
97+
} else {
98+
c.fail <- db
10399
}
104100

105101
select {
106-
case <-doneCh:
102+
case <-c.ctx.Done():
107103
return
108104

109105
case <-time.After(time.Duration(c.getHealthCheckPeriod()) * time.Millisecond):
110106
}
111-
112-
select {
113-
case <-doneCh:
114-
return
115-
116-
case c.fail <- db:
117-
}
118107
}
119108
}
120109
}
121110

122111
func (c *balancer) destroy() {
123-
c.dbs.clear()
124112
c.cancel()
125113
}

dbList.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package mssqlx
2+
3+
import (
4+
"sync"
5+
"sync/atomic"
6+
)
7+
8+
type dbList struct {
9+
lk sync.RWMutex
10+
list []*wrapper
11+
currentIndex uint32
12+
}
13+
14+
func (b *dbList) current() (w *wrapper) {
15+
b.lk.RLock()
16+
17+
if n := uint32(len(b.list)); n > 0 {
18+
w = b.list[atomic.LoadUint32(&b.currentIndex)%n]
19+
}
20+
21+
b.lk.RUnlock()
22+
23+
return
24+
}
25+
26+
func (b *dbList) next() (w *wrapper) {
27+
b.lk.RLock()
28+
29+
if n := uint32(len(b.list)); n > 0 {
30+
w = b.list[atomic.AddUint32(&b.currentIndex, 1)%n]
31+
}
32+
33+
b.lk.RUnlock()
34+
35+
return
36+
}
37+
38+
func (b *dbList) add(w *wrapper) {
39+
if w != nil {
40+
b.lk.Lock()
41+
b.list = append(b.list, w)
42+
b.lk.Unlock()
43+
}
44+
}
45+
46+
func (b *dbList) remove(w *wrapper) (removed bool) {
47+
if w != nil {
48+
b.lk.Lock()
49+
50+
n := len(b.list)
51+
for i := 0; i < n; i++ {
52+
if b.list[i] == w { // found
53+
removed = true
54+
55+
if i != n-1 {
56+
b.list[i] = b.list[n-1]
57+
}
58+
b.list = b.list[:n-1]
59+
60+
break
61+
}
62+
}
63+
64+
b.lk.Unlock()
65+
}
66+
67+
return
68+
}

db_wrapper.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package mssqlx
2+
3+
import (
4+
"github.com/jmoiron/sqlx"
5+
)
6+
7+
type wrapper struct {
8+
db *sqlx.DB
9+
dsn string
10+
}
11+
12+
func (w *wrapper) checkWsrepReady() bool {
13+
type wsrepVariable struct {
14+
VariableName string `db:"Variable_name"`
15+
Value string `db:"Value"`
16+
}
17+
18+
var v wsrepVariable
19+
20+
if err := w.db.Get(&v, "SHOW VARIABLES LIKE 'wsrep_on'"); err != nil {
21+
reportError("SHOW VARIABLES LIKE 'wsrep_on'", err)
22+
return false
23+
}
24+
25+
if v.Value != "ON" {
26+
return true
27+
}
28+
29+
if err := w.db.Get(&v, "SHOW STATUS LIKE 'wsrep_ready'"); err != nil || v.Value != "ON" {
30+
reportError("SHOW STATUS LIKE 'wsrep_ready'", err)
31+
return false
32+
}
33+
34+
return true
35+
}

errors.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,22 @@ package mssqlx
33
import (
44
"database/sql"
55
"database/sql/driver"
6+
"errors"
67
"fmt"
78
"os"
89
"strings"
910
"time"
1011

1112
"github.com/go-sql-driver/mysql"
13+
"github.com/lib/pq"
1214
)
1315

1416
// check bad connection
1517
func isErrBadConn(err error) bool {
1618
if err != nil {
17-
if err == driver.ErrBadConn || err == sql.ErrConnDone || err == mysql.ErrInvalidConn {
19+
if errors.Is(err, driver.ErrBadConn) ||
20+
errors.Is(err, mysql.ErrInvalidConn) ||
21+
errors.Is(err, pq.ErrChannelNotOpen) {
1822
return true
1923
}
2024

@@ -42,7 +46,6 @@ func isErrCode(err error, code int) bool {
4246
}
4347

4448
switch mErr := err.(type) {
45-
4649
case *mysql.MySQLError:
4750
return mErr.Number == uint16(code)
4851

@@ -52,16 +55,10 @@ func isErrCode(err error, code int) bool {
5255
}
5356
}
5457

55-
func parseError(w *wrapper, err error) error {
56-
if err == nil {
57-
return nil
58-
}
59-
60-
if w != nil && ping(w) != nil {
61-
return ErrNetwork
62-
}
63-
64-
return err
58+
func isStdErr(err error) bool {
59+
return errors.Is(err, sql.ErrNoRows) ||
60+
errors.Is(err, sql.ErrTxDone) ||
61+
errors.Is(err, sql.ErrConnDone)
6562
}
6663

6764
func reportError(v string, err error) {

go.mod

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
module github.com/linxGnu/mssqlx
22

33
require (
4-
github.com/davecgh/go-spew v1.1.1 // indirect
54
github.com/go-sql-driver/mysql v1.6.0
5+
github.com/hashicorp/go-multierror v1.1.1
66
github.com/jmoiron/sqlx v1.3.4
77
github.com/lib/pq v1.10.2
8-
github.com/mattn/go-sqlite3 v1.14.7
98
github.com/stretchr/testify v1.7.0
10-
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
119
)

go.sum

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
12
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2-
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3-
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
43
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
54
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
65
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
6+
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
7+
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
8+
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
9+
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
710
github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w=
811
github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
912
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
1013
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
1114
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
15+
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
1216
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
13-
github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA=
14-
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
1517
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1618
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1719
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
1820
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
1921
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
2022
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2123
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
24+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
2225
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
23-
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
24-
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)