Skip to content

Commit 435c726

Browse files
Merge pull request #118 from github/vitess-check-replicas-only
Gather REPLICA tablet types from Vitess only
2 parents 32efe2d + 6b90452 commit 435c726

File tree

4 files changed

+112
-4
lines changed

4 files changed

+112
-4
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ require (
1313
github.com/patrickmn/go-cache v2.1.0+incompatible
1414
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563
1515
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed // indirect
16+
vitess.io/vitess v2.1.1+incompatible
1617
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp
1111
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1212
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
1313
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
14+
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
1415
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
1516
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
1617
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
@@ -45,6 +46,9 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
4546
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
4647
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
4748
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
49+
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
4850
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4951
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed h1:uPxWBzB3+mlnjy9W58qY1j/cjyFjutgw/Vhan2zLy/A=
5052
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
53+
vitess.io/vitess v2.1.1+incompatible h1:nuuGHiWYWpudD3gOCLeGzol2EJ25e/u5Wer2wV1O130=
54+
vitess.io/vitess v2.1.1+incompatible/go.mod h1:h4qvkyNYTOC0xI+vcidSWoka0gQAZc9ZPHbkHo48gP0=

pkg/vitess/api_client.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,20 @@ import (
77
"net/http"
88
"strings"
99
"time"
10+
11+
"vitess.io/vitess/go/vt/proto/topodata"
1012
)
1113

1214
// Tablet represents information about a running instance of vttablet.
1315
type Tablet struct {
14-
MysqlHostname string `json:"mysql_hostname,omitempty"`
15-
MysqlPort int32 `json:"mysql_port,omitempty"`
16+
MysqlHostname string `json:"mysql_hostname,omitempty"`
17+
MysqlPort int32 `json:"mysql_port,omitempty"`
18+
Type topodata.TabletType `json:"type,omitempty"`
19+
}
20+
21+
// IsValidReplica returns a bool reflecting if a tablet type is REPLICA
22+
func (t Tablet) IsValidReplica() bool {
23+
return t.Type == topodata.TabletType_REPLICA
1624
}
1725

1826
var httpClient = http.Client{
@@ -29,8 +37,18 @@ func constructAPIURL(api string, keyspace string, shard string) (url string) {
2937
return url
3038
}
3139

40+
// filterReplicaTablets parses a list of tablets, returning replica tablets only
41+
func filterReplicaTablets(tablets []Tablet) (replicas []Tablet) {
42+
for _, tablet := range tablets {
43+
if tablet.IsValidReplica() {
44+
replicas = append(replicas, tablet)
45+
}
46+
}
47+
return replicas
48+
}
49+
3250
// ParseTablets reads from vitess /api/ks_tablets/<keyspace>/[shard] and returns a
33-
// tblet (mysql_hostname, mysql_port) listing
51+
// listing (mysql_hostname, mysql_port, type) of REPLICA tablets
3452
func ParseTablets(api string, keyspace string, shard string) (tablets []Tablet, err error) {
3553
url := constructAPIURL(api, keyspace, shard)
3654
resp, err := httpClient.Get(url)
@@ -45,5 +63,5 @@ func ParseTablets(api string, keyspace string, shard string) (tablets []Tablet,
4563
}
4664

4765
err = json.Unmarshal(body, &tablets)
48-
return tablets, err
66+
return filterReplicaTablets(tablets), err
4967
}

pkg/vitess/api_client_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package vitess
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"net/http/httptest"
8+
"testing"
9+
10+
"vitess.io/vitess/go/vt/proto/topodata"
11+
)
12+
13+
func TestParseTablets(t *testing.T) {
14+
vitessApi := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
15+
switch r.URL.String() {
16+
case "/api/keyspace/test/tablets/00":
17+
data, _ := json.Marshal([]Tablet{
18+
{
19+
MysqlHostname: "master",
20+
Type: topodata.TabletType_MASTER,
21+
},
22+
{
23+
MysqlHostname: "replica",
24+
Type: topodata.TabletType_REPLICA,
25+
},
26+
{
27+
MysqlHostname: "spare",
28+
Type: topodata.TabletType_SPARE,
29+
},
30+
{
31+
MysqlHostname: "batch",
32+
Type: topodata.TabletType_BATCH,
33+
},
34+
{
35+
MysqlHostname: "backup",
36+
Type: topodata.TabletType_BACKUP,
37+
},
38+
{
39+
40+
MysqlHostname: "restore",
41+
Type: topodata.TabletType_RESTORE,
42+
},
43+
})
44+
fmt.Fprint(w, string(data))
45+
default:
46+
w.WriteHeader(http.StatusNotFound)
47+
fmt.Fprint(w, "[]")
48+
}
49+
}))
50+
defer vitessApi.Close()
51+
52+
t.Run("success", func(t *testing.T) {
53+
tablets, err := ParseTablets(vitessApi.URL, "test", "00")
54+
if err != nil {
55+
t.Fatalf("Expected no error, got %q", err)
56+
}
57+
58+
if len(tablets) != 1 {
59+
t.Fatalf("Expected 1 tablet, got %d", len(tablets))
60+
}
61+
62+
if tablets[0].MysqlHostname != "replica" {
63+
t.Fatalf("Expected hostname %q, got %q", "replica", tablets[0].MysqlHostname)
64+
}
65+
})
66+
67+
t.Run("not-found", func(t *testing.T) {
68+
tablets, err := ParseTablets(vitessApi.URL, "not-found", "00")
69+
if err != nil {
70+
t.Fatalf("Expected no error, got %q", err)
71+
}
72+
73+
if len(tablets) > 0 {
74+
t.Fatalf("Expected 0 tablets, got %d", len(tablets))
75+
}
76+
})
77+
78+
t.Run("failed", func(t *testing.T) {
79+
vitessApi.Close() // kill the mock vitess API
80+
_, err := ParseTablets(vitessApi.URL, "fail", "00")
81+
if err == nil {
82+
t.Fatal("Expected error, got nil")
83+
}
84+
})
85+
}

0 commit comments

Comments
 (0)