Gateway: Add connection timeout, add Config to gateway. (#51)
This change fixes tasks hanging due to rare cases of messages being lost between full Discord reconnections by placing a configurable timeout on the `ConnectionInfo` responses. This is a companion fix to [serenity#1255](https://github.com/serenity-rs/serenity/pull/1255). To make this doable, `Config`s are now used by all versions of `Songbird`/`Call`, and relevant functions are added to simplify setup with configuration. These are now non-exhaustive, correcting an earlier oversight. For future extensibility, this PR moves the return type of `join`/`join_gateway` into a custom future (no longer leaking flume's `RecvFut` type). Additionally, this fixes the Makefile's feature sets for driver/gateway-only compilation. This is a breaking change in: * the return types of `join`/`join_gateway` * moving `crate::driver::Config` -> `crate::Config`, * `Config` and `JoinError` becoming `#[non_breaking]`. This was tested via `cargo make ready`, and by testing `examples/serenity/voice_receive` with various timeout settings.
This commit is contained in:
42
src/error.rs
42
src/error.rs
@@ -11,6 +11,7 @@ use twilight_gateway::shard::CommandError;
|
||||
|
||||
#[cfg(feature = "gateway-core")]
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
/// Error returned when a manager or call handler is
|
||||
/// unable to send messages over Discord's gateway.
|
||||
pub enum JoinError {
|
||||
@@ -23,8 +24,23 @@ pub enum JoinError {
|
||||
///
|
||||
/// [`Call`]: crate::Call
|
||||
NoCall,
|
||||
/// Connection details were not received from Discord in the
|
||||
/// time given in [the `Call`'s configuration].
|
||||
///
|
||||
/// This can occur if a message is lost by the Discord client
|
||||
/// between restarts, or if Discord's gateway believes that
|
||||
/// this bot is still in the channel it attempts to join.
|
||||
///
|
||||
/// *Users should `leave` the server on the gateway before
|
||||
/// re-attempting connection.*
|
||||
///
|
||||
/// [the `Call`'s configuration]: crate::Config
|
||||
TimedOut,
|
||||
#[cfg(feature = "driver-core")]
|
||||
/// The driver failed to establish a voice connection.
|
||||
///
|
||||
/// *Users should `leave` the server on the gateway before
|
||||
/// re-attempting connection.*
|
||||
Driver(ConnectionError),
|
||||
#[cfg(feature = "serenity")]
|
||||
/// Serenity-specific WebSocket send error.
|
||||
@@ -34,6 +50,31 @@ pub enum JoinError {
|
||||
Twilight(CommandError),
|
||||
}
|
||||
|
||||
#[cfg(feature = "gateway-core")]
|
||||
impl JoinError {
|
||||
/// Indicates whether this failure may have left (or been
|
||||
/// caused by) Discord's gateway state being in an
|
||||
/// inconsistent state.
|
||||
///
|
||||
/// Failure to `leave` before rejoining may cause further
|
||||
/// timeouts.
|
||||
pub fn should_leave_server(&self) -> bool {
|
||||
matches!(self, JoinError::TimedOut)
|
||||
}
|
||||
|
||||
#[cfg(feature = "driver-core")]
|
||||
/// Indicates whether this failure can be reattempted via
|
||||
/// [`Driver::connect`] with retreived connection info.
|
||||
///
|
||||
/// Failure to `leave` before rejoining may cause further
|
||||
/// timeouts.
|
||||
///
|
||||
/// [`Driver::connect`]: crate::driver::Driver
|
||||
pub fn should_reconnect_driver(&self) -> bool {
|
||||
matches!(self, JoinError::Driver(_))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gateway-core")]
|
||||
impl fmt::Display for JoinError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@@ -42,6 +83,7 @@ impl fmt::Display for JoinError {
|
||||
JoinError::Dropped => write!(f, "request was cancelled/dropped."),
|
||||
JoinError::NoSender => write!(f, "no gateway destination."),
|
||||
JoinError::NoCall => write!(f, "tried to leave a non-existent call."),
|
||||
JoinError::TimedOut => write!(f, "gateway response from Discord timed out."),
|
||||
#[cfg(feature = "driver-core")]
|
||||
JoinError::Driver(t) => write!(f, "internal driver error {}.", t),
|
||||
#[cfg(feature = "serenity")]
|
||||
|
||||
Reference in New Issue
Block a user