Gateway: Added reconnect timeout; fixed UA (#154)

* Gateway: use gateway version 8

* API: remove old v0.0.1 version tag

* Discord: fix typos

* Gateway: add timeout

* Gateway: revert to returning errors on ReconnectCtx
This commit is contained in:
Maximilian von Lindern 2020-10-30 21:41:04 +01:00 committed by GitHub
parent f3372e016a
commit 607250ae55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 12 deletions

View File

@ -21,7 +21,7 @@ var (
EndpointGatewayBot = EndpointGateway + "/bot"
)
var UserAgent = "DiscordBot (https://github.com/diamondburned/arikawa/v2, v0.0.1)"
var UserAgent = "DiscordBot (https://github.com/diamondburned/arikawa/v2)"
type Client struct {
*httputil.Client

View File

@ -128,7 +128,7 @@ const (
OverwriteMember
)
// UnmarshalJSON unmarshals both a string-quoteed number and a regular number
// UnmarshalJSON unmarshalls both a string-quoted number and a regular number
// into OverwriteType. We need to do this because Discord is so bad that they
// can't even handle 1s and 0s properly.
func (otype *OverwriteType) UnmarshalJSON(b []byte) error {

View File

@ -78,6 +78,13 @@ func BotURL(token string) (*BotData, error) {
type Gateway struct {
WS *wsutil.Websocket
WSTimeout time.Duration
// ReconnectTimeout is the timeout used during reconnection.
// If the a connection to the gateway can't be established before the
// duration passes, the Gateway will be closed and FatalErrorCallback will
// be called.
//
// Setting this to 0 is equivalent to no timeout.
ReconnectTimeout time.Duration
// All events sent over are pointers to Event structs (structs suffixed with
// "Event"). This shouldn't be accessed if the Gateway is created with a
@ -94,6 +101,16 @@ type Gateway struct {
PacerLoop wsutil.PacemakerLoop
ErrorLog func(err error) // default to log.Println
// FatalErrorCallback is called, if the Gateway exits fatally. At the point
// of calling, the gateway will be already closed.
//
// Currently this will only be called, if the ReconnectTimeout was changed
// to a definite timeout, and connection could not be established during
// that time.
// err will be ErrWSMaxTries in that case.
//
// Defaults to noop.
FatalErrorCallback func(err error)
// AfterClose is called after each close. Error can be non-nil, as this is
// called even when the Gateway is gracefully closed. It's used mainly for
@ -182,20 +199,25 @@ func (g *Gateway) Close() error {
return err
}
// Reconnect tries to reconnect forever. It will resume the connection if
// possible. If an Invalid Session is received, it will start a fresh one.
// Reconnect tries to reconnect until the ReconnectTimeout is reached, or if
// set to 0 reconnects indefinitely.
func (g *Gateway) Reconnect() {
for {
if err := g.ReconnectCtx(context.Background()); err != nil {
g.ErrorLog(err)
} else {
return
}
ctx := context.Background()
if g.ReconnectTimeout > 0 {
var cancel func()
ctx, cancel = context.WithTimeout(context.Background(), g.WSTimeout)
defer cancel()
}
// ignore the error, it is already logged and FatalErrorCallback was called
g.ReconnectCtx(ctx)
}
// ReconnectCtx attempts to reconnect until context expires. If context cannot
// expire, then the gateway will try to reconnect forever.
// ReconnectCtx attempts to reconnect until context expires.
// If the context expires FatalErrorCallback will be called with ErrWSMaxTries,
// and the last error returned by Open will be returned.
func (g *Gateway) ReconnectCtx(ctx context.Context) (err error) {
wsutil.WSDebug("Reconnecting...")
@ -206,6 +228,7 @@ func (g *Gateway) ReconnectCtx(ctx context.Context) (err error) {
for i := 1; ; i++ {
select {
case <-ctx.Done():
g.FatalErrorCallback(ErrWSMaxTries)
return err
default:
}