mirror of
https://github.com/diamondburned/arikawa.git
synced 2024-10-01 06:48:51 +00:00
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:
parent
f3372e016a
commit
607250ae55
|
@ -21,7 +21,7 @@ var (
|
||||||
EndpointGatewayBot = EndpointGateway + "/bot"
|
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 {
|
type Client struct {
|
||||||
*httputil.Client
|
*httputil.Client
|
||||||
|
|
|
@ -128,7 +128,7 @@ const (
|
||||||
OverwriteMember
|
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
|
// into OverwriteType. We need to do this because Discord is so bad that they
|
||||||
// can't even handle 1s and 0s properly.
|
// can't even handle 1s and 0s properly.
|
||||||
func (otype *OverwriteType) UnmarshalJSON(b []byte) error {
|
func (otype *OverwriteType) UnmarshalJSON(b []byte) error {
|
||||||
|
|
|
@ -78,6 +78,13 @@ func BotURL(token string) (*BotData, error) {
|
||||||
type Gateway struct {
|
type Gateway struct {
|
||||||
WS *wsutil.Websocket
|
WS *wsutil.Websocket
|
||||||
WSTimeout time.Duration
|
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
|
// 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
|
// "Event"). This shouldn't be accessed if the Gateway is created with a
|
||||||
|
@ -94,6 +101,16 @@ type Gateway struct {
|
||||||
PacerLoop wsutil.PacemakerLoop
|
PacerLoop wsutil.PacemakerLoop
|
||||||
|
|
||||||
ErrorLog func(err error) // default to log.Println
|
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
|
// 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
|
// called even when the Gateway is gracefully closed. It's used mainly for
|
||||||
|
@ -182,20 +199,25 @@ func (g *Gateway) Close() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reconnect tries to reconnect forever. It will resume the connection if
|
// Reconnect tries to reconnect until the ReconnectTimeout is reached, or if
|
||||||
// possible. If an Invalid Session is received, it will start a fresh one.
|
// set to 0 reconnects indefinitely.
|
||||||
func (g *Gateway) Reconnect() {
|
func (g *Gateway) Reconnect() {
|
||||||
for {
|
ctx := context.Background()
|
||||||
if err := g.ReconnectCtx(context.Background()); err != nil {
|
|
||||||
g.ErrorLog(err)
|
if g.ReconnectTimeout > 0 {
|
||||||
} else {
|
var cancel func()
|
||||||
return
|
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
|
// ReconnectCtx attempts to reconnect until context expires.
|
||||||
// expire, then the gateway will try to reconnect forever.
|
// 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) {
|
func (g *Gateway) ReconnectCtx(ctx context.Context) (err error) {
|
||||||
wsutil.WSDebug("Reconnecting...")
|
wsutil.WSDebug("Reconnecting...")
|
||||||
|
|
||||||
|
@ -206,6 +228,7 @@ func (g *Gateway) ReconnectCtx(ctx context.Context) (err error) {
|
||||||
for i := 1; ; i++ {
|
for i := 1; ; i++ {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
g.FatalErrorCallback(ErrWSMaxTries)
|
||||||
return err
|
return err
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue