Skip to content

Commit 703b79f

Browse files
author
Nicola Strappazzon C
committed
refact - proxysql with tests
1 parent 1ebf748 commit 703b79f

13 files changed

+487
-194
lines changed

.github/workflows/go.yml

+22-17
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,33 @@ env:
77
MYSQL_TEST_PASS: test
88
MYSQL_TEST_ADDR: 127.0.0.1:3306
99
MYSQL_TEST_CONCURRENT: 1
10+
PROXYSQL_TEST_ADDR: 127.0.0.1:3307
11+
PROXYSQL_ADMIN_TEST_ADDR: 127.0.0.1:6032
1012

1113
jobs:
1214
test:
1315
name: Check code quality and run tests
1416
runs-on: ubuntu-latest
17+
services:
18+
mysql:
19+
image: mysql:8.0
20+
env:
21+
MYSQL_ROOT_PASSWORD: ${{ env.MYSQL_TEST_PASS }}
22+
MYSQL_USER: ${{ env.MYSQL_TEST_USER }}
23+
MYSQL_PASSWORD: ${{ env.MYSQL_TEST_PASS }}
24+
ports:
25+
- 3306:3306
26+
options: >-
27+
--health-cmd "mysqladmin ping"
28+
--health-interval 10s
29+
--health-timeout 5s
30+
--health-retries 10
31+
proxysql:
32+
image: ghcr.io/debeando/docker-proxysql
33+
ports:
34+
- 3307:3306
35+
- 6032:6032
36+
1537
steps:
1638
- uses: actions/checkout@v3
1739

@@ -20,23 +42,6 @@ jobs:
2042
with:
2143
go-version: 1.21
2244

23-
- name: Setup MySQL Server
24-
uses: shogo82148/actions-setup-mysql@v1.21.0
25-
with:
26-
mysql-version: 8.0
27-
user: ${{ env.MYSQL_TEST_USER }}
28-
password: ${{ env.MYSQL_TEST_PASS }}
29-
my-cnf: |
30-
innodb_log_file_size=256MB
31-
innodb_buffer_pool_size=512MB
32-
max_allowed_packet=16MB
33-
max_connections=50
34-
local_infile=1
35-
performance_schema=on
36-
37-
- name: Setup database
38-
run: mysql --user 'root' --host '127.0.0.1' -e 'CREATE DATABASE gotest;'
39-
4045
- name: Get all dependencies
4146
run: go get -u ./...
4247

go.mod

+3-4
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@ go 1.19
55
require (
66
github.com/ClickHouse/clickhouse-go/v2 v2.14.2
77
github.com/aws/aws-sdk-go v1.44.319
8-
github.com/debeando/zenit v1.4.5
8+
github.com/fatih/color v1.15.0
99
github.com/go-sql-driver/mysql v1.7.1
1010
github.com/google/uuid v1.3.1
1111
github.com/hpcloud/tail v1.0.0
1212
github.com/sirupsen/logrus v1.9.3
1313
github.com/stretchr/testify v1.8.4
1414
go.mongodb.org/mongo-driver v1.12.1
15+
golang.org/x/sys v0.14.0
1516
)
1617

1718
require (
1819
github.com/ClickHouse/ch-go v0.58.2 // indirect
1920
github.com/andybalholm/brotli v1.0.5 // indirect
2021
github.com/davecgh/go-spew v1.1.1 // indirect
21-
github.com/fatih/color v1.15.0 // indirect
22+
github.com/fsnotify/fsnotify v1.7.0 // indirect
2223
github.com/go-faster/city v1.0.1 // indirect
2324
github.com/go-faster/errors v0.6.1 // indirect
2425
github.com/golang/snappy v0.0.1 // indirect
@@ -31,7 +32,6 @@ require (
3132
github.com/pierrec/lz4/v4 v4.1.18 // indirect
3233
github.com/pkg/errors v0.9.1 // indirect
3334
github.com/pmezard/go-difflib v1.0.0 // indirect
34-
github.com/rodaine/table v1.1.0 // indirect
3535
github.com/segmentio/asm v1.2.0 // indirect
3636
github.com/shopspring/decimal v1.3.1 // indirect
3737
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
@@ -42,7 +42,6 @@ require (
4242
go.opentelemetry.io/otel/trace v1.19.0 // indirect
4343
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
4444
golang.org/x/sync v0.3.0 // indirect
45-
golang.org/x/sys v0.14.0 // indirect
4645
golang.org/x/text v0.7.0 // indirect
4746
gopkg.in/fsnotify.v1 v1.4.7 // indirect
4847
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect

go.sum

+2-9
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ github.com/aws/aws-sdk-go v1.44.319/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8
99
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1010
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1111
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12-
github.com/debeando/zenit v1.4.5 h1:3qecmh8v2KT2llPA96r9PEBEMWZAZ8EdWEywwzUab6o=
13-
github.com/debeando/zenit v1.4.5/go.mod h1:SQy1dXrENEK+kOQRguYYj7edS6k9SLNGKWO/SO3p+CY=
1412
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
1513
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
16-
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
14+
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
15+
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
1716
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
1817
github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=
1918
github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI=
@@ -27,7 +26,6 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
2726
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
2827
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
2928
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
30-
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
3129
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
3230
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
3331
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
@@ -51,7 +49,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
5149
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
5250
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
5351
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
54-
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
5552
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
5653
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
5754
github.com/paulmach/orb v0.10.0 h1:guVYVqzxHE/CQ1KpfGO077TR0ATHSNjp4s6XGLn3W9s=
@@ -63,8 +60,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
6360
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
6461
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6562
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
66-
github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4=
67-
github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g=
6863
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
6964
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
7065
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
@@ -133,8 +128,6 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
133128
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
134129
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
135130
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
136-
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
137-
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
138131
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
139132
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
140133
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

mysql/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ func (c *Connection) FetchOne(query string) any {
150150
return val
151151
}
152152

153+
// QueryIterator
153154
func (c *Connection) FetchAll(query string, fn func(map[string]string)) error {
154155
if c.Instance == nil {
155156
return errors.New("The instance is empty.")

mysql/sql/insert_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package sql_test
33
import (
44
"testing"
55

6-
"github.com/debeando/zenit/common/sql"
6+
"github.com/debeando/go-common/mysql/sql"
77
)
88

99
func TestEmpty(t *testing.T) {

proxysql/main.go

+6-163
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
package proxysql
22

33
import (
4-
"errors"
5-
"fmt"
6-
7-
"github.com/debeando/go-common/cast"
84
"github.com/debeando/go-common/mysql"
9-
"github.com/debeando/go-common/time"
105
)
116

127
const (
@@ -18,165 +13,13 @@ const (
1813
)
1914

2015
type ProxySQL struct {
16+
mysql.MySQL
2117
Connection *mysql.Connection
22-
Host string `yaml:"host"`
23-
Password string `yaml:"password"`
24-
Port uint16 `yaml:"port"`
25-
Schema string `yaml:"schema"`
26-
Servers []Server `yaml:"servers"`
27-
Status string `yaml:"status"`
28-
Timeout uint8 `yaml:"timeout"`
29-
Username string `yaml:"username"`
30-
}
31-
32-
type Server struct {
33-
HostgroupID uint8 `yaml:"hostgroup_id"`
34-
Hostname string `yaml:"hostname"`
35-
MaxConnections uint16 `yaml:"max_connections"`
36-
MaxReplicationLag uint16 `yaml:"max_replication_lag"`
37-
Status string `yaml:"status"`
38-
Weight uint16 `yaml:"weight"`
39-
}
40-
41-
func (p *ProxySQL) AddServer(s Server) int {
42-
p.Servers = append(p.Servers, s)
43-
44-
return 0
45-
}
46-
47-
func (p *ProxySQL) DSN() string {
48-
return fmt.Sprintf(
49-
"%s:%s@tcp(%s:%d)/?timeout=%ds",
50-
p.Username,
51-
p.Password,
52-
p.Host,
53-
p.Port,
54-
p.Timeout,
55-
)
56-
}
57-
58-
func (p *ProxySQL) GetStatusServer(index int) string {
59-
sql := fmt.Sprintf(
60-
"SELECT status FROM mysql_servers WHERE hostgroup_id = %d AND hostname = '%s' LIMIT 1;",
61-
p.Servers[index].HostgroupID,
62-
p.Servers[index].Hostname,
63-
)
64-
result, _ := p.Connection.Query(sql)
65-
66-
if len(result) == 1 {
67-
return result[0]["status"]
68-
}
69-
return ServerStatus
70-
}
71-
72-
func (p *ProxySQL) SetStatusServer(index int, ss string) {
73-
sql := fmt.Sprintf(
74-
"UPDATE mysql_servers SET status = '%s' WHERE hostgroup_id = %d AND hostname = '%s';",
75-
ss,
76-
p.Servers[index].HostgroupID,
77-
p.Servers[index].Hostname,
78-
)
79-
p.Connection.Query(sql)
80-
}
81-
82-
func (p *ProxySQL) ExistServer(index int) bool {
83-
sql := fmt.Sprintf(
84-
"SELECT count() AS cnt FROM mysql_servers WHERE hostgroup_id = %d AND hostname = '%s';",
85-
p.Servers[index].HostgroupID,
86-
p.Servers[index].Hostname,
87-
)
88-
result, _ := p.Connection.Query(sql)
89-
90-
return ((len(result) == 1) && (cast.StringToInt(result[0]["cnt"]) == 1))
91-
}
92-
93-
func (p *ProxySQL) DeleteServer(index int) {
94-
sql := fmt.Sprintf(
95-
"DELETE FROM mysql_servers WHERE hostgroup_id = %d AND hostname = '%s';",
96-
p.Servers[index].HostgroupID,
97-
p.Servers[index].Hostname,
98-
)
99-
p.Connection.Query(sql)
100-
}
101-
102-
func (p *ProxySQL) InsertServer(index int) {
103-
sql := fmt.Sprintf(
104-
"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');",
105-
p.Servers[index].HostgroupID,
106-
p.Servers[index].Hostname,
107-
ONLINE,
108-
p.Servers[index].MaxConnections,
109-
p.Servers[index].Weight,
110-
p.Servers[index].MaxReplicationLag,
111-
)
112-
113-
p.Connection.Query(sql)
114-
}
115-
116-
func (p *ProxySQL) EnableServer(index int) {
117-
if p.ExistServer(index) && p.GetStatusServer(index) == OFFLINE_HARD {
118-
p.DeleteServer(index)
119-
p.InsertServer(index)
120-
}
121-
122-
if p.ExistServer(index) && p.GetStatusServer(index) == OFFLINE_SOFT {
123-
p.SetStatusServer(index, ONLINE)
124-
}
125-
126-
if !p.ExistServer(index) {
127-
128-
p.InsertServer(index)
129-
}
130-
131-
p.LoadServers()
132-
p.SaveServers()
133-
}
134-
135-
func (p *ProxySQL) DisableServer(index int) error {
136-
var cntQueries int
137-
var stats map[string]string
138-
139-
p.SetStatusServer(0, OFFLINE_SOFT)
140-
p.LoadServers()
141-
p.SaveServers()
142-
143-
time.Sleep(300000)
144-
145-
p.StatConnectionPoolReset()
146-
stats = p.StatConnectionPool(0)
147-
cntQueries += cast.StringToInt(stats["Queries"])
148-
149-
time.Sleep(60000)
150-
151-
stats = p.StatConnectionPool(0)
152-
cntQueries += cast.StringToInt(stats["Queries"])
153-
154-
if cntQueries > 0 {
155-
return errors.New("Active connections on MySQL replica.")
156-
}
157-
return nil
158-
}
159-
160-
func (p *ProxySQL) LoadServers() {
161-
p.Connection.Query("LOAD MYSQL SERVERS TO RUNTIME;")
162-
}
163-
164-
func (p *ProxySQL) SaveServers() {
165-
p.Connection.Query("SAVE MYSQL SERVERS TO DISK;")
166-
}
167-
168-
func (p *ProxySQL) StatConnectionPoolReset() {
169-
p.Connection.Query("SELECT * FROM stats_mysql_connection_pool_reset;")
18+
Servers Servers
19+
Stats Stats
17020
}
17121

172-
func (p *ProxySQL) StatConnectionPool(index int) map[string]string {
173-
sql := fmt.Sprintf(
174-
"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';",
175-
p.Servers[index].Hostname,
176-
)
177-
result, _ := p.Connection.Query(sql)
178-
if len(result) == 1 {
179-
return result[0]
180-
}
181-
return nil
22+
func (p *ProxySQL) AddServer(s Server) {
23+
s.ProxySQL = p
24+
p.Servers.Add(s)
18225
}

proxysql/main_test.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package proxysql_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/debeando/go-common/mysql"
7+
"github.com/debeando/go-common/proxysql"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
var p = proxysql.ProxySQL{}
13+
14+
func TestConnection(t *testing.T) {
15+
p = proxysql.ProxySQL{
16+
MySQL: mysql.MySQL{
17+
Host: "127.0.0.1",
18+
Port: 6032,
19+
Username: "radmin",
20+
Password: "radmin",
21+
},
22+
}
23+
24+
p.Connection = mysql.New("proxysql", p.MySQL.DSN())
25+
26+
assert.NoError(t, p.Connection.Connect())
27+
}
28+
29+
func TestAddServer(t *testing.T) {
30+
p.Servers.Reset()
31+
p.AddServer(proxysql.Server{
32+
HostgroupID: 0,
33+
Hostname: "127.0.0.1",
34+
})
35+
36+
assert.Equal(t, p.Servers.Count(), 1)
37+
assert.NotEmpty(t, p.Servers.First().ProxySQL)
38+
39+
p.Servers.Reset()
40+
}

0 commit comments

Comments
 (0)