improve ERROR event handling

This commit is contained in:
Liam Stanley 2017-10-19 19:51:57 -04:00
parent 0a98091e3d
commit 9fdd4e9274
2 changed files with 33 additions and 3 deletions

View File

@ -266,7 +266,22 @@ func (c *Client) Close() {
c.mu.RUnlock()
}
func (c *Client) execLoop(ctx context.Context, wg *sync.WaitGroup) {
// ErrEvent is an error returned when the server (or library) sends an ERROR
// message response. The string returned contains the trailing text from the
// message.
type ErrEvent struct {
Event *Event
}
func (e *ErrEvent) Error() string {
if e.Event == nil {
return "unknown error occurred"
}
return e.Event.Trailing
}
func (c *Client) execLoop(ctx context.Context, errs chan error, wg *sync.WaitGroup) {
c.debug.Print("starting execLoop")
defer c.debug.Print("closing execLoop")
@ -292,6 +307,21 @@ func (c *Client) execLoop(ctx context.Context, wg *sync.WaitGroup) {
wg.Done()
return
case event = <-c.rx:
if event != nil && event.Command == ERROR {
// Handles incoming ERROR responses. These are only ever sent
// by the server (with the exception that this library may use
// them as a lower level way of signalling to disconnect due
// to some other client-choosen error), and should always be
// followed up by the server disconnecting the client. If for
// some reason the server doesn't disconnect the client, or
// if this library is the source of the error, this should
// signal back up to the main connect loop, to disconnect.
errs <- &ErrEvent{Event: event}
// Make sure to not actually exit, so we can let any handlers
// actually handle the ERROR event.
}
c.RunHandlers(event)
}
}

View File

@ -273,12 +273,12 @@ func (c *Client) internalConnect(mock net.Conn, dialer Dialer) error {
ctx, c.stop = context.WithCancel(context.Background())
c.mu.Unlock()
errs := make(chan error, 3)
errs := make(chan error, 4)
var wg sync.WaitGroup
// 4 being the number of goroutines we need to finish when this function
// returns.
wg.Add(4)
go c.execLoop(ctx, &wg)
go c.execLoop(ctx, errs, &wg)
go c.readLoop(ctx, errs, &wg)
go c.sendLoop(ctx, errs, &wg)
go c.pingLoop(ctx, errs, &wg)