Implement proper (partial) penalty support
This commit is contained in:
parent
c4c66b5c23
commit
1bb3b36df6
|
@ -0,0 +1,43 @@
|
||||||
|
package gavalink
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
type balancePenalty struct {
|
||||||
|
node *Node
|
||||||
|
penalty int
|
||||||
|
}
|
||||||
|
|
||||||
|
func BestNodeByPenalties(nodes []*Node) (*Node, error) {
|
||||||
|
penalties := make([]*balancePenalty, len(nodes))
|
||||||
|
|
||||||
|
var playerPenalty, cpuPenalty int
|
||||||
|
|
||||||
|
for i, node := range nodes {
|
||||||
|
if node.stats == nil {
|
||||||
|
penalties[i] = &balancePenalty{node, 1}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
playerPenalty = node.stats.ActivePlayers
|
||||||
|
cpuPenalty = int(math.Pow(1.05, 100*node.stats.Cpu.SystemLoad)*10 - 10)
|
||||||
|
|
||||||
|
penalties[i] = &balancePenalty{node, playerPenalty + cpuPenalty}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.SliceStable(penalties, func(i, j int) bool {
|
||||||
|
return penalties[i].penalty < penalties[j].penalty
|
||||||
|
})
|
||||||
|
|
||||||
|
return penalties[0].node, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BestNodeByLoad(n []*Node) (*Node, error) {
|
||||||
|
sort.SliceStable(n, func(i, j int) bool {
|
||||||
|
return n[i].stats.Cpu.LavalinkLoad < n[j].stats.Cpu.LavalinkLoad
|
||||||
|
})
|
||||||
|
|
||||||
|
return n[0], nil
|
||||||
|
}
|
11
lavalink.go
11
lavalink.go
|
@ -5,7 +5,6 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -44,7 +43,7 @@ func NewLavalink(shards string, userID string) *Lavalink {
|
||||||
userID: userID,
|
userID: userID,
|
||||||
players: make(map[string]*Player),
|
players: make(map[string]*Player),
|
||||||
|
|
||||||
BestNodeFunc: BestNodeByLoad,
|
BestNodeFunc: BestNodeByPenalties,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,11 +133,3 @@ func (lavalink *Lavalink) GetPlayer(guild string) (*Player, error) {
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func BestNodeByLoad(n []*Node) (*Node, error) {
|
|
||||||
sort.SliceStable(n, func(i, j int) bool {
|
|
||||||
return n[i].load < n[j].load
|
|
||||||
})
|
|
||||||
|
|
||||||
return n[0], nil
|
|
||||||
}
|
|
||||||
|
|
39
node.go
39
node.go
|
@ -29,12 +29,34 @@ type NodeConfig struct {
|
||||||
// Node wraps a Lavalink Node
|
// Node wraps a Lavalink Node
|
||||||
type Node struct {
|
type Node struct {
|
||||||
config NodeConfig
|
config NodeConfig
|
||||||
load float32
|
stats *RemoteStats
|
||||||
manager *Lavalink
|
manager *Lavalink
|
||||||
wsConn *websocket.Conn
|
wsConn *websocket.Conn
|
||||||
client *http.Client
|
client *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RemoteStats struct {
|
||||||
|
Op string `json:"op"`
|
||||||
|
Players int `json:"players"`
|
||||||
|
ActivePlayers int `json:"playingPlayers"`
|
||||||
|
Uptime int64 `json:"uptime"`
|
||||||
|
Memory *MemoryStats `json:"memory"`
|
||||||
|
Cpu *CpuStats `json:"cpu"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MemoryStats struct {
|
||||||
|
Free uint64 `json:"free"`
|
||||||
|
Used uint64 `json:"used"`
|
||||||
|
Allocated uint64 `json:"allocated"`
|
||||||
|
Reserveable uint64 `json:"reserveable"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CpuStats struct {
|
||||||
|
Cores int `json:"cores"`
|
||||||
|
SystemLoad float64 `json:"systemLoad"`
|
||||||
|
LavalinkLoad float64 `json:"lavalinkLoad"`
|
||||||
|
}
|
||||||
|
|
||||||
func (node *Node) open() error {
|
func (node *Node) open() error {
|
||||||
header := http.Header{}
|
header := http.Header{}
|
||||||
|
|
||||||
|
@ -108,16 +130,25 @@ func (node *Node) listen() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
node.onEvent(v)
|
node.onEvent(v, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *Node) onEvent(v *fastjson.Value) error {
|
func (node *Node) onEvent(v *fastjson.Value, msg []byte) error {
|
||||||
op := jsonStringValue(v, "op")
|
op := jsonStringValue(v, "op")
|
||||||
|
|
||||||
switch op {
|
switch op {
|
||||||
|
case opStats:
|
||||||
|
node.stats = &RemoteStats{}
|
||||||
|
|
||||||
|
err := json.Unmarshal(msg, &node.stats)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case opPlayerUpdate:
|
case opPlayerUpdate:
|
||||||
player, err := node.manager.GetPlayer(jsonStringValue(v, "guildId"))
|
player, err := node.manager.GetPlayer(jsonStringValue(v, "guildId"))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -158,8 +189,6 @@ func (node *Node) onEvent(v *fastjson.Value) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
return player.handler.OnVoiceProcessed(player, data, v.GetBool("hotword"), v.GetBool("override"))
|
return player.handler.OnVoiceProcessed(player, data, v.GetBool("hotword"), v.GetBool("override"))
|
||||||
case opStats:
|
|
||||||
node.load = float32(v.GetFloat64("cpu", "lavalinkLoad"))
|
|
||||||
default:
|
default:
|
||||||
return errUnknownPayload
|
return errUnknownPayload
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue