@@ -34,16 +34,16 @@ func NewThrottler(applier *Applier, inspector *Inspector) *Throttler {
3434// shouldThrottle performs checks to see whether we should currently be throttling.
3535// It merely observes the metrics collected by other components, it does not issue
3636// its own metric collection.
37- func (this * Throttler ) shouldThrottle () (result bool , reason string ) {
37+ func (this * Throttler ) shouldThrottle () (result bool , reason string , reasonHint base. ThrottleReasonHint ) {
3838 generalCheckResult := this .migrationContext .GetThrottleGeneralCheckResult ()
3939 if generalCheckResult .ShouldThrottle {
40- return generalCheckResult .ShouldThrottle , generalCheckResult .Reason
40+ return generalCheckResult .ShouldThrottle , generalCheckResult .Reason , generalCheckResult . ReasonHint
4141 }
4242 // Replication lag throttle
4343 maxLagMillisecondsThrottleThreshold := atomic .LoadInt64 (& this .migrationContext .MaxLagMillisecondsThrottleThreshold )
4444 lag := atomic .LoadInt64 (& this .migrationContext .CurrentLag )
4545 if time .Duration (lag ) > time .Duration (maxLagMillisecondsThrottleThreshold )* time .Millisecond {
46- return true , fmt .Sprintf ("lag=%fs" , time .Duration (lag ).Seconds ())
46+ return true , fmt .Sprintf ("lag=%fs" , time .Duration (lag ).Seconds ()), base . NoThrottleReasonHint
4747 }
4848 checkThrottleControlReplicas := true
4949 if (this .migrationContext .TestOnReplica || this .migrationContext .MigrateOnReplica ) && (atomic .LoadInt64 (& this .migrationContext .AllEventsUpToLockProcessedInjectedFlag ) > 0 ) {
@@ -52,14 +52,14 @@ func (this *Throttler) shouldThrottle() (result bool, reason string) {
5252 if checkThrottleControlReplicas {
5353 lagResult := this .migrationContext .GetControlReplicasLagResult ()
5454 if lagResult .Err != nil {
55- return true , fmt .Sprintf ("%+v %+v" , lagResult .Key , lagResult .Err )
55+ return true , fmt .Sprintf ("%+v %+v" , lagResult .Key , lagResult .Err ), base . NoThrottleReasonHint
5656 }
5757 if lagResult .Lag > time .Duration (maxLagMillisecondsThrottleThreshold )* time .Millisecond {
58- return true , fmt .Sprintf ("%+v replica-lag=%fs" , lagResult .Key , lagResult .Lag .Seconds ())
58+ return true , fmt .Sprintf ("%+v replica-lag=%fs" , lagResult .Key , lagResult .Lag .Seconds ()), base . NoThrottleReasonHint
5959 }
6060 }
6161 // Got here? No metrics indicates we need throttling.
62- return false , ""
62+ return false , "" , base . NoThrottleReasonHint
6363}
6464
6565// parseChangelogHeartbeat is called when a heartbeat event is intercepted
@@ -147,8 +147,8 @@ func (this *Throttler) criticalLoadIsMet() (met bool, variableName string, value
147147// collectGeneralThrottleMetrics reads the once-per-sec metrics, and stores them onto this.migrationContext
148148func (this * Throttler ) collectGeneralThrottleMetrics () error {
149149
150- setThrottle := func (throttle bool , reason string ) error {
151- this .migrationContext .SetThrottleGeneralCheckResult (base .NewThrottleCheckResult (throttle , reason ))
150+ setThrottle := func (throttle bool , reason string , reasonHint base. ThrottleReasonHint ) error {
151+ this .migrationContext .SetThrottleGeneralCheckResult (base .NewThrottleCheckResult (throttle , reason , reasonHint ))
152152 return nil
153153 }
154154
@@ -161,7 +161,7 @@ func (this *Throttler) collectGeneralThrottleMetrics() error {
161161
162162 criticalLoadMet , variableName , value , threshold , err := this .criticalLoadIsMet ()
163163 if err != nil {
164- return setThrottle (true , fmt .Sprintf ("%s %s" , variableName , err ))
164+ return setThrottle (true , fmt .Sprintf ("%s %s" , variableName , err ), base . NoThrottleReasonHint )
165165 }
166166 if criticalLoadMet && this .migrationContext .CriticalLoadIntervalMilliseconds == 0 {
167167 this .migrationContext .PanicAbort <- fmt .Errorf ("critical-load met: %s=%d, >=%d" , variableName , value , threshold )
@@ -181,38 +181,38 @@ func (this *Throttler) collectGeneralThrottleMetrics() error {
181181
182182 // User-based throttle
183183 if atomic .LoadInt64 (& this .migrationContext .ThrottleCommandedByUser ) > 0 {
184- return setThrottle (true , "commanded by user" )
184+ return setThrottle (true , "commanded by user" , base . UserCommandThrottleReasonHint )
185185 }
186186 if this .migrationContext .ThrottleFlagFile != "" {
187187 if base .FileExists (this .migrationContext .ThrottleFlagFile ) {
188188 // Throttle file defined and exists!
189- return setThrottle (true , "flag-file" )
189+ return setThrottle (true , "flag-file" , base . NoThrottleReasonHint )
190190 }
191191 }
192192 if this .migrationContext .ThrottleAdditionalFlagFile != "" {
193193 if base .FileExists (this .migrationContext .ThrottleAdditionalFlagFile ) {
194194 // 2nd Throttle file defined and exists!
195- return setThrottle (true , "flag-file" )
195+ return setThrottle (true , "flag-file" , base . NoThrottleReasonHint )
196196 }
197197 }
198198
199199 maxLoad := this .migrationContext .GetMaxLoad ()
200200 for variableName , threshold := range maxLoad {
201201 value , err := this .applier .ShowStatusVariable (variableName )
202202 if err != nil {
203- return setThrottle (true , fmt .Sprintf ("%s %s" , variableName , err ))
203+ return setThrottle (true , fmt .Sprintf ("%s %s" , variableName , err ), base . NoThrottleReasonHint )
204204 }
205205 if value >= threshold {
206- return setThrottle (true , fmt .Sprintf ("max-load %s=%d >= %d" , variableName , value , threshold ))
206+ return setThrottle (true , fmt .Sprintf ("max-load %s=%d >= %d" , variableName , value , threshold ), base . NoThrottleReasonHint )
207207 }
208208 }
209209 if this .migrationContext .GetThrottleQuery () != "" {
210210 if res , _ := this .applier .ExecuteThrottleQuery (); res > 0 {
211- return setThrottle (true , "throttle-query" )
211+ return setThrottle (true , "throttle-query" , base . NoThrottleReasonHint )
212212 }
213213 }
214214
215- return setThrottle (false , "" )
215+ return setThrottle (false , "" , base . NoThrottleReasonHint )
216216}
217217
218218// initiateThrottlerMetrics initiates the various processes that collect measurements
@@ -237,8 +237,8 @@ func (this *Throttler) initiateThrottlerChecks() error {
237237 throttlerTick := time .Tick (100 * time .Millisecond )
238238
239239 throttlerFunction := func () {
240- alreadyThrottling , currentReason := this .migrationContext .IsThrottled ()
241- shouldThrottle , throttleReason := this .shouldThrottle ()
240+ alreadyThrottling , currentReason , _ := this .migrationContext .IsThrottled ()
241+ shouldThrottle , throttleReason , throttleReasonHint := this .shouldThrottle ()
242242 if shouldThrottle && ! alreadyThrottling {
243243 // New throttling
244244 this .applier .WriteAndLogChangelog ("throttle" , throttleReason )
@@ -249,7 +249,7 @@ func (this *Throttler) initiateThrottlerChecks() error {
249249 // End of throttling
250250 this .applier .WriteAndLogChangelog ("throttle" , "done throttling" )
251251 }
252- this .migrationContext .SetThrottled (shouldThrottle , throttleReason )
252+ this .migrationContext .SetThrottled (shouldThrottle , throttleReason , throttleReasonHint )
253253 }
254254 throttlerFunction ()
255255 for range throttlerTick {
@@ -265,7 +265,7 @@ func (this *Throttler) throttle(onThrottled func()) {
265265 for {
266266 // IsThrottled() is non-blocking; the throttling decision making takes place asynchronously.
267267 // Therefore calling IsThrottled() is cheap
268- if shouldThrottle , _ := this .migrationContext .IsThrottled (); ! shouldThrottle {
268+ if shouldThrottle , _ , _ := this .migrationContext .IsThrottled (); ! shouldThrottle {
269269 return
270270 }
271271 if onThrottled != nil {
0 commit comments