Skip to content

Commit

Permalink
Handle the case where a primary tablet is not setup for a shard
Browse files Browse the repository at this point in the history
Signed-off-by: Rohit Nayak <[email protected]>
  • Loading branch information
rohit-nayak-ps committed Jan 18, 2025
1 parent eaaa206 commit 7ea2051
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
12 changes: 10 additions & 2 deletions go/vt/discovery/tablet_picker.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,13 @@ func (tp *TabletPicker) GetMatchingTablets(ctx context.Context) []*topo.TabletIn
log.Errorf("Error getting shard %s/%s: %v", tp.keyspace, tp.shard, err)
return nil
}
if _, ignore := tp.ignoreTablets[si.PrimaryAlias.String()]; !ignore {
aliases = append(aliases, si.PrimaryAlias)

// It is possible that there is a cluster event (ERS/PRS, for example) due to which
// there is no primary elected for the shard at the moment.
if si.PrimaryAlias != nil {
if _, ignore := tp.ignoreTablets[si.PrimaryAlias.String()]; !ignore {
aliases = append(aliases, si.PrimaryAlias)
}
}
} else {
actualCells := make([]string, 0)
Expand Down Expand Up @@ -425,6 +430,9 @@ func (tp *TabletPicker) GetMatchingTablets(ctx context.Context) []*topo.TabletIn
continue
}
for _, node := range sri.Nodes {
if node.TabletAlias == nil {
continue
}
if _, ignore := tp.ignoreTablets[node.TabletAlias.String()]; !ignore {
aliases = append(aliases, node.TabletAlias)
}
Expand Down
27 changes: 27 additions & 0 deletions go/vt/discovery/tablet_picker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,33 @@ func TestPickPrimary(t *testing.T) {
assert.True(t, proto.Equal(want, tablet), "Pick: %v, want %v", tablet, want)
}

// TestPickNoPrimary confirms that if the picker was setup only for primary tablets but
// there is no primary setup for the shard we correctly return an error.
func TestPickNoPrimary(t *testing.T) {
defer utils.EnsureNoLeaks(t)
ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
defer cancel()

te := newPickerTestEnv(t, ctx, []string{"cell", "otherCell"})
want := addTablet(ctx, te, 100, topodatapb.TabletType_PRIMARY, "cell", true, true)
defer deleteTablet(t, te, want)
ctx, cancel = context.WithTimeout(ctx, 200*time.Millisecond)
defer cancel()
_, err := te.topoServ.UpdateShardFields(ctx, te.keyspace, te.shard, func(si *topo.ShardInfo) error {
si.PrimaryAlias = nil // force a missing primary
return nil
})
require.NoError(t, err)

tp, err := NewTabletPicker(ctx, te.topoServ, []string{"otherCell"}, "cell", te.keyspace, te.shard, "primary", TabletPickerOptions{})
require.NoError(t, err)

ctx2, cancel2 := context.WithTimeout(ctx, 200*time.Millisecond)
defer cancel2()
_, err = tp.PickForStreaming(ctx2)
require.Errorf(t, err, "No healthy serving tablet")
}

func TestPickLocalPreferences(t *testing.T) {
defer utils.EnsureNoLeaks(t)
type tablet struct {
Expand Down
3 changes: 3 additions & 0 deletions go/vt/topo/tablet.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,9 @@ func (ts *Server) GetTabletMap(ctx context.Context, tabletAliases []*topodatapb.
)

for _, tabletAlias := range tabletAliases {
if tabletAlias == nil {
return nil, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "nil tablet alias in list")
}
wg.Add(1)
go func(tabletAlias *topodatapb.TabletAlias) {
defer wg.Done()
Expand Down

0 comments on commit 7ea2051

Please sign in to comment.