vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletservermock/controller.go (about)

     1  /*
     2  Copyright 2019 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 tabletservermock provides mock interfaces for tabletserver.
    18  package tabletservermock
    19  
    20  import (
    21  	"sync"
    22  
    23  	"google.golang.org/protobuf/proto"
    24  
    25  	"context"
    26  
    27  	"time"
    28  
    29  	"vitess.io/vitess/go/vt/dbconfigs"
    30  	"vitess.io/vitess/go/vt/mysqlctl"
    31  	"vitess.io/vitess/go/vt/servenv"
    32  	"vitess.io/vitess/go/vt/topo"
    33  	"vitess.io/vitess/go/vt/vttablet/queryservice"
    34  	"vitess.io/vitess/go/vt/vttablet/tabletserver/rules"
    35  	"vitess.io/vitess/go/vt/vttablet/tabletserver/schema"
    36  	"vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv"
    37  	"vitess.io/vitess/go/vt/vttablet/vexec"
    38  
    39  	querypb "vitess.io/vitess/go/vt/proto/query"
    40  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    41  )
    42  
    43  // BroadcastData is used by the mock Controller to send data
    44  // so the tests can check what was sent.
    45  type BroadcastData struct {
    46  	// TERTimestamp stores the last broadcast timestamp.
    47  	TERTimestamp int64
    48  
    49  	// RealtimeStats stores the last broadcast stats.
    50  	RealtimeStats querypb.RealtimeStats
    51  
    52  	// Serving contains the QueryServiceEnabled flag
    53  	Serving bool
    54  }
    55  
    56  // StateChange stores the state the controller changed to.
    57  // Tests can use this to verify that the state changed as expected.
    58  type StateChange struct {
    59  	// Serving is true when the QueryService is enabled.
    60  	Serving bool
    61  	// TabletType is the type of tablet e.g. REPLICA.
    62  	TabletType topodatapb.TabletType
    63  }
    64  
    65  // Controller is a mock tabletserver.Controller
    66  type Controller struct {
    67  	stats *tabletenv.Stats
    68  
    69  	// BroadcastData is a channel where we send BroadcastHealth data.
    70  	// Set at construction time.
    71  	BroadcastData chan *BroadcastData
    72  
    73  	// StateChanges has the list of state changes done by SetServingType().
    74  	// Set at construction time.
    75  	StateChanges chan *StateChange
    76  
    77  	target *querypb.Target
    78  
    79  	// SetServingTypeError is the return value for SetServingType.
    80  	SetServingTypeError error
    81  
    82  	// TS is the return value for TopoServer.
    83  	TS *topo.Server
    84  
    85  	// mu protects the next fields in this structure. They are
    86  	// accessed by both the methods in this interface, and the
    87  	// background health check.
    88  	mu sync.Mutex
    89  
    90  	// QueryServiceEnabled is a state variable.
    91  	queryServiceEnabled bool
    92  
    93  	// isInLameduck is a state variable.
    94  	isInLameduck bool
    95  
    96  	// queryRulesMap has the latest query rules.
    97  	queryRulesMap map[string]*rules.Rules
    98  }
    99  
   100  // NewController returns a mock of tabletserver.Controller
   101  func NewController() *Controller {
   102  	return &Controller{
   103  		stats:               tabletenv.NewStats(servenv.NewExporter("MockController", "Tablet")),
   104  		queryServiceEnabled: false,
   105  		BroadcastData:       make(chan *BroadcastData, 10),
   106  		StateChanges:        make(chan *StateChange, 10),
   107  		queryRulesMap:       make(map[string]*rules.Rules),
   108  	}
   109  }
   110  
   111  // Stats is part of the tabletserver.Controller interface
   112  func (tqsc *Controller) Stats() *tabletenv.Stats {
   113  	return tqsc.stats
   114  }
   115  
   116  // Register is part of the tabletserver.Controller interface
   117  func (tqsc *Controller) Register() {
   118  }
   119  
   120  // AddStatusHeader is part of the tabletserver.Controller interface
   121  func (tqsc *Controller) AddStatusHeader() {
   122  }
   123  
   124  // AddStatusPart is part of the tabletserver.Controller interface
   125  func (tqsc *Controller) AddStatusPart() {
   126  }
   127  
   128  // InitDBConfig is part of the tabletserver.Controller interface
   129  func (tqsc *Controller) InitDBConfig(target *querypb.Target, dbcfgs *dbconfigs.DBConfigs, _ mysqlctl.MysqlDaemon) error {
   130  	tqsc.mu.Lock()
   131  	defer tqsc.mu.Unlock()
   132  
   133  	tqsc.target = proto.Clone(target).(*querypb.Target)
   134  	return nil
   135  }
   136  
   137  // SetServingType is part of the tabletserver.Controller interface
   138  func (tqsc *Controller) SetServingType(tabletType topodatapb.TabletType, terTime time.Time, serving bool, reason string) error {
   139  	tqsc.mu.Lock()
   140  	defer tqsc.mu.Unlock()
   141  
   142  	if tqsc.SetServingTypeError == nil {
   143  		tqsc.target.TabletType = tabletType
   144  		tqsc.queryServiceEnabled = serving
   145  	}
   146  	tqsc.StateChanges <- &StateChange{
   147  		Serving:    serving,
   148  		TabletType: tabletType,
   149  	}
   150  	tqsc.isInLameduck = false
   151  	return tqsc.SetServingTypeError
   152  }
   153  
   154  // IsServing is part of the tabletserver.Controller interface
   155  func (tqsc *Controller) IsServing() bool {
   156  	tqsc.mu.Lock()
   157  	defer tqsc.mu.Unlock()
   158  
   159  	return tqsc.queryServiceEnabled
   160  }
   161  
   162  // CurrentTarget returns the current target.
   163  func (tqsc *Controller) CurrentTarget() *querypb.Target {
   164  	tqsc.mu.Lock()
   165  	defer tqsc.mu.Unlock()
   166  	return proto.Clone(tqsc.target).(*querypb.Target)
   167  }
   168  
   169  // IsHealthy is part of the tabletserver.Controller interface
   170  func (tqsc *Controller) IsHealthy() error {
   171  	return nil
   172  }
   173  
   174  // ReloadSchema is part of the tabletserver.Controller interface
   175  func (tqsc *Controller) ReloadSchema(ctx context.Context) error {
   176  	return nil
   177  }
   178  
   179  // OnlineDDLExecutor is part of the tabletserver.Controller interface
   180  func (tqsc *Controller) OnlineDDLExecutor() vexec.Executor {
   181  	return nil
   182  }
   183  
   184  // ClearQueryPlanCache is part of the tabletserver.Controller interface
   185  func (tqsc *Controller) ClearQueryPlanCache() {
   186  }
   187  
   188  // RegisterQueryRuleSource is part of the tabletserver.Controller interface
   189  func (tqsc *Controller) RegisterQueryRuleSource(ruleSource string) {
   190  }
   191  
   192  // UnRegisterQueryRuleSource is part of the tabletserver.Controller interface
   193  func (tqsc *Controller) UnRegisterQueryRuleSource(ruleSource string) {
   194  }
   195  
   196  // SetQueryRules is part of the tabletserver.Controller interface
   197  func (tqsc *Controller) SetQueryRules(ruleSource string, qrs *rules.Rules) error {
   198  	tqsc.mu.Lock()
   199  	defer tqsc.mu.Unlock()
   200  	tqsc.queryRulesMap[ruleSource] = qrs
   201  	return nil
   202  }
   203  
   204  // QueryService is part of the tabletserver.Controller interface
   205  func (tqsc *Controller) QueryService() queryservice.QueryService {
   206  	return nil
   207  }
   208  
   209  // SchemaEngine is part of the tabletserver.Controller interface
   210  func (tqsc *Controller) SchemaEngine() *schema.Engine {
   211  	return nil
   212  }
   213  
   214  // BroadcastHealth is part of the tabletserver.Controller interface
   215  func (tqsc *Controller) BroadcastHealth() {
   216  	tqsc.mu.Lock()
   217  	defer tqsc.mu.Unlock()
   218  
   219  	tqsc.BroadcastData <- &BroadcastData{
   220  		Serving: tqsc.queryServiceEnabled && (!tqsc.isInLameduck),
   221  	}
   222  }
   223  
   224  // TopoServer is part of the tabletserver.Controller interface.
   225  func (tqsc *Controller) TopoServer() *topo.Server {
   226  	return tqsc.TS
   227  }
   228  
   229  // EnterLameduck implements tabletserver.Controller.
   230  func (tqsc *Controller) EnterLameduck() {
   231  	tqsc.mu.Lock()
   232  	defer tqsc.mu.Unlock()
   233  
   234  	tqsc.isInLameduck = true
   235  }
   236  
   237  // SetQueryServiceEnabledForTests can set queryServiceEnabled in tests.
   238  func (tqsc *Controller) SetQueryServiceEnabledForTests(enabled bool) {
   239  	tqsc.mu.Lock()
   240  	defer tqsc.mu.Unlock()
   241  
   242  	tqsc.queryServiceEnabled = enabled
   243  }
   244  
   245  // GetQueryRules allows a test to check what was set.
   246  func (tqsc *Controller) GetQueryRules(ruleSource string) *rules.Rules {
   247  	tqsc.mu.Lock()
   248  	defer tqsc.mu.Unlock()
   249  	return tqsc.queryRulesMap[ruleSource]
   250  }