Fixed bug where reconnect would fail

This commit is contained in:
diamondburned (Forefront) 2020-01-17 23:40:44 -08:00
parent 7f5a470024
commit 971c162d33
4 changed files with 26 additions and 11 deletions

View File

@ -150,7 +150,10 @@ func (g *Gateway) Close() error {
g.Pacemaker.Stop()
// Stop the event handler
defer close(g.handler)
if g.handler != nil {
close(g.handler)
g.handler = nil
}
// Stop the Websocket
return g.WS.Close(nil)
@ -190,7 +193,10 @@ func (g *Gateway) Open() error {
// If the connection is rate limited (documented behavior):
// https://discordapp.com/developers/docs/topics/gateway#rate-limiting
if err == ErrInvalidSession {
continue // retry
// Close the connection
g.Close()
continue // then retry
}
// Else, fatal

View File

@ -32,9 +32,10 @@ func TestIntegration(t *testing.T) {
t.Fatal("Failed to authenticate with Discord:", err)
}
ready, ok := wait(t, gateway.Events).(*ReadyEvent)
ev := wait(t, gateway.Events)
ready, ok := ev.(*ReadyEvent)
if !ok {
t.Fatal("Event received is not of type Ready:", ready)
t.Fatal("Event received is not of type Ready:", ev)
}
if gateway.SessionID == "" {
@ -48,18 +49,15 @@ func TestIntegration(t *testing.T) {
t.Fatal("Failed to reconnect:", err)
}
/* TODO: this isn't true, as Discord would keep sending Invalid Sessions.
/* TODO: We're not testing this, as Discord will replay events before it
* sends the Resumed event.
resumed, ok := (<-gateway.Events).(*ResumedEvent)
if !ok {
t.Fatal("Event received is not of type Resumed:", resumed)
}
*/
ready, ok = wait(t, gateway.Events).(*ReadyEvent)
if !ok {
t.Fatal("Event received is not of type Ready:", ready)
}
if err := g.Close(); err != nil {
t.Fatal("Failed to close Gateway:", err)
}

View File

@ -2,6 +2,8 @@ package gateway
import (
"fmt"
"math/rand"
"time"
"github.com/diamondburned/arikawa/internal/json"
"github.com/diamondburned/arikawa/internal/wsutil"
@ -122,6 +124,9 @@ func HandleOP(g *Gateway, op *OP) error {
return g.Reconnect()
case InvalidSessionOP:
// Discord expects us to sleep for no reason
time.Sleep(time.Duration(rand.Intn(5)+1) * time.Second)
// Invalid session, respond with Identify.
return g.Identify()

View File

@ -39,7 +39,10 @@ func (p *Pacemaker) Dead() bool {
}
func (p *Pacemaker) Stop() {
close(p.stop)
if p.stop != nil {
close(p.stop)
p.stop = nil
}
}
// Start beats until it's dead.
@ -57,10 +60,13 @@ func (p *Pacemaker) start(stop chan struct{}) error {
// Echo at least once
p.Echo()
// TODO: what happens if the heartbeat fails?
for {
select {
case <-stop:
return nil
case <-tick.C:
if err := p.Pace(); err != nil {
return err