Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go/vt/external/golib/sqlutils/sqlutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
"vitess.io/vitess/go/vt/log"
)

const DateTimeFormat = "2006-01-02 15:04:05.999999"
const DateTimeFormat = "2006-01-02 15:04:05.999999 +0000 UTC"

// RowMap represents one row in a result set. Its objective is to allow
// for easy, typed getters by column name.
Expand Down
5 changes: 3 additions & 2 deletions go/vt/external/golib/sqlutils/sqlutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
)

func TestRowMap(t *testing.T) {
getTimeExpected := time.Date(2024, time.January, 24, 12, 34, 56, 789000000, time.UTC)
tt := []struct {
name string
rowMap RowMap
Expand Down Expand Up @@ -82,8 +83,8 @@ func TestRowMap(t *testing.T) {
},
{
"GetTime",
RowMap{"key": CellData{String: "2024-01-24 12:34:56.789"}},
time.Date(2024, time.January, 24, 12, 34, 56, 789000000, time.UTC),
RowMap{"key": CellData{String: getTimeExpected.UTC().String()}},
getTimeExpected,
},
{
"GetTime Error",
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtorc/inst/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ type ReplicationAnalysis struct {
AnalyzedKeyspace string
AnalyzedShard string
// ShardPrimaryTermTimestamp is the primary term start time stored in the shard record.
ShardPrimaryTermTimestamp string
ShardPrimaryTermTimestamp time.Time
AnalyzedInstanceBinlogCoordinates BinlogCoordinates
IsPrimary bool
IsClusterPrimary bool
Expand Down
6 changes: 3 additions & 3 deletions go/vt/vtorc/inst/analysis_dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAna
return nil
}

a.ShardPrimaryTermTimestamp = m.GetString("shard_primary_term_timestamp")
a.ShardPrimaryTermTimestamp = m.GetTime("shard_primary_term_timestamp")
a.IsPrimary = m.GetBool("is_primary")
a.AnalyzedInstanceAlias = topoproto.TabletAliasString(tablet.Alias)
a.AnalyzedInstancePrimaryAlias = topoproto.TabletAliasString(primaryTablet.Alias)
Expand Down Expand Up @@ -458,12 +458,12 @@ func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAna
} else if topo.IsReplicaType(a.TabletType) && a.ErrantGTID != "" {
a.Analysis = ErrantGTIDDetected
a.Description = "Tablet has errant GTIDs"
} else if topo.IsReplicaType(a.TabletType) && ca.primaryAlias == "" && a.ShardPrimaryTermTimestamp == "" {
} else if topo.IsReplicaType(a.TabletType) && ca.primaryAlias == "" && a.ShardPrimaryTermTimestamp.IsZero() {
// ClusterHasNoPrimary should only be detected when the shard record doesn't have any primary term start time specified either.
a.Analysis = ClusterHasNoPrimary
a.Description = "Cluster has no primary"
ca.hasClusterwideAction = true
} else if topo.IsReplicaType(a.TabletType) && ca.primaryAlias == "" && a.ShardPrimaryTermTimestamp != "" {
} else if topo.IsReplicaType(a.TabletType) && ca.primaryAlias == "" && !a.ShardPrimaryTermTimestamp.IsZero() {
// If there are no primary tablets, but the shard primary start time isn't empty, then we know
// the primary tablet was deleted.
a.Analysis = PrimaryTabletDeleted
Expand Down
12 changes: 6 additions & 6 deletions go/vt/vtorc/inst/analysis_dao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ var (
`INSERT INTO database_instance VALUES('zone1-0000000100','localhost',6711,2,'zone1','2022-12-28 07:26:04','2022-12-28 07:26:04',1094500338,'8.0.31','ROW',1,1,'vt-0000000100-bin.000001',15963,'localhost',6714,8,4.0,1,1,'vt-0000000101-bin.000001',15583,'vt-0000000101-bin.000001',15583,0,0,1,'','',1,'vt-0000000100-relay-bin.000002',15815,1,0,0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a5138-8680-11ed-acf8-d6b0ef9f4eaa','2022-12-28 07:26:04','',1,0,0,'Homebrew','8.0','FULL',10103920,0,1,'ON',1,'729a4cc4-8680-11ed-a104-47706090afbd','','729a4cc4-8680-11ed-a104-47706090afbd,729a5138-8680-11ed-acf8-d6b0ef9f4eaa',1,1,1000000000000000000,1,0,1,0,false,false);`,
`INSERT INTO database_instance VALUES('zone1-0000000101','localhost',6714,1,'zone1','2022-12-28 07:26:04','2022-12-28 07:26:04',390954723,'8.0.31','ROW',1,1,'vt-0000000101-bin.000001',15583,'',0,0,0,0,0,'',0,'',0,NULL,NULL,0,'','',0,'',0,0,0,0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a4cc4-8680-11ed-a104-47706090afbd','2022-12-28 07:26:04','',0,0,0,'Homebrew','8.0','FULL',11366095,1,1,'ON',1,'','','729a4cc4-8680-11ed-a104-47706090afbd',-1,-1,1000000000000000000,1,1,0,2,false,false);`,
`INSERT INTO database_instance VALUES('zone2-0000000200','localhost',6756,2,'zone2','2022-12-28 07:26:05','2022-12-28 07:26:05',444286571,'8.0.31','ROW',1,1,'vt-0000000200-bin.000001',15963,'localhost',6714,8,4.0,1,1,'vt-0000000101-bin.000001',15583,'vt-0000000101-bin.000001',15583,0,0,1,'','',1,'vt-0000000200-relay-bin.000002',15815,1,0,0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a497c-8680-11ed-8ad4-3f51d747db75','2022-12-28 07:26:05','',1,0,0,'Homebrew','8.0','FULL',10443112,0,1,'ON',1,'729a4cc4-8680-11ed-a104-47706090afbd','','729a4cc4-8680-11ed-a104-47706090afbd,729a497c-8680-11ed-8ad4-3f51d747db75',1,1,1000000000000000000,1,0,1,0,false,false);`,
`INSERT INTO vitess_tablet VALUES('zone1-0000000100','localhost',6711,'ks','0','zone1',2,'0001-01-01 00:00:00+00:00',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3130307d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363731307d20706f72745f6d61703a7b6b65793a227674222076616c75653a363730397d206b657973706163653a226b73222073686172643a22302220747970653a5245504c494341206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363731312064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`,
`INSERT INTO vitess_tablet VALUES('zone1-0000000101','localhost',6714,'ks','0','zone1',1,'2022-12-28 07:23:25.129898+00:00',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3130317d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363731337d20706f72745f6d61703a7b6b65793a227674222076616c75653a363731327d206b657973706163653a226b73222073686172643a22302220747970653a5052494d415259206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a36373134207072696d6172795f7465726d5f73746172745f74696d653a7b7365636f6e64733a31363732323132323035206e616e6f7365636f6e64733a3132393839383030307d2064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`,
`INSERT INTO vitess_tablet VALUES('zone1-0000000112','localhost',6747,'ks','0','zone1',3,'0001-01-01 00:00:00+00:00',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3131327d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363734367d20706f72745f6d61703a7b6b65793a227674222076616c75653a363734357d206b657973706163653a226b73222073686172643a22302220747970653a52444f4e4c59206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363734372064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`,
`INSERT INTO vitess_tablet VALUES('zone2-0000000200','localhost',6756,'ks','0','zone2',2,'0001-01-01 00:00:00+00:00',X'616c6961733a7b63656c6c3a227a6f6e653222207569643a3230307d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363735357d20706f72745f6d61703a7b6b65793a227674222076616c75653a363735347d206b657973706163653a226b73222073686172643a22302220747970653a5245504c494341206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363735362064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`,
`INSERT INTO vitess_shard VALUES('ks','0','zone1-0000000101','2022-12-28 07:23:25.129898+00:00');`,
`INSERT INTO vitess_tablet VALUES('zone1-0000000100','localhost',6711,'ks','0','zone1',2,'0001-01-01 00:00:00 +0000 UTC',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3130307d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363731307d20706f72745f6d61703a7b6b65793a227674222076616c75653a363730397d206b657973706163653a226b73222073686172643a22302220747970653a5245504c494341206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363731312064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`,
`INSERT INTO vitess_tablet VALUES('zone1-0000000101','localhost',6714,'ks','0','zone1',1,'2022-12-28 07:23:25.129898 +0000 UTC',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3130317d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363731337d20706f72745f6d61703a7b6b65793a227674222076616c75653a363731327d206b657973706163653a226b73222073686172643a22302220747970653a5052494d415259206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a36373134207072696d6172795f7465726d5f73746172745f74696d653a7b7365636f6e64733a31363732323132323035206e616e6f7365636f6e64733a3132393839383030307d2064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`,
`INSERT INTO vitess_tablet VALUES('zone1-0000000112','localhost',6747,'ks','0','zone1',3,'0001-01-01 00:00:00 +0000 UTC',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3131327d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363734367d20706f72745f6d61703a7b6b65793a227674222076616c75653a363734357d206b657973706163653a226b73222073686172643a22302220747970653a52444f4e4c59206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363734372064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`,
`INSERT INTO vitess_tablet VALUES('zone2-0000000200','localhost',6756,'ks','0','zone2',2,'0001-01-01 00:00:00 +0000 UTC',X'616c6961733a7b63656c6c3a227a6f6e653222207569643a3230307d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363735357d20706f72745f6d61703a7b6b65793a227674222076616c75653a363735347d206b657973706163653a226b73222073686172643a22302220747970653a5245504c494341206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363735362064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`,
`INSERT INTO vitess_shard VALUES('ks','0','zone1-0000000101','2025-06-25 23:48:57.306096 +0000 UTC');`,
`INSERT INTO vitess_keyspace VALUES('ks',0,'semi_sync');`,
}
)
Expand Down Expand Up @@ -89,7 +89,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) {
MysqlHostname: "localhost",
MysqlPort: 6709,
},
ShardPrimaryTermTimestamp: "2022-12-28 07:23:25.129898+00:00",
ShardPrimaryTermTimestamp: "2022-12-28 07:23:25.129898 +0000 UTC",
DurabilityPolicy: policy.DurabilityNone,
LastCheckValid: 1,
}},
Expand Down
29 changes: 15 additions & 14 deletions go/vt/vtorc/inst/shard_dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package inst

import (
"errors"
"time"

"vitess.io/vitess/go/protoutil"
"vitess.io/vitess/go/vt/external/golib/sqlutils"
Expand All @@ -42,36 +43,36 @@ func ReadShardNames(keyspaceName string) (shardNames []string, err error) {
}

// ReadShardPrimaryInformation reads the vitess shard record and gets the shard primary alias and timestamp.
func ReadShardPrimaryInformation(keyspaceName, shardName string) (primaryAlias string, primaryTimestamp string, err error) {
func ReadShardPrimaryInformation(keyspaceName, shardName string) (primaryAlias string, primaryTimestamp time.Time, err error) {
if err = topo.ValidateKeyspaceName(keyspaceName); err != nil {
return
}
if _, _, err = topo.ValidateShardName(shardName); err != nil {
return
}

query := `
select
query := `SELECT
primary_alias, primary_timestamp
from
FROM
vitess_shard
where keyspace=? and shard=?
`
WHERE
keyspace = ?
AND shard = ?`
args := sqlutils.Args(keyspaceName, shardName)
shardFound := false
err = db.QueryVTOrc(query, args, func(row sqlutils.RowMap) error {
shardFound = true
primaryAlias = row.GetString("primary_alias")
primaryTimestamp = row.GetString("primary_timestamp")
primaryTimestamp = row.GetTime("primary_timestamp")
return nil
})
if err != nil {
return
}
if !shardFound {
return "", "", ErrShardNotFound
err = ErrShardNotFound
}
return primaryAlias, primaryTimestamp, nil
return primaryAlias, primaryTimestamp, err
}

// SaveShard saves the shard record against the shard name.
Expand All @@ -87,7 +88,7 @@ func SaveShard(shard *topo.ShardInfo) error {
shard.Keyspace(),
shard.ShardName(),
getShardPrimaryAliasString(shard),
getShardPrimaryTermStartTimeString(shard),
getShardPrimaryTermStartTime(shard),
)
return err
}
Expand All @@ -100,12 +101,12 @@ func getShardPrimaryAliasString(shard *topo.ShardInfo) string {
return topoproto.TabletAliasString(shard.PrimaryAlias)
}

// getShardPrimaryAliasString gets the shard primary term start time to be stored as a string in the database.
func getShardPrimaryTermStartTimeString(shard *topo.ShardInfo) string {
// getShardPrimaryTermStartTime gets the shard primary term start time to be stored as a string in the database.
func getShardPrimaryTermStartTime(shard *topo.ShardInfo) time.Time {
if shard.PrimaryTermStartTime == nil {
return ""
return time.Time{}
}
return protoutil.TimeFromProto(shard.PrimaryTermStartTime).UTC().String()
return protoutil.TimeFromProto(shard.PrimaryTermStartTime).UTC()
}

// DeleteShard deletes a shard using a keyspace and shard name.
Expand Down
8 changes: 4 additions & 4 deletions go/vt/vtorc/inst/shard_dao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestSaveReadAndDeleteShard(t *testing.T) {
shardName string
shard *topodatapb.Shard
primaryAliasWanted string
primaryTimestampWanted string
primaryTimestampWanted time.Time
err string
}{
{
Expand All @@ -54,7 +54,7 @@ func TestSaveReadAndDeleteShard(t *testing.T) {
},
PrimaryTermStartTime: protoutil.TimeToProto(timeToUse.Add(1 * time.Hour)),
},
primaryTimestampWanted: "2023-07-24 06:00:05.000001 +0000 UTC",
primaryTimestampWanted: timeToUse.Add(1 * time.Hour).UTC(),
primaryAliasWanted: "zone1-0000000301",
}, {
name: "Success with empty primary alias",
Expand All @@ -63,7 +63,7 @@ func TestSaveReadAndDeleteShard(t *testing.T) {
shard: &topodatapb.Shard{
PrimaryTermStartTime: protoutil.TimeToProto(timeToUse),
},
primaryTimestampWanted: "2023-07-24 05:00:05.000001 +0000 UTC",
primaryTimestampWanted: timeToUse.UTC(),
primaryAliasWanted: "",
}, {
name: "Success with empty primary term start time",
Expand All @@ -75,7 +75,7 @@ func TestSaveReadAndDeleteShard(t *testing.T) {
Uid: 301,
},
},
primaryTimestampWanted: "",
primaryTimestampWanted: time.Time{},
primaryAliasWanted: "zone1-0000000301",
},
{
Expand Down
Loading