Skip to content

Commit

Permalink
feat: diff in gtid info (#112)
Browse files Browse the repository at this point in the history
Co-authored-by: teem0n <[email protected]>
  • Loading branch information
Fizic and teem0n authored Sep 3, 2024
1 parent dd7ca94 commit e62a305
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 5 deletions.
28 changes: 23 additions & 5 deletions internal/app/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/yandex/mysync/internal/mysql"
"github.com/yandex/mysync/internal/mysql/gtids"
)

type appState string
Expand Down Expand Up @@ -128,6 +129,19 @@ func (ns *NodeState) IsReplicationPermanentlyBroken() (bool, int) {
return false, 0
}

func (ns *NodeState) CalcGTIDDiffWithMaster() (string, error) {
if ns.SlaveState == nil {
return "", fmt.Errorf("slave state not defined")
}
replicaGTID := gtids.ParseGtidSet(ns.SlaveState.ExecutedGtidSet)
if ns.MasterState == nil {
return "", fmt.Errorf("master state not defined")
}
sourceGTID := gtids.ParseGtidSet(ns.MasterState.ExecutedGtidSet)

return gtids.GTIDDiff(replicaGTID, sourceGTID)
}

func (ns *NodeState) String() string {
ping := "ok"
if !ns.PingOk {
Expand All @@ -140,17 +154,21 @@ func (ns *NodeState) String() string {
repl := unknown
gtid := unknown
lag := 0.0
if ns.MasterState != nil {
repl = "master"
gtid = strings.ReplaceAll(ns.MasterState.ExecutedGtidSet, "\n", "")
} else if ns.SlaveState != nil {
if ns.SlaveState != nil {
repl = ns.SlaveState.ReplicationState
gtid = strings.ReplaceAll(ns.SlaveState.ExecutedGtidSet, "\n", "")
var err error
gtid, err = ns.CalcGTIDDiffWithMaster()
if err != nil {
gtid = fmt.Sprintf("%s", err)
}
if ns.SlaveState.ReplicationLag != nil {
lag = *ns.SlaveState.ReplicationLag
} else {
lag = math.NaN()
}
} else if ns.MasterState != nil {
repl = "master"
gtid = strings.ReplaceAll(ns.MasterState.ExecutedGtidSet, "\n", "")
}
sync := unknown
if ns.SemiSyncState != nil {
Expand Down
9 changes: 9 additions & 0 deletions internal/app/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,15 @@ func getNodeStatesInParallel(hosts []string, getter func(string) (*NodeState, er
if err != nil {
return nil, err
}

// adding information about source to each replica
for host := range clusterState {
if clusterState[host].SlaveState == nil {
continue
}
masterHost := clusterState[host].SlaveState.MasterHost
clusterState[host].MasterState = clusterState[masterHost].MasterState
}
return clusterState, nil
}

Expand Down
38 changes: 38 additions & 0 deletions internal/mysql/gtids/wrapper.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package gtids

import (
"fmt"

"github.com/go-mysql-org/go-mysql/mysql"
)

Expand All @@ -13,3 +15,39 @@ func ParseGtidSet(gtidset string) GTIDSet {
}
return parsed
}

func GTIDDiff(replicaGTIDSet, sourceGTIDSet mysql.GTIDSet) (string, error) {
mysqlReplicaGTIDSet := replicaGTIDSet.(*mysql.MysqlGTIDSet)
mysqlSourceGTIDSet := sourceGTIDSet.(*mysql.MysqlGTIDSet)
// check standard case
diffWithSource := mysqlSourceGTIDSet.Clone().(*mysql.MysqlGTIDSet)
err := diffWithSource.Minus(*mysqlReplicaGTIDSet)
if err != nil {
return "", err
}

// check reverse case
diffWithReplica := mysqlReplicaGTIDSet.Clone().(*mysql.MysqlGTIDSet)
err = diffWithReplica.Minus(*mysqlSourceGTIDSet)
if err != nil {
return "", err
}

if diffWithSource.String() == "" && diffWithReplica.String() == "" {
return "replica gtid equal source", nil
}

if diffWithSource.String() != "" && diffWithReplica.String() == "" {
return fmt.Sprintf("source ahead on: %s", diffWithSource.String()), nil
}

if diffWithSource.String() != "" && diffWithReplica.String() != "" {
return fmt.Sprintf("split brain! source ahead on: %s; replica ahead on: %s", diffWithSource.String(), diffWithReplica.String()), nil
}

if diffWithSource.String() == "" && diffWithReplica.String() != "" {
return fmt.Sprintf("replica ahead on: %s", diffWithReplica.String()), nil
}

return "", fmt.Errorf("an indefinite case was obtained")
}
50 changes: 50 additions & 0 deletions internal/mysql/gtids/wrapper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package gtids

import (
"testing"

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

func TestGTIDDiff(t *testing.T) {
sourceGTID := ParseGtidSet("00000000-0000-0000-0000-000000000000:1-100,11111111-1111-1111-1111-111111111111:1-100")

// equal
replicaGTID := ParseGtidSet("00000000-0000-0000-0000-000000000000:1-100,11111111-1111-1111-1111-111111111111:1-100")
diff, err := GTIDDiff(replicaGTID, sourceGTID)
require.NoError(t, err)
require.Equal(t, "replica gtid equal source", diff)

replicaGTID = ParseGtidSet("11111111-1111-1111-1111-111111111111:1-100,00000000-0000-0000-0000-000000000000:1-100")
diff, err = GTIDDiff(replicaGTID, sourceGTID)
require.NoError(t, err)
require.Equal(t, "replica gtid equal source", diff)

// source ahead
replicaGTID = ParseGtidSet("00000000-0000-0000-0000-000000000000:1-90,11111111-1111-1111-1111-111111111111:1-100")
diff, err = GTIDDiff(replicaGTID, sourceGTID)
require.NoError(t, err)
require.Equal(t, "source ahead on: 00000000-0000-0000-0000-000000000000:91-100", diff)

replicaGTID = ParseGtidSet("00000000-0000-0000-0000-000000000000:1-90,11111111-1111-1111-1111-111111111111:1-90")
diff, err = GTIDDiff(replicaGTID, sourceGTID)
require.NoError(t, err)
require.Equal(t, "source ahead on: 00000000-0000-0000-0000-000000000000:91-100,11111111-1111-1111-1111-111111111111:91-100", diff)

// replica ahead
replicaGTID = ParseGtidSet("00000000-0000-0000-0000-000000000000:1-110,11111111-1111-1111-1111-111111111111:1-100")
diff, err = GTIDDiff(replicaGTID, sourceGTID)
require.NoError(t, err)
require.Equal(t, "replica ahead on: 00000000-0000-0000-0000-000000000000:101-110", diff)

// split brain
replicaGTID = ParseGtidSet("00000000-0000-0000-0000-000000000000:1-90,11111111-1111-1111-1111-111111111111:1-110")
diff, err = GTIDDiff(replicaGTID, sourceGTID)
require.NoError(t, err)
require.Equal(t, "split brain! source ahead on: 00000000-0000-0000-0000-000000000000:91-100; replica ahead on: 11111111-1111-1111-1111-111111111111:101-110", diff)

replicaGTID = ParseGtidSet("00000000-0000-0000-0000-000000000000:1-100,22222222-2222-2222-2222-222222222222:1-110")
diff, err = GTIDDiff(replicaGTID, sourceGTID)
require.NoError(t, err)
require.Equal(t, "split brain! source ahead on: 11111111-1111-1111-1111-111111111111:1-100; replica ahead on: 22222222-2222-2222-2222-222222222222:1-110", diff)
}

0 comments on commit e62a305

Please sign in to comment.