Skip to content

Commit 0fc2fe9

Browse files
Merge remote-tracking branch 'upstream/main' into reference-dml-fix
Signed-off-by: Harshit Gangal <harshit@planetscale.com>
2 parents 80523d3 + fa79c3f commit 0fc2fe9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+3490
-2366
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ require (
6868
go.uber.org/mock v0.2.0
6969
golang.org/x/crypto v0.31.0 // indirect
7070
golang.org/x/mod v0.22.0 // indirect
71-
golang.org/x/net v0.31.0
71+
golang.org/x/net v0.33.0
7272
golang.org/x/oauth2 v0.24.0
7373
golang.org/x/sys v0.28.0
7474
golang.org/x/term v0.27.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,8 +660,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
660660
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
661661
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
662662
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
663-
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
664-
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
663+
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
664+
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
665665
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
666666
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
667667
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=

go/cmd/vtctldclient/command/vreplication/vdiff/vdiff.go

Lines changed: 1 addition & 222 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@ limitations under the License.
1717
package vdiff
1818

1919
import (
20-
"encoding/json"
2120
"fmt"
2221
"html/template"
2322
"io"
2423
"math"
2524
"reflect"
26-
"sort"
2725
"strings"
2826
"time"
2927

@@ -579,7 +577,7 @@ func buildRecentListings(resp *vtctldatapb.VDiffShowResponse) ([]*listing, error
579577
func displayShowSingleSummary(out io.Writer, format, keyspace, workflowName, uuid string, resp *vtctldatapb.VDiffShowResponse, verbose bool) (vdiff.VDiffState, error) {
580578
state := vdiff.UnknownState
581579
var output string
582-
summary, err := buildSingleSummary(keyspace, workflowName, uuid, resp, verbose)
580+
summary, err := workflow.BuildSummary(keyspace, workflowName, uuid, resp, verbose)
583581
if err != nil {
584582
return state, err
585583
}
@@ -616,225 +614,6 @@ func displayShowSingleSummary(out io.Writer, format, keyspace, workflowName, uui
616614
return state, nil
617615
}
618616

619-
func buildSingleSummary(keyspace, workflow, uuid string, resp *vtctldatapb.VDiffShowResponse, verbose bool) (*summary, error) {
620-
summary := &summary{
621-
Workflow: workflow,
622-
Keyspace: keyspace,
623-
UUID: uuid,
624-
State: vdiff.UnknownState,
625-
RowsCompared: 0,
626-
StartedAt: "",
627-
CompletedAt: "",
628-
HasMismatch: false,
629-
Shards: "",
630-
Reports: make(map[string]map[string]vdiff.DiffReport),
631-
Errors: make(map[string]string),
632-
Progress: nil,
633-
}
634-
635-
var tableSummaryMap map[string]tableSummary
636-
var reports map[string]map[string]vdiff.DiffReport
637-
// Keep a tally of the states across all tables in all shards.
638-
tableStateCounts := map[vdiff.VDiffState]int{
639-
vdiff.UnknownState: 0,
640-
vdiff.PendingState: 0,
641-
vdiff.StartedState: 0,
642-
vdiff.StoppedState: 0,
643-
vdiff.ErrorState: 0,
644-
vdiff.CompletedState: 0,
645-
}
646-
// Keep a tally of the summary states across all shards.
647-
shardStateCounts := map[vdiff.VDiffState]int{
648-
vdiff.UnknownState: 0,
649-
vdiff.PendingState: 0,
650-
vdiff.StartedState: 0,
651-
vdiff.StoppedState: 0,
652-
vdiff.ErrorState: 0,
653-
vdiff.CompletedState: 0,
654-
}
655-
// Keep a tally of the approximate total rows to process as we'll use this for our progress
656-
// report.
657-
totalRowsToCompare := int64(0)
658-
var shards []string
659-
for shard, resp := range resp.TabletResponses {
660-
first := true
661-
if resp != nil && resp.Output != nil {
662-
shards = append(shards, shard)
663-
qr := sqltypes.Proto3ToResult(resp.Output)
664-
if tableSummaryMap == nil {
665-
tableSummaryMap = make(map[string]tableSummary, 0)
666-
reports = make(map[string]map[string]vdiff.DiffReport, 0)
667-
}
668-
for _, row := range qr.Named().Rows {
669-
// Update the global VDiff summary based on the per shard level summary.
670-
// Since these values will be the same for all subsequent rows we only use
671-
// the first row.
672-
if first {
673-
first = false
674-
// Our timestamps are strings in `2022-06-26 20:43:25` format so we sort
675-
// them lexicographically.
676-
// We should use the earliest started_at across all shards.
677-
if sa := row.AsString("started_at", ""); summary.StartedAt == "" || sa < summary.StartedAt {
678-
summary.StartedAt = sa
679-
}
680-
// And we should use the latest completed_at across all shards.
681-
if ca := row.AsString("completed_at", ""); summary.CompletedAt == "" || ca > summary.CompletedAt {
682-
summary.CompletedAt = ca
683-
}
684-
// If we had an error on the shard, then let's add that to the summary.
685-
if le := row.AsString("last_error", ""); le != "" {
686-
summary.Errors[shard] = le
687-
}
688-
// Keep track of how many shards are marked as a specific state. We check
689-
// this combined with the shard.table states to determine the VDiff summary
690-
// state.
691-
shardStateCounts[vdiff.VDiffState(strings.ToLower(row.AsString("vdiff_state", "")))]++
692-
}
693-
694-
// Global VDiff summary updates that take into account the per table details
695-
// per shard.
696-
{
697-
summary.RowsCompared += row.AsInt64("rows_compared", 0)
698-
totalRowsToCompare += row.AsInt64("table_rows", 0)
699-
700-
// If we had a mismatch on any table on any shard then the global VDiff
701-
// summary does too.
702-
if mm, _ := row.ToBool("has_mismatch"); mm {
703-
summary.HasMismatch = true
704-
}
705-
}
706-
707-
// Table summary information that must be accounted for across all shards.
708-
{
709-
table := row.AsString("table_name", "")
710-
if table == "" { // This occurs when the table diff has not started on 1 or more shards
711-
continue
712-
}
713-
// Create the global VDiff table summary object if it doesn't exist.
714-
if _, ok := tableSummaryMap[table]; !ok {
715-
tableSummaryMap[table] = tableSummary{
716-
TableName: table,
717-
State: vdiff.UnknownState,
718-
}
719-
720-
}
721-
ts := tableSummaryMap[table]
722-
// This is the shard level VDiff table state.
723-
sts := vdiff.VDiffState(strings.ToLower(row.AsString("table_state", "")))
724-
tableStateCounts[sts]++
725-
726-
// The error state must be sticky, and we should not override any other
727-
// known state with completed.
728-
switch sts {
729-
case vdiff.CompletedState:
730-
if ts.State == vdiff.UnknownState {
731-
ts.State = sts
732-
}
733-
case vdiff.ErrorState:
734-
ts.State = sts
735-
default:
736-
if ts.State != vdiff.ErrorState {
737-
ts.State = sts
738-
}
739-
}
740-
741-
diffReport := row.AsString("report", "")
742-
dr := vdiff.DiffReport{}
743-
if diffReport != "" {
744-
err := json.Unmarshal([]byte(diffReport), &dr)
745-
if err != nil {
746-
return nil, err
747-
}
748-
ts.RowsCompared += dr.ProcessedRows
749-
ts.MismatchedRows += dr.MismatchedRows
750-
ts.MatchingRows += dr.MatchingRows
751-
ts.ExtraRowsTarget += dr.ExtraRowsTarget
752-
ts.ExtraRowsSource += dr.ExtraRowsSource
753-
}
754-
if _, ok := reports[table]; !ok {
755-
reports[table] = make(map[string]vdiff.DiffReport)
756-
}
757-
758-
reports[table][shard] = dr
759-
tableSummaryMap[table] = ts
760-
}
761-
}
762-
}
763-
}
764-
765-
// The global VDiff summary should progress from pending->started->completed with
766-
// stopped for any shard and error for any table being sticky for the global summary.
767-
// We should only consider the VDiff to be complete if it's completed for every table
768-
// on every shard.
769-
if shardStateCounts[vdiff.StoppedState] > 0 {
770-
summary.State = vdiff.StoppedState
771-
} else if shardStateCounts[vdiff.ErrorState] > 0 || tableStateCounts[vdiff.ErrorState] > 0 {
772-
summary.State = vdiff.ErrorState
773-
} else if tableStateCounts[vdiff.StartedState] > 0 {
774-
summary.State = vdiff.StartedState
775-
} else if tableStateCounts[vdiff.PendingState] > 0 {
776-
summary.State = vdiff.PendingState
777-
} else if tableStateCounts[vdiff.CompletedState] == (len(tableSummaryMap) * len(shards)) {
778-
// When doing shard consolidations/merges, we cannot rely solely on the
779-
// vdiff_table state as there are N sources that we process rows from sequentially
780-
// with each one writing to the shared _vt.vdiff_table record for the target shard.
781-
// So we only mark the vdiff for the shard as completed when we've finished
782-
// processing rows from all of the sources -- which is recorded by marking the
783-
// vdiff done for the shard by setting _vt.vdiff.state = completed.
784-
if shardStateCounts[vdiff.CompletedState] == len(shards) {
785-
summary.State = vdiff.CompletedState
786-
} else {
787-
summary.State = vdiff.StartedState
788-
}
789-
} else {
790-
summary.State = vdiff.UnknownState
791-
}
792-
793-
// If the vdiff has been started then we can calculate the progress.
794-
if summary.State == vdiff.StartedState {
795-
summary.Progress = BuildProgressReport(summary.RowsCompared, totalRowsToCompare, summary.StartedAt)
796-
}
797-
798-
sort.Strings(shards) // Sort for predictable output
799-
summary.Shards = strings.Join(shards, ",")
800-
summary.TableSummaryMap = tableSummaryMap
801-
summary.Reports = reports
802-
if !summary.HasMismatch && !verbose {
803-
summary.Reports = nil
804-
summary.TableSummaryMap = nil
805-
}
806-
// If we haven't completed the global VDiff then be sure to reflect that with no
807-
// CompletedAt value.
808-
if summary.State != vdiff.CompletedState {
809-
summary.CompletedAt = ""
810-
}
811-
return summary, nil
812-
}
813-
814-
func BuildProgressReport(rowsCompared int64, rowsToCompare int64, startedAt string) *vdiff.ProgressReport {
815-
report := &vdiff.ProgressReport{}
816-
if rowsCompared >= 1 {
817-
// Round to 2 decimal points.
818-
report.Percentage = math.Round(math.Min((float64(rowsCompared)/float64(rowsToCompare))*100, 100.00)*100) / 100
819-
}
820-
if math.IsNaN(report.Percentage) {
821-
report.Percentage = 0
822-
}
823-
pctToGo := math.Abs(report.Percentage - 100.00)
824-
startTime, _ := time.Parse(vdiff.TimestampFormat, startedAt)
825-
curTime := time.Now().UTC()
826-
runTime := curTime.Unix() - startTime.Unix()
827-
if report.Percentage >= 1 {
828-
// Calculate how long 1% took, on avg, and multiply that by the % left.
829-
eta := time.Unix(((int64(runTime)/int64(report.Percentage))*int64(pctToGo))+curTime.Unix(), 1).UTC()
830-
// Cap the ETA at 1 year out to prevent providing nonsensical ETAs.
831-
if eta.Before(time.Now().UTC().AddDate(1, 0, 0)) {
832-
report.ETA = eta.Format(vdiff.TimestampFormat)
833-
}
834-
}
835-
return report
836-
}
837-
838617
func commandShow(cmd *cobra.Command, args []string) error {
839618
format, err := common.GetOutputFormat(cmd)
840619
if err != nil {

go/cmd/vtctldclient/command/vreplication/vdiff/vdiff_test.go

Lines changed: 0 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package vdiff
1919
import (
2020
"context"
2121
"fmt"
22-
"math"
2322
"testing"
2423
"time"
2524

@@ -690,112 +689,3 @@ func TestGetStructNames(t *testing.T) {
690689
want := []string{"A", "B"}
691690
require.EqualValues(t, want, got)
692691
}
693-
694-
func TestBuildProgressReport(t *testing.T) {
695-
now := time.Now()
696-
type args struct {
697-
summary *summary
698-
rowsToCompare int64
699-
}
700-
tests := []struct {
701-
name string
702-
args args
703-
want *vdiff.ProgressReport
704-
}{
705-
{
706-
name: "no progress",
707-
args: args{
708-
summary: &summary{RowsCompared: 0},
709-
rowsToCompare: 100,
710-
},
711-
want: &vdiff.ProgressReport{
712-
Percentage: 0,
713-
ETA: "", // no ETA
714-
},
715-
},
716-
{
717-
name: "one third of the way",
718-
args: args{
719-
summary: &summary{
720-
RowsCompared: 33,
721-
StartedAt: now.Add(-10 * time.Second).UTC().Format(vdiff.TimestampFormat),
722-
},
723-
rowsToCompare: 100,
724-
},
725-
want: &vdiff.ProgressReport{
726-
Percentage: 33,
727-
ETA: now.Add(20 * time.Second).UTC().Format(vdiff.TimestampFormat),
728-
},
729-
},
730-
{
731-
name: "half way",
732-
args: args{
733-
summary: &summary{
734-
RowsCompared: 5000000000,
735-
StartedAt: now.Add(-10 * time.Hour).UTC().Format(vdiff.TimestampFormat),
736-
},
737-
rowsToCompare: 10000000000,
738-
},
739-
want: &vdiff.ProgressReport{
740-
Percentage: 50,
741-
ETA: now.Add(10 * time.Hour).UTC().Format(vdiff.TimestampFormat),
742-
},
743-
},
744-
{
745-
name: "full progress",
746-
args: args{
747-
summary: &summary{
748-
RowsCompared: 100,
749-
CompletedAt: now.UTC().Format(vdiff.TimestampFormat),
750-
},
751-
rowsToCompare: 100,
752-
},
753-
want: &vdiff.ProgressReport{
754-
Percentage: 100,
755-
ETA: now.UTC().Format(vdiff.TimestampFormat),
756-
},
757-
},
758-
{
759-
name: "more than in I_S",
760-
args: args{
761-
summary: &summary{
762-
RowsCompared: 100,
763-
CompletedAt: now.UTC().Format(vdiff.TimestampFormat),
764-
},
765-
rowsToCompare: 50,
766-
},
767-
want: &vdiff.ProgressReport{
768-
Percentage: 100,
769-
ETA: now.UTC().Format(vdiff.TimestampFormat),
770-
},
771-
},
772-
}
773-
for _, tt := range tests {
774-
t.Run(tt.name, func(t *testing.T) {
775-
tt.args.summary.Progress = BuildProgressReport(tt.args.summary.RowsCompared, tt.args.rowsToCompare, tt.args.summary.StartedAt)
776-
// We always check the percentage
777-
require.Equal(t, int(tt.want.Percentage), int(tt.args.summary.Progress.Percentage))
778-
779-
// We only check the ETA if there is one.
780-
if tt.want.ETA != "" {
781-
// Let's check that we're within 1 second to avoid flakes.
782-
wantTime, err := time.Parse(vdiff.TimestampFormat, tt.want.ETA)
783-
require.NoError(t, err)
784-
var timeDiff float64
785-
if tt.want.Percentage == 100 {
786-
completedTime, err := time.Parse(vdiff.TimestampFormat, tt.args.summary.CompletedAt)
787-
require.NoError(t, err)
788-
timeDiff = math.Abs(completedTime.Sub(wantTime).Seconds())
789-
} else {
790-
startTime, err := time.Parse(vdiff.TimestampFormat, tt.args.summary.StartedAt)
791-
require.NoError(t, err)
792-
completedTimeUnix := float64(now.UTC().Unix()-startTime.UTC().Unix()) * (100 / tt.want.Percentage)
793-
estimatedTime, err := time.Parse(vdiff.TimestampFormat, tt.want.ETA)
794-
require.NoError(t, err)
795-
timeDiff = math.Abs(estimatedTime.Sub(startTime).Seconds() - completedTimeUnix)
796-
}
797-
require.LessOrEqual(t, timeDiff, 1.0)
798-
}
799-
})
800-
}
801-
}

go/mysql/conn.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ func (c *Conn) readHeaderFrom(r io.Reader) (int, error) {
399399
return 0, vterrors.Wrapf(err, "io.ReadFull(header size) failed")
400400
}
401401

402-
sequence := uint8(c.header[3])
402+
sequence := c.header[3]
403403
if sequence != c.sequence {
404404
return 0, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "invalid sequence, expected %v got %v", c.sequence, sequence)
405405
}

0 commit comments

Comments
 (0)