From 723aa0e4c31e7b87d2cb4d8c9b99e16b9bfdb97e Mon Sep 17 00:00:00 2001 From: diamondburned Date: Thu, 7 Apr 2022 23:27:34 -0700 Subject: [PATCH] session: Add Gateway{IsAlive,Error} methods This commit adds the above 2 methods mostly for the user's convenience. GatewayIsAlive will be useful when handling CloseError events and determining if the session was fatal without needing to handle Open(). GatewayError builds upon GatewayIsAlive and returns an error. While the user could call GatewayIsAlive and LastError themselves, doing so without locking is technically racy if another thread wants to reconnect. --- session/session.go | 48 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/session/session.go b/session/session.go index 415539f..a0c9195 100644 --- a/session/session.go +++ b/session/session.go @@ -142,9 +142,51 @@ func (s *Session) HasIntents(intents gateway.Intents) bool { // or Session was never constructed with a gateway, then nil is returned. func (s *Session) Gateway() *gateway.Gateway { s.state.Lock() - g := s.state.gateway - s.state.Unlock() - return g + defer s.state.Unlock() + + return s.state.gateway +} + +// GatewayError returns the gateway's error if the gateway is dead. If it's not +// dead, then nil is always returned. The check is done with GatewayIsAlive(). +// If the gateway has never been started, nil will be returned (even though +// GatewayIsAlive would've returned true). +// +// This method would return what Close() would've returned if a fatal gateway +// error was found. +func (s *Session) GatewayError() error { + s.state.Lock() + defer s.state.Unlock() + + if !s.gatewayIsAlive() && s.state.gateway != nil { + return s.state.gateway.LastError() + } + + return nil +} + +// GatewayIsAlive returns true if the gateway is still alive, that is, it is +// either connected or is trying to reconnect after an interruption. In other +// words, false is returned if the gateway isn't open or it has exited after +// seeing a fatal error code (and therefore cannot recover). +func (s *Session) GatewayIsAlive() bool { + s.state.Lock() + defer s.state.Unlock() + + return s.gatewayIsAlive() +} + +func (s *Session) gatewayIsAlive() bool { + if s.state.gateway == nil || s.state.doneCh == nil { + return false + } + + select { + case <-s.state.doneCh: + return false + default: + return true + } } // Open opens the Discord gateway and its handler, then waits until either the