Skip to content

Commit

Permalink
refact - proxysql with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicola Strappazzon C committed Jan 21, 2024
1 parent 1ebf748 commit 6f2a49c
Show file tree
Hide file tree
Showing 13 changed files with 468 additions and 194 deletions.
39 changes: 22 additions & 17 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,33 @@ env:
MYSQL_TEST_PASS: test
MYSQL_TEST_ADDR: 127.0.0.1:3306
MYSQL_TEST_CONCURRENT: 1
PROXYSQL_TEST_ADDR: 127.0.0.1:3307
PROXYSQL_ADMIN_TEST_ADDR: 127.0.0.1:6032

jobs:
test:
name: Check code quality and run tests
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: ${{ env.MYSQL_TEST_PASS }}
MYSQL_USER: ${{ env.MYSQL_TEST_USER }}
MYSQL_PASSWORD: ${{ env.MYSQL_TEST_PASS }}
ports:
- 3306:3306
options: >-
--health-cmd "mysqladmin ping"
--health-interval 10s
--health-timeout 5s
--health-retries 10
proxysql:
image: ghcr.io/debeando/docker-proxysql
ports:
- 3307:3306
- 6032:6032

steps:
- uses: actions/checkout@v3

Expand All @@ -20,23 +42,6 @@ jobs:
with:
go-version: 1.21

- name: Setup MySQL Server
uses: shogo82148/actions-setup-mysql@v1.21.0
with:
mysql-version: 8.0
user: ${{ env.MYSQL_TEST_USER }}
password: ${{ env.MYSQL_TEST_PASS }}
my-cnf: |
innodb_log_file_size=256MB
innodb_buffer_pool_size=512MB
max_allowed_packet=16MB
max_connections=50
local_infile=1
performance_schema=on
- name: Setup database
run: mysql --user 'root' --host '127.0.0.1' -e 'CREATE DATABASE gotest;'

- name: Get all dependencies
run: go get -u ./...

Expand Down
7 changes: 3 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@ go 1.19
require (
github.com/ClickHouse/clickhouse-go/v2 v2.14.2
github.com/aws/aws-sdk-go v1.44.319
github.com/debeando/zenit v1.4.5
github.com/fatih/color v1.15.0
github.com/go-sql-driver/mysql v1.7.1
github.com/google/uuid v1.3.1
github.com/hpcloud/tail v1.0.0
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
go.mongodb.org/mongo-driver v1.12.1
golang.org/x/sys v0.14.0
)

require (
github.com/ClickHouse/ch-go v0.58.2 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-faster/city v1.0.1 // indirect
github.com/go-faster/errors v0.6.1 // indirect
github.com/golang/snappy v0.0.1 // indirect
Expand All @@ -31,7 +32,6 @@ require (
github.com/pierrec/lz4/v4 v4.1.18 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rodaine/table v1.1.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
Expand All @@ -42,7 +42,6 @@ require (
go.opentelemetry.io/otel/trace v1.19.0 // indirect
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.7.0 // indirect
gopkg.in/fsnotify.v1 v1.4.7 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
Expand Down
11 changes: 2 additions & 9 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ github.com/aws/aws-sdk-go v1.44.319/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8
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/debeando/zenit v1.4.5 h1:3qecmh8v2KT2llPA96r9PEBEMWZAZ8EdWEywwzUab6o=
github.com/debeando/zenit v1.4.5/go.mod h1:SQy1dXrENEK+kOQRguYYj7edS6k9SLNGKWO/SO3p+CY=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=
github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI=
Expand All @@ -27,7 +26,6 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
Expand All @@ -51,7 +49,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/paulmach/orb v0.10.0 h1:guVYVqzxHE/CQ1KpfGO077TR0ATHSNjp4s6XGLn3W9s=
Expand All @@ -63,8 +60,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4=
github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
Expand Down Expand Up @@ -133,8 +128,6 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
1 change: 1 addition & 0 deletions mysql/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ func (c *Connection) FetchOne(query string) any {
return val
}

// QueryIterator
func (c *Connection) FetchAll(query string, fn func(map[string]string)) error {
if c.Instance == nil {
return errors.New("The instance is empty.")
Expand Down
2 changes: 1 addition & 1 deletion mysql/sql/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package sql_test
import (
"testing"

"github.com/debeando/zenit/common/sql"
"github.com/debeando/go-common/mysql/sql"
)

func TestEmpty(t *testing.T) {
Expand Down
169 changes: 6 additions & 163 deletions proxysql/main.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package proxysql

import (
"errors"
"fmt"

"github.com/debeando/go-common/cast"
"github.com/debeando/go-common/mysql"
"github.com/debeando/go-common/time"
)

const (
Expand All @@ -18,165 +13,13 @@ const (
)

type ProxySQL struct {
mysql.MySQL
Connection *mysql.Connection
Host string `yaml:"host"`
Password string `yaml:"password"`
Port uint16 `yaml:"port"`
Schema string `yaml:"schema"`
Servers []Server `yaml:"servers"`
Status string `yaml:"status"`
Timeout uint8 `yaml:"timeout"`
Username string `yaml:"username"`
}

type Server struct {
HostgroupID uint8 `yaml:"hostgroup_id"`
Hostname string `yaml:"hostname"`
MaxConnections uint16 `yaml:"max_connections"`
MaxReplicationLag uint16 `yaml:"max_replication_lag"`
Status string `yaml:"status"`
Weight uint16 `yaml:"weight"`
}

func (p *ProxySQL) AddServer(s Server) int {
p.Servers = append(p.Servers, s)

return 0
}

func (p *ProxySQL) DSN() string {
return fmt.Sprintf(
"%s:%s@tcp(%s:%d)/?timeout=%ds",
p.Username,
p.Password,
p.Host,
p.Port,
p.Timeout,
)
}

func (p *ProxySQL) GetStatusServer(index int) string {
sql := fmt.Sprintf(
"SELECT status FROM mysql_servers WHERE hostgroup_id = %d AND hostname = '%s' LIMIT 1;",
p.Servers[index].HostgroupID,
p.Servers[index].Hostname,
)
result, _ := p.Connection.Query(sql)

if len(result) == 1 {
return result[0]["status"]
}
return ServerStatus
}

func (p *ProxySQL) SetStatusServer(index int, ss string) {
sql := fmt.Sprintf(
"UPDATE mysql_servers SET status = '%s' WHERE hostgroup_id = %d AND hostname = '%s';",
ss,
p.Servers[index].HostgroupID,
p.Servers[index].Hostname,
)
p.Connection.Query(sql)
}

func (p *ProxySQL) ExistServer(index int) bool {
sql := fmt.Sprintf(
"SELECT count() AS cnt FROM mysql_servers WHERE hostgroup_id = %d AND hostname = '%s';",
p.Servers[index].HostgroupID,
p.Servers[index].Hostname,
)
result, _ := p.Connection.Query(sql)

return ((len(result) == 1) && (cast.StringToInt(result[0]["cnt"]) == 1))
}

func (p *ProxySQL) DeleteServer(index int) {
sql := fmt.Sprintf(
"DELETE FROM mysql_servers WHERE hostgroup_id = %d AND hostname = '%s';",
p.Servers[index].HostgroupID,
p.Servers[index].Hostname,
)
p.Connection.Query(sql)
}

func (p *ProxySQL) InsertServer(index int) {
sql := fmt.Sprintf(
"INSERT INTO mysql_servers (hostgroup_id, hostname, status, max_connections, weight, max_replication_lag, comment) VALUES (%d, '%s', '%s', %d, %d, %d, 'Managed by DeBeAndo');",
p.Servers[index].HostgroupID,
p.Servers[index].Hostname,
ONLINE,
p.Servers[index].MaxConnections,
p.Servers[index].Weight,
p.Servers[index].MaxReplicationLag,
)

p.Connection.Query(sql)
}

func (p *ProxySQL) EnableServer(index int) {
if p.ExistServer(index) && p.GetStatusServer(index) == OFFLINE_HARD {
p.DeleteServer(index)
p.InsertServer(index)
}

if p.ExistServer(index) && p.GetStatusServer(index) == OFFLINE_SOFT {
p.SetStatusServer(index, ONLINE)
}

if !p.ExistServer(index) {

p.InsertServer(index)
}

p.LoadServers()
p.SaveServers()
}

func (p *ProxySQL) DisableServer(index int) error {
var cntQueries int
var stats map[string]string

p.SetStatusServer(0, OFFLINE_SOFT)
p.LoadServers()
p.SaveServers()

time.Sleep(300000)

p.StatConnectionPoolReset()
stats = p.StatConnectionPool(0)
cntQueries += cast.StringToInt(stats["Queries"])

time.Sleep(60000)

stats = p.StatConnectionPool(0)
cntQueries += cast.StringToInt(stats["Queries"])

if cntQueries > 0 {
return errors.New("Active connections on MySQL replica.")
}
return nil
}

func (p *ProxySQL) LoadServers() {
p.Connection.Query("LOAD MYSQL SERVERS TO RUNTIME;")
}

func (p *ProxySQL) SaveServers() {
p.Connection.Query("SAVE MYSQL SERVERS TO DISK;")
}

func (p *ProxySQL) StatConnectionPoolReset() {
p.Connection.Query("SELECT * FROM stats_mysql_connection_pool_reset;")
Servers Servers
Stats Stats
}

func (p *ProxySQL) StatConnectionPool(index int) map[string]string {
sql := fmt.Sprintf(
"SELECT hostgroup, substr(srv_host, 0, instr(srv_host, '.')) AS host, status, ConnUsed, ConnOK, ConnERR, Queries FROM stats_mysql_connection_pool WHERE srv_host = '%s';",
p.Servers[index].Hostname,
)
result, _ := p.Connection.Query(sql)
if len(result) == 1 {
return result[0]
}
return nil
func (p *ProxySQL) AddServer(s Server) {
s.ProxySQL = p
p.Servers.Add(s)
}
40 changes: 40 additions & 0 deletions proxysql/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package proxysql_test

import (
"testing"

"github.com/debeando/go-common/mysql"
"github.com/debeando/go-common/proxysql"

"github.com/stretchr/testify/assert"
)

var p = proxysql.ProxySQL{}

func TestConnection(t *testing.T) {
p = proxysql.ProxySQL{
MySQL: mysql.MySQL{
Host: "127.0.0.1",
Port: 6032,
Username: "radmin",
Password: "radmin",
},
}

p.Connection = mysql.New("proxysql", p.MySQL.DSN())

assert.NoError(t, p.Connection.Connect())
}

func TestAddServer(t *testing.T) {
p.Servers.Reset()
p.AddServer(proxysql.Server{
HostgroupID: 0,
Hostname: "127.0.0.1",
})

assert.Equal(t, p.Servers.Count(), 1)
assert.NotEmpty(t, p.Servers.First().ProxySQL)

p.Servers.Reset()
}
Loading

0 comments on commit 6f2a49c

Please sign in to comment.