Skip to content

Commit

Permalink
feat: add allow cross cell promotion flag to prs
Browse files Browse the repository at this point in the history
Signed-off-by: Manan Gupta <manan@planetscale.com>
  • Loading branch information
GuptaManan100 committed Jul 23, 2024
1 parent ae7214d commit 7e9f8e6
Show file tree
Hide file tree
Showing 11 changed files with 1,008 additions and 863 deletions.
3 changes: 3 additions & 0 deletions go/cmd/vtctldclient/command/reparents.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ var plannedReparentShardOptions = struct {
AvoidPrimaryAliasStr string
WaitReplicasTimeout time.Duration
TolerableReplicationLag time.Duration
AllowCrossCellPromotion bool
}{}

func commandPlannedReparentShard(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -223,6 +224,7 @@ func commandPlannedReparentShard(cmd *cobra.Command, args []string) error {
AvoidPrimary: avoidPrimaryAlias,
WaitReplicasTimeout: protoutil.DurationToProto(plannedReparentShardOptions.WaitReplicasTimeout),
TolerableReplicationLag: protoutil.DurationToProto(plannedReparentShardOptions.TolerableReplicationLag),
AllowCrossCellPromotion: plannedReparentShardOptions.AllowCrossCellPromotion,
})
if err != nil {
return err
Expand Down Expand Up @@ -297,6 +299,7 @@ func init() {
PlannedReparentShard.Flags().DurationVar(&plannedReparentShardOptions.TolerableReplicationLag, "tolerable-replication-lag", 0, "Amount of replication lag that is considered acceptable for a tablet to be eligible for promotion when Vitess makes the choice of a new primary.")
PlannedReparentShard.Flags().StringVar(&plannedReparentShardOptions.NewPrimaryAliasStr, "new-primary", "", "Alias of a tablet that should be the new primary.")
PlannedReparentShard.Flags().StringVar(&plannedReparentShardOptions.AvoidPrimaryAliasStr, "avoid-primary", "", "Alias of a tablet that should not be the primary; i.e. \"reparent to any other tablet if this one is the primary\".")
PlannedReparentShard.Flags().BoolVar(&plannedReparentShardOptions.AllowCrossCellPromotion, "allow-cross-cell-promotion", false, "Allow cross cell promotion")
Root.AddCommand(PlannedReparentShard)

Root.AddCommand(ReparentTablet)
Expand Down
1,691 changes: 852 additions & 839 deletions go/vt/proto/vtctldata/vtctldata.pb.go

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions go/vt/proto/vtctldata/vtctldata_vtproto.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions go/vt/vtctl/grpcvtctldserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2976,10 +2976,11 @@ func (s *VtctldServer) PlannedReparentShard(ctx context.Context, req *vtctldatap
req.Keyspace,
req.Shard,
reparentutil.PlannedReparentOptions{
AvoidPrimaryAlias: req.AvoidPrimary,
NewPrimaryAlias: req.NewPrimary,
WaitReplicasTimeout: waitReplicasTimeout,
TolerableReplLag: tolerableReplLag,
AvoidPrimaryAlias: req.AvoidPrimary,
NewPrimaryAlias: req.NewPrimary,
WaitReplicasTimeout: waitReplicasTimeout,
TolerableReplLag: tolerableReplLag,
AllowCrossCellPromotion: req.AllowCrossCellPromotion,
},
)

Expand Down
10 changes: 6 additions & 4 deletions go/vt/vtctl/reparent.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ func commandPlannedReparentShard(ctx context.Context, wr *wrangler.Wrangler, sub
keyspaceShard := subFlags.String("keyspace_shard", "", "keyspace/shard of the shard that needs to be reparented")
newPrimary := subFlags.String("new_primary", "", "alias of a tablet that should be the new primary")
avoidTablet := subFlags.String("avoid_tablet", "", "alias of a tablet that should not be the primary, i.e. reparent to any other tablet if this one is the primary")
allowCrossCellPromotion := subFlags.Bool("allow-cross-cell-promotion", false, "allow cross cell promotions")

if err := subFlags.Parse(args); err != nil {
return err
Expand Down Expand Up @@ -153,10 +154,11 @@ func commandPlannedReparentShard(ctx context.Context, wr *wrangler.Wrangler, sub
}

return wr.PlannedReparentShard(ctx, keyspace, shard, reparentutil.PlannedReparentOptions{
NewPrimaryAlias: newPrimaryAlias,
AvoidPrimaryAlias: avoidTabletAlias,
WaitReplicasTimeout: *waitReplicasTimeout,
TolerableReplLag: *tolerableReplicationLag,
NewPrimaryAlias: newPrimaryAlias,
AvoidPrimaryAlias: avoidTabletAlias,
WaitReplicasTimeout: *waitReplicasTimeout,
TolerableReplLag: *tolerableReplicationLag,
AllowCrossCellPromotion: *allowCrossCellPromotion,
})
}

Expand Down
11 changes: 6 additions & 5 deletions go/vt/vtctl/reparentutil/planned_reparenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ type PlannedReparenter struct {
// operations. Options are passed by value, so it is safe for callers to mutate
// resue options structs for multiple calls.
type PlannedReparentOptions struct {
NewPrimaryAlias *topodatapb.TabletAlias
AvoidPrimaryAlias *topodatapb.TabletAlias
WaitReplicasTimeout time.Duration
TolerableReplLag time.Duration
NewPrimaryAlias *topodatapb.TabletAlias
AvoidPrimaryAlias *topodatapb.TabletAlias
WaitReplicasTimeout time.Duration
TolerableReplLag time.Duration
AllowCrossCellPromotion bool

// Private options managed internally. We use value-passing semantics to
// set these options inside a PlannedReparent without leaking these details
Expand Down Expand Up @@ -178,7 +179,7 @@ func (pr *PlannedReparenter) preflightChecks(
}

event.DispatchUpdate(ev, "electing a primary candidate")
opts.NewPrimaryAlias, err = ElectNewPrimary(ctx, pr.tmc, &ev.ShardInfo, tabletMap, opts.NewPrimaryAlias, opts.AvoidPrimaryAlias, opts.WaitReplicasTimeout, opts.TolerableReplLag, opts.durability, pr.logger)
opts.NewPrimaryAlias, err = ElectNewPrimary(ctx, pr.tmc, &ev.ShardInfo, tabletMap, opts.NewPrimaryAlias, opts.AvoidPrimaryAlias, opts.WaitReplicasTimeout, opts.TolerableReplLag, opts.durability, opts.AllowCrossCellPromotion, pr.logger)
if err != nil {
return true, err
}
Expand Down
3 changes: 2 additions & 1 deletion go/vt/vtctl/reparentutil/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func ElectNewPrimary(
waitReplicasTimeout time.Duration,
tolerableReplLag time.Duration,
durability Durabler,
allowCrossCellPromotion bool,
// (TODO:@ajm188) it's a little gross we need to pass this, maybe embed in the context?
logger logutil.Logger,
) (*topodatapb.TabletAlias, error) {
Expand Down Expand Up @@ -102,7 +103,7 @@ func ElectNewPrimary(
reasonsToInvalidate.WriteString(fmt.Sprintf("\n%v does not match the new primary alias provided", topoproto.TabletAliasString(tablet.Alias)))
continue
}
case primaryCell != "" && tablet.Alias.Cell != primaryCell:
case !allowCrossCellPromotion && primaryCell != "" && tablet.Alias.Cell != primaryCell:
reasonsToInvalidate.WriteString(fmt.Sprintf("\n%v is not in the same cell as the previous primary", topoproto.TabletAliasString(tablet.Alias)))
continue
case avoidPrimaryAlias != nil && topoproto.TabletAliasEqual(tablet.Alias, avoidPrimaryAlias):
Expand Down
79 changes: 69 additions & 10 deletions go/vt/vtctl/reparentutil/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,16 @@ func TestElectNewPrimary(t *testing.T) {
ctx := context.Background()
logger := logutil.NewMemoryLogger()
tests := []struct {
name string
tmc *chooseNewPrimaryTestTMClient
shardInfo *topo.ShardInfo
tabletMap map[string]*topo.TabletInfo
newPrimaryAlias *topodatapb.TabletAlias
avoidPrimaryAlias *topodatapb.TabletAlias
tolerableReplLag time.Duration
expected *topodatapb.TabletAlias
errContains []string
name string
tmc *chooseNewPrimaryTestTMClient
shardInfo *topo.ShardInfo
tabletMap map[string]*topo.TabletInfo
newPrimaryAlias *topodatapb.TabletAlias
avoidPrimaryAlias *topodatapb.TabletAlias
tolerableReplLag time.Duration
allowCrossCellPromotion bool
expected *topodatapb.TabletAlias
errContains []string
}{
{
name: "found a replica",
Expand Down Expand Up @@ -653,6 +654,64 @@ func TestElectNewPrimary(t *testing.T) {
`zone1-0000000102 is not in the same cell as the previous primary`,
},
},
{
name: "no replicas in primary cell but cross cell allowed",
tmc: &chooseNewPrimaryTestTMClient{
// zone1-101 is behind zone1-102
replicationStatuses: map[string]*replicationdatapb.Status{
"zone1-0000000101": {
Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429562:1",
},
"zone1-0000000102": {
Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5",
},
},
},
allowCrossCellPromotion: true,
shardInfo: topo.NewShardInfo("testkeyspace", "-", &topodatapb.Shard{
PrimaryAlias: &topodatapb.TabletAlias{
Cell: "zone2",
Uid: 200,
},
}, nil),
tabletMap: map[string]*topo.TabletInfo{
"primary": {
Tablet: &topodatapb.Tablet{
Alias: &topodatapb.TabletAlias{
Cell: "zone2",
Uid: 200,
},
Type: topodatapb.TabletType_PRIMARY,
},
},
"replica1": {
Tablet: &topodatapb.Tablet{
Alias: &topodatapb.TabletAlias{
Cell: "zone1",
Uid: 101,
},
Type: topodatapb.TabletType_REPLICA,
},
},
"replica2": {
Tablet: &topodatapb.Tablet{
Alias: &topodatapb.TabletAlias{
Cell: "zone1",
Uid: 102,
},
Type: topodatapb.TabletType_REPLICA,
},
},
},
avoidPrimaryAlias: &topodatapb.TabletAlias{
Cell: "zone1",
Uid: 0,
},
expected: &topodatapb.TabletAlias{
Cell: "zone1",
Uid: 102,
},
},
{
name: "only available tablet is AvoidPrimary",
tmc: &chooseNewPrimaryTestTMClient{
Expand Down Expand Up @@ -731,7 +790,7 @@ zone1-0000000100 is not a replica`,
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

actual, err := ElectNewPrimary(ctx, tt.tmc, tt.shardInfo, tt.tabletMap, tt.newPrimaryAlias, tt.avoidPrimaryAlias, time.Millisecond*50, tt.tolerableReplLag, durability, logger)
actual, err := ElectNewPrimary(ctx, tt.tmc, tt.shardInfo, tt.tabletMap, tt.newPrimaryAlias, tt.avoidPrimaryAlias, time.Millisecond*50, tt.tolerableReplLag, durability, tt.allowCrossCellPromotion, logger)
if len(tt.errContains) > 0 {
for _, errC := range tt.errContains {
assert.ErrorContains(t, err, errC)
Expand Down
2 changes: 2 additions & 0 deletions proto/vtctldata.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,8 @@ message PlannedReparentShardRequest {
// acceptable for a tablet to be eligible for promotion when Vitess makes the choice of a new primary.
// A value of 0 indicates that Vitess shouldn't consider the replication lag at all.
vttime.Duration tolerable_replication_lag = 6;
// AllowCrossCellPromotion allows cross cell promotion,
bool allow_cross_cell_promotion = 7;
}

message PlannedReparentShardResponse {
Expand Down
6 changes: 6 additions & 0 deletions web/vtadmin/src/proto/vtadmin.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions web/vtadmin/src/proto/vtadmin.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7e9f8e6

Please sign in to comment.