Driver: Automate (re)connection logic (#81)
This PR adds several enhancements to Driver connection logic: * Driver (re)connection attempts now have a default timeout of around 10s. * The driver will now attempt to retry full connection attempts using a user-provided strategy: currently, this defaults to 5 attempts under an exponential backoff strategy. * The driver will now fire `DriverDisconnect` events at the end of any session -- this unifies (re)connection failure events with session expiry as seen in #76, which should provide users with enough detail to know *which* voice channel to reconnect to. Users still need to be careful to read the session/channel IDs to ensure that they aren't overwriting another join. This has been tested using `cargo make ready`, and by setting low timeouts to force failures in the voice receive example (with some additional error handlers). Closes #68.
This commit is contained in:
@@ -21,9 +21,9 @@ use error::{Error, Result};
|
||||
use flume::Sender;
|
||||
use std::{net::IpAddr, str::FromStr, sync::Arc};
|
||||
#[cfg(not(feature = "tokio-02-marker"))]
|
||||
use tokio::{net::UdpSocket, spawn};
|
||||
use tokio::{net::UdpSocket, spawn, time::timeout};
|
||||
#[cfg(feature = "tokio-02-marker")]
|
||||
use tokio_compat::{net::UdpSocket, spawn};
|
||||
use tokio_compat::{net::UdpSocket, spawn, time::timeout};
|
||||
use tracing::{debug, info, instrument};
|
||||
use url::Url;
|
||||
use xsalsa20poly1305::{aead::NewAead, XSalsa20Poly1305 as Cipher};
|
||||
@@ -42,9 +42,23 @@ pub(crate) struct Connection {
|
||||
|
||||
impl Connection {
|
||||
pub(crate) async fn new(
|
||||
info: ConnectionInfo,
|
||||
interconnect: &Interconnect,
|
||||
config: &Config,
|
||||
idx: usize,
|
||||
) -> Result<Connection> {
|
||||
if let Some(t) = config.driver_timeout {
|
||||
timeout(t, Connection::new_inner(info, interconnect, config, idx)).await?
|
||||
} else {
|
||||
Connection::new_inner(info, interconnect, config, idx).await
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn new_inner(
|
||||
mut info: ConnectionInfo,
|
||||
interconnect: &Interconnect,
|
||||
config: &Config,
|
||||
idx: usize,
|
||||
) -> Result<Connection> {
|
||||
let url = generate_url(&mut info.endpoint)?;
|
||||
|
||||
@@ -207,6 +221,8 @@ impl Connection {
|
||||
client,
|
||||
ssrc,
|
||||
hello.heartbeat_interval,
|
||||
idx,
|
||||
info.clone(),
|
||||
));
|
||||
|
||||
spawn(udp_rx::runner(
|
||||
@@ -226,7 +242,16 @@ impl Connection {
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
pub async fn reconnect(&mut self) -> Result<()> {
|
||||
pub async fn reconnect(&mut self, config: &Config) -> Result<()> {
|
||||
if let Some(t) = config.driver_timeout {
|
||||
timeout(t, self.reconnect_inner()).await?
|
||||
} else {
|
||||
self.reconnect_inner().await
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
pub async fn reconnect_inner(&mut self) -> Result<()> {
|
||||
let url = generate_url(&mut self.info.endpoint)?;
|
||||
|
||||
// Thread may have died, we want to send to prompt a clean exit
|
||||
|
||||
Reference in New Issue
Block a user