81 lines
2.9 KiB
Go
81 lines
2.9 KiB
Go
package domain
|
|
|
|
import (
|
|
"errors"
|
|
"slices"
|
|
"sort"
|
|
|
|
"git.cin.su/m/Assistant/contracts/capability"
|
|
)
|
|
|
|
var ErrInvalidFleetReadiness = errors.New("invalid fleet readiness")
|
|
|
|
func BuildFleetReadiness(observedAt int64, members []capability.FleetMember) (capability.FleetReadiness, error) {
|
|
if observedAt < 1 || len(members) == 0 {
|
|
return capability.FleetReadiness{}, ErrInvalidFleetReadiness
|
|
}
|
|
result := capability.FleetReadiness{ObservedAtUnixMillis: observedAt, Members: append([]capability.FleetMember(nil), members...), FallbackTier: capability.FleetTierLifeboat}
|
|
seen := map[capability.FleetTier]bool{}
|
|
for i := range result.Members {
|
|
member := &result.Members[i]
|
|
if member.ProviderInstanceID == "" || member.ModelDescriptorID == "" || !validFleetTier(member.Tier) || seen[member.Tier] && member.Ready {
|
|
return capability.FleetReadiness{}, ErrInvalidFleetReadiness
|
|
}
|
|
if member.Ready {
|
|
seen[member.Tier] = true
|
|
}
|
|
}
|
|
for _, tier := range []capability.FleetTier{capability.FleetTierFast, capability.FleetTierMedium, capability.FleetTierHeavy, capability.FleetTierLifeboat} {
|
|
if seen[tier] {
|
|
result.ReadyTiers = append(result.ReadyTiers, tier)
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func SelectFleetTier(readiness capability.FleetReadiness, preferred capability.FleetTier) (capability.FleetTier, error) {
|
|
if readiness.ObservedAtUnixMillis < 1 || len(readiness.Members) == 0 || !validFleetTier(readiness.FallbackTier) {
|
|
return "", ErrInvalidFleetReadiness
|
|
}
|
|
if !validFleetTier(preferred) {
|
|
return "", ErrInvalidFleetReadiness
|
|
}
|
|
for _, tier := range fleetFailoverOrder(preferred) {
|
|
if slices.Contains(readiness.ReadyTiers, tier) {
|
|
return tier, nil
|
|
}
|
|
}
|
|
if slices.Contains(readiness.ReadyTiers, readiness.FallbackTier) {
|
|
return readiness.FallbackTier, nil
|
|
}
|
|
return "", ErrInvalidFleetReadiness
|
|
}
|
|
|
|
func fleetFailoverOrder(preferred capability.FleetTier) []capability.FleetTier {
|
|
switch preferred {
|
|
case capability.FleetTierHeavy:
|
|
return []capability.FleetTier{capability.FleetTierHeavy, capability.FleetTierMedium, capability.FleetTierFast}
|
|
case capability.FleetTierMedium:
|
|
return []capability.FleetTier{capability.FleetTierMedium, capability.FleetTierFast}
|
|
case capability.FleetTierFast:
|
|
return []capability.FleetTier{capability.FleetTierFast, capability.FleetTierMedium, capability.FleetTierHeavy}
|
|
case capability.FleetTierLifeboat:
|
|
return []capability.FleetTier{capability.FleetTierLifeboat}
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func validFleetTier(value capability.FleetTier) bool {
|
|
return value == capability.FleetTierFast || value == capability.FleetTierMedium || value == capability.FleetTierHeavy || value == capability.FleetTierLifeboat
|
|
}
|
|
|
|
func SortFleetMembers(members []capability.FleetMember) {
|
|
sort.SliceStable(members, func(i, j int) bool {
|
|
if members[i].Tier != members[j].Tier {
|
|
return members[i].Tier < members[j].Tier
|
|
}
|
|
return members[i].ProviderInstanceID < members[j].ProviderInstanceID
|
|
})
|
|
}
|