gateway: Skip unknown events while reconnecting (#255)

This change skips events that are unknown while the bot reconnects. This
is an event that is particularly rare as it requires unimplemented
events being called in the time before a bot's HELLO -> RESUME events
are called. This change explicitly returns unknown events as a special
time defined in wsutil/op.go and ignores them from reaching gateway/op.go
This commit is contained in:
Hamza Ali 2021-08-04 08:00:31 +07:00 committed by GitHub
parent 101fe46313
commit 0d7774bd6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 5 deletions

View File

@ -474,7 +474,8 @@ func (g *Gateway) start(ctx context.Context) error {
// Expect either READY or RESUMED before continuing.
wsutil.WSDebug("Waiting for either READY or RESUMED.")
// WaitForEvent should
// WaitForEvent should until the bot becomes ready or resumes (if a
// previous ready event has already been called).
err := wsutil.WaitForEvent(ctx, g, ch, func(op *wsutil.OP) bool {
switch op.EventName {
case "READY":

View File

@ -85,10 +85,10 @@ func (g *Gateway) HandleOP(op *wsutil.OP) error {
// Check if we know the event
fn, ok := EventCreator[op.EventName]
if !ok {
return fmt.Errorf(
"unknown event %s: %s",
op.EventName, string(op.Data),
)
return &wsutil.UnknownEventError{
Name: op.EventName,
Data: op.Data,
}
}
// Make a new pointer to the event

View File

@ -66,6 +66,25 @@ func AssertEvent(ev Event, code OPCode, v interface{}) (*OP, error) {
return op, nil
}
// UnknownEventError is required by HandleOP if an event is encountered that is
// not known. Internally, unknown events are logged and ignored. It is not a
// fatal error.
type UnknownEventError struct {
Name string
Data json.Raw
}
// Error formats the unknown event error to with the event name and payload
func (err UnknownEventError) Error() string {
return fmt.Sprintf("unknown event %s: %s", err.Name, string(err.Data))
}
// IsBrokenConnection returns true if the error is a broken connection error.
func IsUnknownEvent(err error) bool {
var uevent *UnknownEventError
return errors.As(err, &uevent)
}
type EventHandler interface {
HandleOP(op *OP) error
}
@ -98,6 +117,11 @@ func WaitForEvent(ctx context.Context, h EventHandler, ch <-chan Event, fn func(
// also prevent a race condition with things that need Ready after
// Open().
if err := h.HandleOP(o); err != nil {
// Explicitly ignore events we don't know.
if IsUnknownEvent(err) {
WSError(err)
continue
}
return err
}