3 Commits

Author SHA1 Message Date
c4c66b5c23 Resolve issue with client reference 2019-10-13 00:42:08 -04:00
ef903095c9 Full support for changing nodes 2019-10-13 00:04:01 -04:00
ba383db391 Implement node auto switching 2019-10-12 23:57:59 -04:00
3 changed files with 68 additions and 26 deletions

View File

@ -3,8 +3,10 @@ package gavalink
import ( import (
"errors" "errors"
"log" "log"
"net/http"
"os" "os"
"sort" "sort"
"time"
) )
// Log sets the log.Logger gavalink will write to // Log sets the log.Logger gavalink will write to
@ -19,8 +21,10 @@ type Lavalink struct {
shards string shards string
userID string userID string
nodes []Node nodes []*Node
players map[string]*Player players map[string]*Player
BestNodeFunc func([]*Node) (*Node, error)
} }
var ( var (
@ -38,19 +42,25 @@ func NewLavalink(shards string, userID string) *Lavalink {
return &Lavalink{ return &Lavalink{
shards: shards, shards: shards,
userID: userID, userID: userID,
/* nodes: make([]Node, 1),*/
players: make(map[string]*Player), players: make(map[string]*Player),
BestNodeFunc: BestNodeByLoad,
} }
} }
// AddNodes adds a node to the Lavalink manager // AddNodes adds a node to the Lavalink manager
func (lavalink *Lavalink) AddNodes(nodeConfigs ...NodeConfig) error { func (lavalink *Lavalink) AddNodes(nodeConfigs ...NodeConfig) error {
nodes := make([]Node, len(nodeConfigs)) nodes := make([]*Node, len(nodeConfigs))
client := &http.Client{
Timeout: 60 * time.Second,
}
for i, c := range nodeConfigs { for i, c := range nodeConfigs {
n := Node{ n := &Node{
config: c, config: c,
manager: lavalink, manager: lavalink,
client: client,
} }
err := n.open() err := n.open()
@ -71,7 +81,7 @@ func (lavalink *Lavalink) AddNodes(nodeConfigs ...NodeConfig) error {
func (lavalink *Lavalink) removeNode(node *Node) error { func (lavalink *Lavalink) removeNode(node *Node) error {
idx := -1 idx := -1
for i, n := range lavalink.nodes { for i, n := range lavalink.nodes {
if n == *node { if n == node {
idx = i idx = i
break break
} }
@ -82,6 +92,18 @@ func (lavalink *Lavalink) removeNode(node *Node) error {
node.stop() node.stop()
for _, player := range lavalink.players {
if player.node == node {
n, err := lavalink.BestNode()
if err != nil {
continue
}
player.ChangeNode(n)
}
}
// temp var for easier reading // temp var for easier reading
n := lavalink.nodes n := lavalink.nodes
z := len(n) - 1 z := len(n) - 1
@ -99,11 +121,7 @@ func (lavalink *Lavalink) BestNode() (*Node, error) {
return nil, errNoNodes return nil, errNoNodes
} }
sort.SliceStable(lavalink.nodes, func(i, j int) bool { return lavalink.BestNodeFunc(lavalink.nodes)
return lavalink.nodes[i].load < lavalink.nodes[j].load
})
return &lavalink.nodes[0], nil
} }
// GetPlayer gets a player for a guild // GetPlayer gets a player for a guild
@ -116,3 +134,11 @@ 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
}

View File

@ -184,10 +184,12 @@ func (node *Node) CreatePlayer(guildID string, sessionID string, event VoiceServ
player := &Player{ player := &Player{
guildID: guildID, guildID: guildID,
sessionID: sessionID,
manager: node.manager, manager: node.manager,
node: node, node: node,
handler: handler, handler: handler,
vol: 100, vol: 100,
lastVoiceServerUpdate: event,
} }
node.manager.players[guildID] = player node.manager.players[guildID] = player

View File

@ -7,6 +7,7 @@ import (
// Player is a Lavalink player // Player is a Lavalink player
type Player struct { type Player struct {
guildID string guildID string
sessionID string
time int time int
position int position int
paused bool paused bool
@ -15,6 +16,7 @@ type Player struct {
manager *Lavalink manager *Lavalink
node *Node node *Node
handler EventHandler handler EventHandler
lastVoiceServerUpdate VoiceServerUpdate
} }
// GuildID returns this player's Guild ID // GuildID returns this player's Guild ID
@ -166,6 +168,8 @@ func (player *Player) UserLeave(userId string) error {
// To move a player to a new Node, first player.Destroy() it, and then // To move a player to a new Node, first player.Destroy() it, and then
// create a new player on the new node. // create a new player on the new node.
func (player *Player) Forward(sessionID string, event VoiceServerUpdate) error { func (player *Player) Forward(sessionID string, event VoiceServerUpdate) error {
player.sessionID = sessionID
msg := voiceUpdateMessage{ msg := voiceUpdateMessage{
Op: opVoiceUpdate, Op: opVoiceUpdate,
GuildID: player.guildID, GuildID: player.guildID,
@ -173,9 +177,19 @@ func (player *Player) Forward(sessionID string, event VoiceServerUpdate) error {
Event: &event, Event: &event,
} }
player.lastVoiceServerUpdate = event
return player.node.wsConn.WriteJSON(msg) return player.node.wsConn.WriteJSON(msg)
} }
func (player *Player) ChangeNode(node *Node) error {
player.node = node
player.Forward(player.sessionID, player.lastVoiceServerUpdate)
return player.PlayAt(player.track, player.position, 0)
}
// Destroy will destroy this player // Destroy will destroy this player
func (player *Player) Destroy() error { func (player *Player) Destroy() error {
msg := basicMessage{ msg := basicMessage{