in core/circuitbreaker/circuit_breaker.go [494:548]
func (b *errorRatioCircuitBreaker) OnRequestComplete(_ uint64, err error) {
metricStat := b.stat
counter, curErr := metricStat.currentCounter()
if curErr != nil {
logging.Error(curErr, "Fail to get current counter in errorRatioCircuitBreaker#OnRequestComplete().",
"rule", b.rule)
return
}
if err != nil {
atomic.AddUint64(&counter.errorCount, 1)
}
atomic.AddUint64(&counter.totalCount, 1)
errorCount := uint64(0)
totalCount := uint64(0)
counters := metricStat.allCounter()
for _, c := range counters {
errorCount += atomic.LoadUint64(&c.errorCount)
totalCount += atomic.LoadUint64(&c.totalCount)
}
errorRatio := float64(errorCount) / float64(totalCount)
// handleStateChangeWhenThresholdExceeded
curStatus := b.CurrentState()
if curStatus == Open {
return
}
if curStatus == HalfOpen {
if err == nil {
b.addCurProbeNum()
if b.probeNumber == 0 || atomic.LoadUint64(&b.curProbeNumber) >= b.probeNumber {
b.fromHalfOpenToClosed()
b.resetMetric()
}
} else {
b.fromHalfOpenToOpen(1.0)
}
return
}
// current state is CLOSED
if totalCount < b.minRequestAmount {
return
}
if errorRatio > b.errorRatioThreshold || util.Float64Equals(errorRatio, b.errorRatioThreshold) {
curStatus = b.CurrentState()
switch curStatus {
case Closed:
b.fromClosedToOpen(errorRatio)
case HalfOpen:
b.fromHalfOpenToOpen(errorRatio)
default:
}
}
}