1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2025-03-21 17:39:25 +00:00

Heartbeat can now resume, bot will fatal (die) if it can't reconnect

This commit is contained in:
diamondburned (Forefront) 2020-01-18 22:14:46 -08:00
parent 28228a60f5
commit 9651de81c6
3 changed files with 17 additions and 8 deletions

View file

@ -9,6 +9,7 @@ package gateway
import ( import (
"context" "context"
"log"
"net/url" "net/url"
"runtime" "runtime"
"time" "time"
@ -40,6 +41,9 @@ var (
WSRetries = uint(5) WSRetries = uint(5)
// WSError is the default error handler // WSError is the default error handler
WSError = func(err error) {} WSError = func(err error) {}
// WSFatal is the default fatal handler, which is called when the Gateway
// can't recover.
WSFatal = func(err error) { log.Fatalln("Gateway failed:", err) }
// WSExtraReadTimeout is the duration to be added to Hello, as a read // WSExtraReadTimeout is the duration to be added to Hello, as a read
// timeout for the websocket. // timeout for the websocket.
WSExtraReadTimeout = time.Second WSExtraReadTimeout = time.Second
@ -88,6 +92,7 @@ type Gateway struct {
Sequence *Sequence Sequence *Sequence
ErrorLog func(err error) // default to log.Println ErrorLog func(err error) // default to log.Println
FatalLog func(err error) // called when the WS can't reconnect and resume
// Only use for debugging // Only use for debugging
@ -121,6 +126,7 @@ func NewGatewayWithDriver(token string, driver json.Driver) (*Gateway, error) {
Identifier: DefaultIdentifier(token), Identifier: DefaultIdentifier(token),
Sequence: NewSequence(), Sequence: NewSequence(),
ErrorLog: WSError, ErrorLog: WSError,
FatalLog: WSFatal,
} }
// Parameters for the gateway // Parameters for the gateway
@ -258,10 +264,6 @@ func (g *Gateway) Start() error {
return nil return nil
} }
func (g *Gateway) Wait() error {
return <-g.paceDeath
}
// handleWS uses the Websocket and parses them into g.Events. // handleWS uses the Websocket and parses them into g.Events.
func (g *Gateway) handleWS(stop <-chan struct{}) { func (g *Gateway) handleWS(stop <-chan struct{}) {
ch := g.WS.Listen() ch := g.WS.Listen()
@ -270,6 +272,16 @@ func (g *Gateway) handleWS(stop <-chan struct{}) {
select { select {
case <-stop: case <-stop:
return return
case <-g.paceDeath:
// Pacemaker died, pretty fatal. We'll reconnect though.
if err := g.Reconnect(); err != nil {
// Very fatal if this fails. We'll warn the user.
g.FatalLog(errors.Wrap(err, "Failed to reconnect"))
// Then, we'll take the safe way and exit.
return
}
case ev := <-ch: case ev := <-ch:
// Check for error // Check for error
if ev.Error != nil { if ev.Error != nil {

View file

@ -41,7 +41,6 @@ func (p *Pacemaker) Dead() bool {
func (p *Pacemaker) Stop() { func (p *Pacemaker) Stop() {
if p.stop != nil { if p.stop != nil {
close(p.stop) close(p.stop)
p.stop = nil
} }
} }
@ -60,8 +59,6 @@ func (p *Pacemaker) start(stop chan struct{}) error {
// Echo at least once // Echo at least once
p.Echo() p.Echo()
// TODO: what happens if the heartbeat fails?
for { for {
select { select {
case <-stop: case <-stop:

View file

@ -11,7 +11,7 @@ import (
"golang.org/x/time/rate" "golang.org/x/time/rate"
) )
const DefaultTimeout = 10 * time.Second const DefaultTimeout = time.Minute
type Event struct { type Event struct {
Data []byte Data []byte