feature: track node load, account for this when selecting a node

This commit is contained in:
Christopher F 2018-08-23 18:29:58 -04:00
parent 35bfb14058
commit d3a75d1dab
3 changed files with 38 additions and 20 deletions

View File

@ -4,13 +4,14 @@ import (
"errors" "errors"
"log" "log"
"os" "os"
"sort"
) )
// Log sets the log.Logger gavalink will write to // Log sets the log.Logger gavalink will write to
var Log *log.Logger var Log *log.Logger
func init() { func init() {
Log = log.New(os.Stdout, "(gavalink)", 0) Log = log.New(os.Stdout, "(gavalink) ", 0)
} }
// Lavalink manages a connection to Lavalink Nodes // Lavalink manages a connection to Lavalink Nodes
@ -91,7 +92,11 @@ func (lavalink *Lavalink) BestNode() (*Node, error) {
if len(lavalink.nodes) < 1 { if len(lavalink.nodes) < 1 {
return nil, errNoNodes return nil, errNoNodes
} }
// TODO: lookup latency
sort.SliceStable(lavalink.nodes, func(i, j int) bool {
return lavalink.nodes[i].load < lavalink.nodes[j].load
})
return &lavalink.nodes[0], nil return &lavalink.nodes[0], nil
} }

View File

@ -62,27 +62,29 @@ const (
opDestroy = "destroy" opDestroy = "destroy"
opPlayerUpdate = "playerUpdate" opPlayerUpdate = "playerUpdate"
opEvent = "event" opEvent = "event"
opStats = "stats"
eventTrackEnd = "TrackEndEvent" eventTrackEnd = "TrackEndEvent"
eventTrackException = "TrackExceptionEvent" eventTrackException = "TrackExceptionEvent"
eventTrackStuck = "TrackStuckEvent" eventTrackStuck = "TrackStuckEvent"
) )
type message struct { type message struct {
Op string `json:"op"` Op string `json:"op"`
GuildID string `json:"guildId,omitempty"` GuildID string `json:"guildId,omitempty"`
SessionID string `json:"sessionId,omitempty"` SessionID string `json:"sessionId,omitempty"`
Event *VoiceServerUpdate `json:"event,omitempty"` Event VoiceServerUpdate `json:"event,omitempty"`
Track string `json:"track,omitempty"` Track string `json:"track,omitempty"`
StartTime string `json:"startTime,omitempty"` StartTime string `json:"startTime,omitempty"`
EndTime string `json:"endTime,omitempty"` EndTime string `json:"endTime,omitempty"`
Pause bool `json:"pause,omitempty"` Pause bool `json:"pause,omitempty"`
Position int `json:"position,omitempty"` Position int `json:"position,omitempty"`
Volume int `json:"volume,omitempty"` Volume int `json:"volume,omitempty"`
State *state `json:"state,omitempty"` State state `json:"state,omitempty"`
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
Reason string `json:"reason,omitempty"` Reason string `json:"reason,omitempty"`
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
ThresholdMs int `json:"thresholdMs,omitempty"` ThresholdMs int `json:"thresholdMs,omitempty"`
StatCPU statCPU `json:"cpu,omitempty"`
// TODO: stats // TODO: stats
} }
@ -91,6 +93,10 @@ type state struct {
Position int `json:"position"` Position int `json:"position"`
} }
type statCPU struct {
Load float32 `json:"lavalinkLoad"`
}
// VoiceServerUpdate is a raw Discord VOICE_SERVER_UPDATE event // VoiceServerUpdate is a raw Discord VOICE_SERVER_UPDATE event
type VoiceServerUpdate struct { type VoiceServerUpdate struct {
GuildID string `json:"guild_id"` GuildID string `json:"guild_id"`

13
node.go
View File

@ -29,6 +29,7 @@ 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
manager *Lavalink manager *Lavalink
wsConn *websocket.Conn wsConn *websocket.Conn
} }
@ -84,8 +85,11 @@ func (node *Node) listen() {
return return
} }
err = node.onEvent(msgType, msg) err = node.onEvent(msgType, msg)
// TODO: better error handling // TODO: better error handling?
Log.Println(err)
if err != nil {
Log.Println(err)
}
} }
} }
@ -124,6 +128,9 @@ func (node *Node) onEvent(msgType int, msg []byte) error {
} }
return err return err
case opStats:
node.load = m.StatCPU.Load
Log.Println("dbg-node", node.config.WebSocket, "load", node.load)
default: default:
return errUnknownPayload return errUnknownPayload
} }
@ -137,7 +144,7 @@ func (node *Node) CreatePlayer(guildID string, sessionID string, event VoiceServ
Op: opVoiceUpdate, Op: opVoiceUpdate,
GuildID: guildID, GuildID: guildID,
SessionID: sessionID, SessionID: sessionID,
Event: &event, Event: event,
} }
data, err := json.Marshal(msg) data, err := json.Marshal(msg)
if err != nil { if err != nil {