57 lines
1.2 KiB
Go
57 lines
1.2 KiB
Go
package main
|
|
|
|
import (
|
|
"sort"
|
|
"sync"
|
|
)
|
|
|
|
const (
|
|
penaltyBumpOn429503 = 5
|
|
penaltyDecaySuccess = 1
|
|
)
|
|
|
|
var backendPenalties = struct {
|
|
sync.Mutex
|
|
scores map[routeBackend]int
|
|
}{
|
|
scores: make(map[routeBackend]int),
|
|
}
|
|
|
|
func recordBackendFailure(backend routeBackend) {
|
|
backendPenalties.Lock()
|
|
defer backendPenalties.Unlock()
|
|
backendPenalties.scores[backend] += penaltyBumpOn429503
|
|
}
|
|
|
|
func recordBackendSuccess(backend routeBackend) {
|
|
backendPenalties.Lock()
|
|
defer backendPenalties.Unlock()
|
|
score := backendPenalties.scores[backend] - penaltyDecaySuccess
|
|
if score < 0 {
|
|
score = 0
|
|
}
|
|
backendPenalties.scores[backend] = score
|
|
}
|
|
|
|
func penaltyScore(backend routeBackend) int {
|
|
backendPenalties.Lock()
|
|
defer backendPenalties.Unlock()
|
|
return backendPenalties.scores[backend]
|
|
}
|
|
|
|
func sortBackendsByPenalty(backends []routeBackend) []routeBackend {
|
|
if len(backends) <= 1 {
|
|
return append([]routeBackend(nil), backends...)
|
|
}
|
|
out := append([]routeBackend(nil), backends...)
|
|
sort.SliceStable(out, func(i, j int) bool {
|
|
return penaltyScore(out[i]) < penaltyScore(out[j])
|
|
})
|
|
return out
|
|
}
|
|
|
|
func resetBackendPenaltiesForTest() {
|
|
backendPenalties.Lock()
|
|
defer backendPenalties.Unlock()
|
|
backendPenalties.scores = make(map[routeBackend]int)
|
|
}
|