vitess.io/vitess@v0.16.2/go/vt/vtctl/schematools/reload.go (about)

     1  /*
     2  Copyright 2021 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package schematools
    18  
    19  import (
    20  	"context"
    21  	"sync"
    22  
    23  	"vitess.io/vitess/go/sync2"
    24  	"vitess.io/vitess/go/vt/logutil"
    25  	"vitess.io/vitess/go/vt/topo"
    26  	"vitess.io/vitess/go/vt/topo/topoproto"
    27  	"vitess.io/vitess/go/vt/vttablet/tmclient"
    28  
    29  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    30  )
    31  
    32  // ReloadShard reloads the schema for all replica tablets in a shard, after
    33  // they reach a given replication position (empty pos means immediate).
    34  //
    35  // In general, we don't always expect all replicas to be ready to reload,
    36  // and the periodic schema reload makes them self-healing anyway.
    37  // So we do this on a best-effort basis, and log warnings for any tablets
    38  // that fail to reload within the context deadline.
    39  func ReloadShard(ctx context.Context, ts *topo.Server, tmc tmclient.TabletManagerClient, logger logutil.Logger, keyspace, shard, replicationPos string, concurrency *sync2.Semaphore, includePrimary bool) (isPartial bool, ok bool) {
    40  	tablets, err := ts.GetTabletMapForShard(ctx, keyspace, shard)
    41  	switch {
    42  	case topo.IsErrType(err, topo.PartialResult):
    43  		// We got a partial result. Do what we can, but warn
    44  		// that some may be missed.
    45  		logger.Warningf("ReloadSchemaShard(%v/%v) got a partial tablet list. Some tablets may not have schema reloaded (use vtctl ReloadSchema to fix individual tablets)", keyspace, shard)
    46  		isPartial = true
    47  	case err == nil:
    48  		// Good case, keep going too.
    49  		isPartial = false
    50  	default:
    51  		// This is best-effort, so just log it and move on.
    52  		logger.Warningf("ReloadSchemaShard(%v/%v) failed to load tablet list, will not reload schema (use vtctl ReloadSchemaShard to try again): %v", keyspace, shard, err)
    53  		return false, false
    54  	}
    55  
    56  	var wg sync.WaitGroup
    57  	for _, ti := range tablets {
    58  		if !includePrimary && ti.Type == topodatapb.TabletType_PRIMARY {
    59  			// We don't need to reload on the primary
    60  			// because we assume ExecuteFetchAsDba()
    61  			// already did that.
    62  			continue
    63  		}
    64  
    65  		wg.Add(1)
    66  		go func(tablet *topodatapb.Tablet) {
    67  			defer wg.Done()
    68  
    69  			if concurrency != nil {
    70  				concurrency.Acquire()
    71  				defer concurrency.Release()
    72  			}
    73  
    74  			pos := replicationPos
    75  			// Primary is always up-to-date. So, don't wait for position.
    76  			if tablet.Type == topodatapb.TabletType_PRIMARY {
    77  				pos = ""
    78  			}
    79  
    80  			if err := tmc.ReloadSchema(ctx, tablet, pos); err != nil {
    81  				logger.Warningf(
    82  					"Failed to reload schema on replica tablet %v in %v/%v (use vtctl ReloadSchema to try again): %v",
    83  					topoproto.TabletAliasString(tablet.Alias), keyspace, shard, err,
    84  				)
    85  			}
    86  		}(ti.Tablet)
    87  	}
    88  	wg.Wait()
    89  
    90  	return isPartial, true
    91  }