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 }