diff --git a/twilight-gateway/src/compression/inflater.rs b/twilight-gateway/src/compression/inflater.rs index c42914e5af5..16eba653f83 100644 --- a/twilight-gateway/src/compression/inflater.rs +++ b/twilight-gateway/src/compression/inflater.rs @@ -6,7 +6,7 @@ //! //! # Resizing buffers //! -//! Buffers are resized after some heurestics: +//! Buffers are resized after some heuristics: //! //! - if the data does not fit the buffer size is doubled; or //! - at most once per minute the buffer will be resized down to the size of the @@ -34,7 +34,7 @@ const INTERNAL_BUFFER_SIZE: usize = 32 * 1024; #[derive(Debug)] pub struct Inflater { /// Zlib decompressor, which can have a considerable heap size given the - /// main way this saves memory is by having a directonary to look up data. + /// main way this saves memory is by having a dictionary to look up data. decompress: Decompress, /// Buffer for storing compressed data. Data is stored here via [`extend`]. /// diff --git a/twilight-gateway/src/config.rs b/twilight-gateway/src/config.rs index bb18bc16bc8..14738ca5a73 100644 --- a/twilight-gateway/src/config.rs +++ b/twilight-gateway/src/config.rs @@ -294,6 +294,11 @@ impl ConfigBuilder { } /// Set the proxy URL for connecting to the gateway. + /// + /// When reconnecting, the shard will always use this URL instead of + /// [`resume_gateway_url`]. Proper reconnection is left to the proxy. + /// + /// [`resume_gateway_url`]: twilight_model::gateway::payload::incoming::Ready::resume_gateway_url #[allow(clippy::missing_const_for_fn)] pub fn gateway_url(mut self, gateway_url: String) -> Self { self.inner.gateway_url = Some(gateway_url); diff --git a/twilight-gateway/src/shard.rs b/twilight-gateway/src/shard.rs index 3c9a8b58ba5..c975324af21 100644 --- a/twilight-gateway/src/shard.rs +++ b/twilight-gateway/src/shard.rs @@ -40,12 +40,19 @@ //! then the previous steps are taken and the resultant message is deserialized //! into a [`GatewayEvent`]. //! +//! # Reconnecting +//! +//! If a custom gateway URL is used when reconnecting, the shard will always +//! prefer it over the [`resume_gateway_url`]. Proper reconnection is left to +//! the proxy. +//! +//! [`GatewayEvent`]: twilight_model::gateway::event::GatewayEvent +//! [`resume_gateway_url`]: twilight_model::gateway::payload::incoming::Ready::resume_gateway_url //! [command]: crate::Command //! [is enabled]: Config::ratelimit_messages //! [processed]: Shard::process -//! [websocket message]: crate::message::Message //! [websocket connection]: Shard::connection -//! [`GatewayEvent`]: twilight_model::gateway::event::GatewayEvent +//! [websocket message]: crate::message::Message use crate::{ channel::{MessageChannel, MessageSender}, @@ -122,7 +129,7 @@ pub enum ConnectionStatus { /// Shard has fatally closed. /// /// Possible reasons may be due to [failed authentication], - /// [invalid intents], or other reasons. Refer to the documtation for + /// [invalid intents], or other reasons. Refer to the documentation for /// [`CloseCode`] for possible reasons. /// /// [failed authentication]: CloseCode::AuthenticationFailed @@ -197,6 +204,8 @@ struct MinimalEvent { /// [`Ready`]: twilight_model::gateway::payload::incoming::Ready #[derive(Deserialize)] struct MinimalReady { + /// Used for resuming connections. + resume_gateway_url: String, /// ID of the new identified session. session_id: String, } @@ -305,6 +314,8 @@ pub struct Shard { /// Command ratelimiter, if it was enabled via /// [`Config::ratelimit_messages`]. ratelimiter: Option, + /// Used for resuming connections. + resume_gateway_url: Option, /// Active session of the shard. /// /// The shard may not have an active session if it hasn't completed a full @@ -394,6 +405,7 @@ impl Shard { id: shard_id, latency: Latency::new(), ratelimiter: None, + resume_gateway_url: None, session, status: ConnectionStatus::Connected, user_channel: MessageChannel::new(), @@ -840,6 +852,7 @@ impl Shard { source: None, })?; + self.resume_gateway_url = Some(event.data.resume_gateway_url); self.status = ConnectionStatus::Connected; self.session = Some(Session::new(sequence, event.data.session_id)); } @@ -894,17 +907,21 @@ impl Shard { ) -> Result<(), ReceiveMessageError> { future::reconnect_delay(reconnect_attempts).await; - self.connection = - connection::connect(self.id(), self.config.gateway_url(), self.config.tls()) - .await - .map_err(|source| { - self.status = ConnectionStatus::Disconnected { - close_code, - reconnect_attempts: reconnect_attempts + 1, - }; + let maybe_gateway_url = self + .config + .gateway_url() + .or(self.resume_gateway_url.as_deref()); - ReceiveMessageError::from_reconnect(source) - })?; + self.connection = connection::connect(self.id(), maybe_gateway_url, self.config.tls()) + .await + .map_err(|source| { + self.status = ConnectionStatus::Disconnected { + close_code, + reconnect_attempts: reconnect_attempts + 1, + }; + + ReceiveMessageError::from_reconnect(source) + })?; self.compression.reset(); self.status = ConnectionStatus::Connected; diff --git a/twilight-model/src/gateway/payload/incoming/ready.rs b/twilight-model/src/gateway/payload/incoming/ready.rs index 5eb9e628a58..e0f39fc25ce 100644 --- a/twilight-model/src/gateway/payload/incoming/ready.rs +++ b/twilight-model/src/gateway/payload/incoming/ready.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; pub struct Ready { pub application: PartialApplication, pub guilds: Vec, + pub resume_gateway_url: String, pub session_id: String, #[serde(skip_serializing_if = "Option::is_none")] pub shard: Option<[u64; 2]>, @@ -44,6 +45,7 @@ mod tests { id: Id::new(100), }, guilds, + resume_gateway_url: "wss://gateway.discord.gg".into(), session_id: "foo".to_owned(), shard: Some([4, 7]), user: CurrentUser { @@ -106,6 +108,8 @@ mod tests { Token::Bool(true), Token::StructEnd, Token::SeqEnd, + Token::Str("resume_gateway_url"), + Token::Str("wss://gateway.discord.gg"), Token::Str("session_id"), Token::Str("foo"), Token::Str("shard"), diff --git a/twilight-standby/src/lib.rs b/twilight-standby/src/lib.rs index f2dc1d3f682..48a924361dc 100644 --- a/twilight-standby/src/lib.rs +++ b/twilight-standby/src/lib.rs @@ -1324,6 +1324,7 @@ mod tests { id: Id::new(1), }, guilds: Vec::new(), + resume_gateway_url: "wss://gateway.discord.gg".into(), session_id: String::new(), shard: Some([5, 7]), user: CurrentUser {