Driver, Tracks: Cleanup of leaky types (#20)

Main goal: a lot of nested future/result folding.

This mainly modifies error handling for Tracks and TrackHandles to be
more consistent, and hides the underlying channel result passing in
get_info. Errors returned should be far clearer, and are domain
specific rather than falling back to a very opaque use of the underlying
channel error. It should be clearer to users why their handle commands
failed, or why they can't make a ytdl track loop or similar.

Also fixed/cleaned up Songbird::join(_gateway) to return in a single
await, sparing the user from the underlying channel details and repeated
Errs. I was trying for some time to extend the same graces to `Call`,
but could not figure out a sane way to get a 'static version of the
first future in the chain (i.e., the gateway send) so that the whole
thing could happen after dropping the lock around the Call. I really
wanted to fix this to happen as a single folded await too, but I think
this might need some crazy hack or redesign.
This commit is contained in:
Kyle Simpson
2020-12-04 15:13:43 +00:00
committed by GitHub
parent 9fdbcd77be
commit f222ce9969
14 changed files with 276 additions and 134 deletions

View File

@@ -14,6 +14,8 @@ use twilight_gateway::shard::CommandError;
/// Error returned when a manager or call handler is
/// unable to send messages over Discord's gateway.
pub enum JoinError {
/// Request to join was dropped, cancelled, or replaced.
Dropped,
/// No available gateway connection was provided to send
/// voice state update messages.
NoSender,
@@ -21,6 +23,9 @@ pub enum JoinError {
///
/// [`Call`]: crate::Call
NoCall,
#[cfg(feature = "driver")]
/// The driver failed to establish a voice connection.
Driver(ConnectionError),
#[cfg(feature = "serenity")]
/// Serenity-specific WebSocket send error.
Serenity(TrySendError<InterMessage>),
@@ -34,8 +39,11 @@ impl fmt::Display for JoinError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Failed to Join Voice channel: ")?;
match self {
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."),
#[cfg(feature = "driver")]
JoinError::Driver(t) => write!(f, "internal driver error {}.", t),
#[cfg(feature = "serenity")]
JoinError::Serenity(t) => write!(f, "serenity failure {}.", t),
#[cfg(feature = "twilight")]
@@ -61,9 +69,19 @@ impl From<CommandError> for JoinError {
}
}
#[cfg(all(feature = "driver", feature = "gateway"))]
impl From<ConnectionError> for JoinError {
fn from(e: ConnectionError) -> Self {
JoinError::Driver(e)
}
}
#[cfg(feature = "gateway")]
/// Convenience type for Discord gateway error handling.
pub type JoinResult<T> = Result<T, JoinError>;
#[cfg(feature = "driver")]
pub use crate::driver::connection::error::{Error as ConnectionError, Result as ConnectionResult};
pub use crate::{
driver::connection::error::{Error as ConnectionError, Result as ConnectionResult},
tracks::{TrackError, TrackResult},
};