Skip to content

Commit a4dbece

Browse files
Vtctld SwitchReads: fix bug where writes were also being switched as part of switching reads when all traffic was switched using SwitchTraffic (#14360)
Signed-off-by: Rohit Nayak <[email protected]> Signed-off-by: Matt Lord <[email protected]> Co-authored-by: Matt Lord <[email protected]>
1 parent 28ceaa8 commit a4dbece

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

go/vt/vtctl/workflow/server.go

+17-9
Original file line numberDiff line numberDiff line change
@@ -2940,9 +2940,18 @@ func (s *Server) WorkflowSwitchTraffic(ctx context.Context, req *vtctldatapb.Wor
29402940

29412941
// switchReads is a generic way of switching read traffic for a workflow.
29422942
func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitchTrafficRequest, ts *trafficSwitcher, state *State, timeout time.Duration, cancel bool, direction TrafficSwitchDirection) (*[]string, error) {
2943-
roTypesToSwitchStr := topoproto.MakeStringTypeCSV(req.TabletTypes)
2943+
var roTabletTypes []topodatapb.TabletType
2944+
// When we are switching all traffic we also get the primary tablet type, which we need to
2945+
// filter out for switching reads.
2946+
for _, tabletType := range req.TabletTypes {
2947+
if tabletType != topodatapb.TabletType_PRIMARY {
2948+
roTabletTypes = append(roTabletTypes, tabletType)
2949+
}
2950+
}
2951+
2952+
roTypesToSwitchStr := topoproto.MakeStringTypeCSV(roTabletTypes)
29442953
var switchReplica, switchRdonly bool
2945-
for _, roType := range req.TabletTypes {
2954+
for _, roType := range roTabletTypes {
29462955
switch roType {
29472956
case topodatapb.TabletType_REPLICA:
29482957
switchReplica = true
@@ -2953,14 +2962,13 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc
29532962

29542963
// Consistently handle errors by logging and returning them.
29552964
handleError := func(message string, err error) (*[]string, error) {
2956-
werr := vterrors.Errorf(vtrpcpb.Code_INTERNAL, fmt.Sprintf("%s: %v", message, err))
2957-
ts.Logger().Error(werr)
2958-
return nil, werr
2965+
ts.Logger().Error(err)
2966+
return nil, err
29592967
}
29602968

29612969
log.Infof("Switching reads: %s.%s tablet types: %s, cells: %s, workflow state: %s", ts.targetKeyspace, ts.workflow, roTypesToSwitchStr, ts.optCells, state.String())
29622970
if !switchReplica && !switchRdonly {
2963-
return handleError("invalid tablet types", vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "tablet types must be REPLICA or RDONLY: %s", roTypesToSwitchStr))
2971+
return handleError("invalid tablet types", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "tablet types must be REPLICA or RDONLY: %s", roTypesToSwitchStr))
29642972
}
29652973
if !ts.isPartialMigration { // shard level traffic switching is all or nothing
29662974
if direction == DirectionBackward && switchReplica && len(state.ReplicaCellsSwitched) == 0 {
@@ -2987,7 +2995,7 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc
29872995
return nil, err
29882996
}
29892997
if !rdonlyTabletsExist {
2990-
req.TabletTypes = append(req.TabletTypes, topodatapb.TabletType_RDONLY)
2998+
roTabletTypes = append(roTabletTypes, topodatapb.TabletType_RDONLY)
29912999
}
29923000
}
29933001

@@ -3020,13 +3028,13 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc
30203028
if ts.MigrationType() == binlogdatapb.MigrationType_TABLES {
30213029
if ts.isPartialMigration {
30223030
ts.Logger().Infof("Partial migration, skipping switchTableReads as traffic is all or nothing per shard and overridden for reads AND writes in the ShardRoutingRule created when switching writes.")
3023-
} else if err := sw.switchTableReads(ctx, cells, req.TabletTypes, direction); err != nil {
3031+
} else if err := sw.switchTableReads(ctx, cells, roTabletTypes, direction); err != nil {
30243032
return handleError("failed to switch read traffic for the tables", err)
30253033
}
30263034
return sw.logs(), nil
30273035
}
30283036
ts.Logger().Infof("About to switchShardReads: %+v, %+s, %+v", cells, roTypesToSwitchStr, direction)
3029-
if err := sw.switchShardReads(ctx, cells, req.TabletTypes, direction); err != nil {
3037+
if err := sw.switchShardReads(ctx, cells, roTabletTypes, direction); err != nil {
30303038
return handleError("failed to switch read traffic for the shards", err)
30313039
}
30323040

go/vt/vtctl/workflow/traffic_switcher.go

+4
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,10 @@ func (ts *trafficSwitcher) switchTableReads(ctx context.Context, cells []string,
587587
// For forward migration, we add tablet type specific rules to redirect traffic to the target.
588588
// For backward, we redirect to source.
589589
for _, servedType := range servedTypes {
590+
if servedType != topodatapb.TabletType_REPLICA && servedType != topodatapb.TabletType_RDONLY {
591+
return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid tablet type specified when switching reads: %v", servedType)
592+
}
593+
590594
tt := strings.ToLower(servedType.String())
591595
for _, table := range ts.Tables() {
592596
if direction == DirectionForward {

0 commit comments

Comments
 (0)