// Package choose picks the host for a new lease: among the healthy, non-draining, known hosts it // prefers those that have the model loaded over those that would only be able to serve it, then the // one with the most free slots times weight, breaking ties by shortest queue and finally list // order. package choose // Info is one candidate host's view of itself for a single model. type Info struct { Healthy bool // answered its last poll Draining bool // operator is draining it; no new leases Loaded bool // the model is resident here CanServe bool // config lists the model, so we may load it Free int Queued int Weight float64 } // Best returns the best host for a new lease, or ok=false when nothing is eligible. It runs two // passes over the candidates in order: the first over those that have the model loaded, the second, // only if the first found nothing, over those that can serve it. A host must be healthy, not // draining, and known (info reported ok) to be eligible in either pass; a host with zero free slots // is still eligible, since it will queue. Among the eligible ones the highest Free*Weight wins, ties // go to the lowest queue, and a remaining tie keeps the earlier candidate. func Best(candidates []string, info func(host string) (Info, bool)) (string, bool) { const ( passLoaded = 0 passCanServe = 1 ) best := "" var ( bestScore float64 bestQueued int found bool ) for pass := passLoaded; pass <= passCanServe; pass++ { for _, host := range candidates { v, ok := info(host) if !ok || !v.Healthy || v.Draining { continue } switch pass { case passLoaded: if !v.Loaded { continue } case passCanServe: if !v.CanServe { continue } } score := float64(v.Free) * v.Weight // Replace only when strictly better on score, or equal score with a shorter queue; a // further tie keeps the earlier candidate because we scan in order and use "<". if !found || score > bestScore || (score == bestScore && v.Queued < bestQueued) { best, bestScore, bestQueued, found = host, score, v.Queued, true } } if found { break } } return best, found }