diff --git a/lib/gat/handlers/pool/penalty.go b/lib/gat/handlers/pool/penalty.go index 790090a83b9ab4b9fbd8e6f75c66adb4938f3728..08a0f09f4f1c46613be19ffe97aa1866c5ca2889 100644 --- a/lib/gat/handlers/pool/penalty.go +++ b/lib/gat/handlers/pool/penalty.go @@ -2,7 +2,7 @@ package pool import "gfx.cafe/gfx/pggat/lib/fed" -type Penalty interface { +type Scorer interface { // Score calculates how much a recipe should be penalized. Lower is better Score(conn *fed.Conn) (int, error) } diff --git a/lib/gat/handlers/pool/penalties/latency/penalty.go b/lib/gat/handlers/pool/scorers/latency/scorer.go similarity index 63% rename from lib/gat/handlers/pool/penalties/latency/penalty.go rename to lib/gat/handlers/pool/scorers/latency/scorer.go index 7b607f0749e4c6c188c3320c3ed438344f1a9dc7..7c1648895500e091032e781c43320aa2872e634f 100644 --- a/lib/gat/handlers/pool/penalties/latency/penalty.go +++ b/lib/gat/handlers/pool/scorers/latency/scorer.go @@ -11,23 +11,23 @@ import ( ) func init() { - caddy.RegisterModule((*Penalty)(nil)) + caddy.RegisterModule((*Scorer)(nil)) } -type Penalty struct { +type Scorer struct { Threshold caddy.Duration `json:"threshold"` } -func (T *Penalty) CaddyModule() caddy.ModuleInfo { +func (T *Scorer) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ - ID: "pggat.handlers.pool.penalties.latency", + ID: "pggat.handlers.pool.scorers.latency", New: func() caddy.Module { - return new(Penalty) + return new(Scorer) }, } } -func (T *Penalty) Score(conn *fed.Conn) (int, error) { +func (T *Scorer) Score(conn *fed.Conn) (int, error) { start := time.Now() err, _ := backends.QueryString(conn, nil, "select 0") if err != nil { @@ -38,5 +38,5 @@ func (T *Penalty) Score(conn *fed.Conn) (int, error) { return penalty, nil } -var _ pool.Penalty = (*Penalty)(nil) -var _ caddy.Module = (*Penalty)(nil) +var _ pool.Scorer = (*Scorer)(nil) +var _ caddy.Module = (*Scorer)(nil) diff --git a/lib/gat/handlers/pool/spool/config.go b/lib/gat/handlers/pool/spool/config.go index e07415c4c404a40c1473ad924f29d7cffaa3e058..a808dbc39330bfc1bf8ac686b1934ff07a55053b 100644 --- a/lib/gat/handlers/pool/spool/config.go +++ b/lib/gat/handlers/pool/spool/config.go @@ -23,8 +23,9 @@ type Config struct { ReconnectInitialTime time.Duration ReconnectMaxTime time.Duration - PenaltyPeriod time.Duration - Penalties []pool.Penalty + // ScorePeriod defines how long a score should last before being recalculated. + ScorePeriod time.Duration + Scorers []pool.Scorer Logger *zap.Logger } diff --git a/lib/gat/handlers/pool/spool/pool.go b/lib/gat/handlers/pool/spool/pool.go index dadc9aab96f66ba1362294189d05707ae28dbcb2..c112dc1ef2c63f7c66161c8be1181854616dbfe4 100644 --- a/lib/gat/handlers/pool/spool/pool.go +++ b/lib/gat/handlers/pool/spool/pool.go @@ -25,7 +25,7 @@ type Pool struct { recipes map[string]*Recipe recipeScaleOrder []*Recipe - lastPenalize time.Time + lastScore time.Time servers map[uuid.UUID]*Server mu sync.RWMutex } @@ -59,53 +59,54 @@ func (T *Pool) removeServer(server *Server, deleteFromRecipe, freeFromRecipe boo } } -func (T *Pool) penalizeRecipe(recipe *Recipe) error { +func (T *Pool) scoreRecipe(recipe *Recipe) error { T.mu.RUnlock() defer T.mu.RLock() - recipe.Penalty = 0 + recipe.Score = 0 conn, err := recipe.Recipe.Dial() if err != nil { + recipe.Score = math.MaxInt return err } defer func() { _ = conn.Close() }() - for _, penalty := range T.config.Penalties { + for _, penalty := range T.config.Scorers { var p int p, err = penalty.Score(conn) if err != nil { + recipe.Score = math.MaxInt return err } - recipe.Penalty += p + recipe.Score += p } return nil } func (T *Pool) sortRecipes() { - if len(T.config.Penalties) > 0 && time.Since(T.lastPenalize) > T.config.PenaltyPeriod { + if len(T.config.Scorers) > 0 && time.Since(T.lastScore) > T.config.ScorePeriod { for _, recipe := range T.recipes { - if err := T.penalizeRecipe(recipe); err != nil { + if err := T.scoreRecipe(recipe); err != nil { T.config.Logger.Error("failed to score recipe", zap.Error(err)) - recipe.Penalty = math.MaxInt } } - T.lastPenalize = time.Now() + T.lastScore = time.Now() } sort.Slice(T.recipeScaleOrder, func(i, j int) bool { a := T.recipeScaleOrder[i] b := T.recipeScaleOrder[j] // sort by priority first - if a.Score() < b.Score() { + if a.Priority() < b.Priority() { return true } - if a.Score() > b.Score() { + if a.Priority() > b.Priority() { return false } // then sort by number of servers diff --git a/lib/gat/handlers/pool/spool/recipe.go b/lib/gat/handlers/pool/spool/recipe.go index ee7700bd5d9bd5292743b7e209e68a38eaaeb7a0..f358b3aa3e152b2ea2dd711769d33a78030f1959 100644 --- a/lib/gat/handlers/pool/spool/recipe.go +++ b/lib/gat/handlers/pool/spool/recipe.go @@ -6,7 +6,7 @@ type Recipe struct { Name string Recipe *pool.Recipe - Penalty int + Score int Servers []*Server } @@ -18,6 +18,6 @@ func NewRecipe(name string, recipe *pool.Recipe) *Recipe { } } -func (T *Recipe) Score() int { - return T.Recipe.Priority + T.Penalty +func (T *Recipe) Priority() int { + return T.Recipe.Priority + T.Score }