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:
@@ -1,10 +1,9 @@
|
||||
#[cfg(feature = "driver-core")]
|
||||
use crate::driver::Config;
|
||||
use crate::{
|
||||
error::{JoinError, JoinResult},
|
||||
id::{ChannelId, GuildId, UserId},
|
||||
shards::Sharder,
|
||||
Call,
|
||||
Config,
|
||||
ConnectionInfo,
|
||||
};
|
||||
#[cfg(feature = "serenity")]
|
||||
@@ -50,9 +49,7 @@ pub struct Songbird {
|
||||
client_data: PRwLock<ClientData>,
|
||||
calls: DashMap<GuildId, Arc<Mutex<Call>>>,
|
||||
sharder: Sharder,
|
||||
|
||||
#[cfg(feature = "driver-core")]
|
||||
driver_config: PRwLock<Option<Config>>,
|
||||
config: PRwLock<Option<Config>>,
|
||||
}
|
||||
|
||||
impl Songbird {
|
||||
@@ -63,13 +60,21 @@ impl Songbird {
|
||||
///
|
||||
/// [registered]: crate::serenity::register_with
|
||||
pub fn serenity() -> Arc<Self> {
|
||||
Self::serenity_from_config(Default::default())
|
||||
}
|
||||
|
||||
#[cfg(feature = "serenity")]
|
||||
/// Create a new Songbird instance for serenity, using the given configuration.
|
||||
///
|
||||
/// This must be [registered] after creation.
|
||||
///
|
||||
/// [registered]: crate::serenity::register_with
|
||||
pub fn serenity_from_config(config: Config) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
client_data: Default::default(),
|
||||
calls: Default::default(),
|
||||
sharder: Sharder::Serenity(Default::default()),
|
||||
|
||||
#[cfg(feature = "driver-core")]
|
||||
driver_config: Default::default(),
|
||||
config: Some(config).into(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -82,6 +87,26 @@ impl Songbird {
|
||||
///
|
||||
/// [`process`]: Songbird::process
|
||||
pub fn twilight<U>(cluster: Cluster, shard_count: u64, user_id: U) -> Arc<Self>
|
||||
where
|
||||
U: Into<UserId>,
|
||||
{
|
||||
Self::twilight_from_config(cluster, shard_count, user_id, Default::default())
|
||||
}
|
||||
|
||||
#[cfg(feature = "twilight")]
|
||||
/// Create a new Songbird instance for twilight.
|
||||
///
|
||||
/// Twilight handlers do not need to be registered, but
|
||||
/// users are responsible for passing in any events using
|
||||
/// [`process`].
|
||||
///
|
||||
/// [`process`]: Songbird::process
|
||||
pub fn twilight_from_config<U>(
|
||||
cluster: Cluster,
|
||||
shard_count: u64,
|
||||
user_id: U,
|
||||
config: Config,
|
||||
) -> Arc<Self>
|
||||
where
|
||||
U: Into<UserId>,
|
||||
{
|
||||
@@ -93,9 +118,7 @@ impl Songbird {
|
||||
}),
|
||||
calls: Default::default(),
|
||||
sharder: Sharder::Twilight(cluster),
|
||||
|
||||
#[cfg(feature = "driver-core")]
|
||||
driver_config: Default::default(),
|
||||
config: Some(config).into(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -144,23 +167,30 @@ impl Songbird {
|
||||
.get_shard(shard)
|
||||
.expect("Failed to get shard handle: shard_count incorrect?");
|
||||
|
||||
#[cfg(feature = "driver-core")]
|
||||
let call = Call::from_driver_config(
|
||||
let call = Call::from_config(
|
||||
guild_id,
|
||||
shard_handle,
|
||||
info.user_id,
|
||||
self.driver_config.read().clone().unwrap_or_default(),
|
||||
self.config.read().clone().unwrap_or_default(),
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "driver-core"))]
|
||||
let call = Call::new(guild_id, shard_handle, info.user_id);
|
||||
|
||||
Arc::new(Mutex::new(call))
|
||||
})
|
||||
.clone()
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets a shared configuration for all drivers created from this
|
||||
/// manager.
|
||||
///
|
||||
/// Changes made here will apply to new Call and Driver instances only.
|
||||
///
|
||||
/// Requires the `"driver"` feature.
|
||||
pub fn set_config(&self, new_config: Config) {
|
||||
let mut config = self.config.write();
|
||||
*config = Some(new_config);
|
||||
}
|
||||
|
||||
fn manager_info(&self) -> ClientData {
|
||||
let client_data = self.client_data.write();
|
||||
|
||||
@@ -213,10 +243,7 @@ impl Songbird {
|
||||
};
|
||||
|
||||
let result = match stage_1 {
|
||||
Ok(chan) => chan
|
||||
.await
|
||||
.map_err(|_| JoinError::Dropped)
|
||||
.and_then(|x| x.map_err(JoinError::from)),
|
||||
Ok(chan) => chan.await,
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
|
||||
@@ -401,20 +428,6 @@ impl VoiceGatewayManager for Songbird {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "driver-core")]
|
||||
impl Songbird {
|
||||
/// Sets a shared configuration for all drivers created from this
|
||||
/// manager.
|
||||
///
|
||||
/// Changes made here will apply to new Call and Driver instances only.
|
||||
///
|
||||
/// Requires the `"driver"` feature.
|
||||
pub fn set_config(&self, new_config: Config) {
|
||||
let mut config = self.driver_config.write();
|
||||
*config = Some(new_config);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shard_id(guild_id: u64, shard_count: u64) -> u64 {
|
||||
(guild_id >> 22) % shard_count
|
||||
|
||||
Reference in New Issue
Block a user