Skip to content

Commit

Permalink
NO-ISSUE Code refactoring (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
linxGnu committed Aug 6, 2021
1 parent 28dab12 commit 4aafc01
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 285 deletions.
38 changes: 13 additions & 25 deletions balancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package mssqlx

import (
"context"
"fmt"
"sync/atomic"
"time"
)
Expand All @@ -22,7 +23,7 @@ type balancer struct {

// new balancer and start health checkers
func newBalancer(ctx context.Context, numHealthChecker int, numDbInstance int, isWsrep bool) *balancer {
if numHealthChecker <= 0 {
if numHealthChecker < 2 {
numHealthChecker = 2 // at least two checkers
}

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

// failure make a db node become failure and auto health tracking
func (c *balancer) failure(w *wrapper) {
func (c *balancer) failure(w *wrapper, err error) {
if c.dbs.remove(w) { // remove this node
c.sendFailure(w)
}
}

func (c *balancer) sendFailure(w *wrapper) {
select {
case <-c.ctx.Done():
return
reportError(fmt.Sprintf("deactive connection:[%s] for health checking due to error", w.dsn), err)

case c.fail <- w: // give to health checker
select {
case <-c.ctx.Done():
case c.fail <- w:
}
}
}

// healthChecker daemon to check health of db connection
func (c *balancer) healthChecker() {
doneCh := c.ctx.Done()

var db *wrapper
for {
select {
case <-doneCh:
case <-c.ctx.Done():
return

case db = <-c.fail:
case db := <-c.fail:
if ping(db) == nil && (!c.isWsrep || db.checkWsrepReady()) {
c.dbs.add(db)
continue
} else {
c.fail <- db
}

select {
case <-doneCh:
case <-c.ctx.Done():
return

case <-time.After(time.Duration(c.getHealthCheckPeriod()) * time.Millisecond):
}

select {
case <-doneCh:
return

case c.fail <- db:
}
}
}
}

func (c *balancer) destroy() {
c.dbs.clear()
c.cancel()
}
68 changes: 68 additions & 0 deletions dbList.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package mssqlx

import (
"sync"
"sync/atomic"
)

type dbList struct {
lk sync.RWMutex
list []*wrapper
currentIndex uint32
}

func (b *dbList) current() (w *wrapper) {
b.lk.RLock()

if n := uint32(len(b.list)); n > 0 {
w = b.list[atomic.LoadUint32(&b.currentIndex)%n]
}

b.lk.RUnlock()

return
}

func (b *dbList) next() (w *wrapper) {
b.lk.RLock()

if n := uint32(len(b.list)); n > 0 {
w = b.list[atomic.AddUint32(&b.currentIndex, 1)%n]
}

b.lk.RUnlock()

return
}

func (b *dbList) add(w *wrapper) {
if w != nil {
b.lk.Lock()
b.list = append(b.list, w)
b.lk.Unlock()
}
}

func (b *dbList) remove(w *wrapper) (removed bool) {
if w != nil {
b.lk.Lock()

n := len(b.list)
for i := 0; i < n; i++ {
if b.list[i] == w { // found
removed = true

if i != n-1 {
b.list[i] = b.list[n-1]
}
b.list = b.list[:n-1]

break
}
}

b.lk.Unlock()
}

return
}
35 changes: 35 additions & 0 deletions db_wrapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package mssqlx

import (
"github.com/jmoiron/sqlx"
)

type wrapper struct {
db *sqlx.DB
dsn string
}

func (w *wrapper) checkWsrepReady() bool {
type wsrepVariable struct {
VariableName string `db:"Variable_name"`
Value string `db:"Value"`
}

var v wsrepVariable

if err := w.db.Get(&v, "SHOW VARIABLES LIKE 'wsrep_on'"); err != nil {
reportError("SHOW VARIABLES LIKE 'wsrep_on'", err)
return false
}

if v.Value != "ON" {
return true
}

if err := w.db.Get(&v, "SHOW STATUS LIKE 'wsrep_ready'"); err != nil || v.Value != "ON" {
reportError("SHOW STATUS LIKE 'wsrep_ready'", err)
return false
}

return true
}
21 changes: 9 additions & 12 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ package mssqlx
import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"os"
"strings"
"time"

"github.com/go-sql-driver/mysql"
"github.com/lib/pq"
)

// check bad connection
func isErrBadConn(err error) bool {
if err != nil {
if err == driver.ErrBadConn || err == sql.ErrConnDone || err == mysql.ErrInvalidConn {
if errors.Is(err, driver.ErrBadConn) ||
errors.Is(err, mysql.ErrInvalidConn) ||
errors.Is(err, pq.ErrChannelNotOpen) {
return true
}

Expand Down Expand Up @@ -42,7 +46,6 @@ func isErrCode(err error, code int) bool {
}

switch mErr := err.(type) {

case *mysql.MySQLError:
return mErr.Number == uint16(code)

Expand All @@ -52,16 +55,10 @@ func isErrCode(err error, code int) bool {
}
}

func parseError(w *wrapper, err error) error {
if err == nil {
return nil
}

if w != nil && ping(w) != nil {
return ErrNetwork
}

return err
func isStdErr(err error) bool {
return errors.Is(err, sql.ErrNoRows) ||
errors.Is(err, sql.ErrTxDone) ||
errors.Is(err, sql.ErrConnDone)
}

func reportError(v string, err error) {
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
module github.com/linxGnu/mssqlx

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

0 comments on commit 4aafc01

Please sign in to comment.