Skip to content

Commit

Permalink
add client config for number of initial connect/reconnect attempts
Browse files Browse the repository at this point in the history
  • Loading branch information
UkoeHB committed Sep 30, 2023
1 parent f6e9646 commit 6b9443b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 9 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Return `Ok(MessageSignal)` from `Client` and `Session` `.binary()/.text()/.close()` endpoints instead of `Ok(())`. The `MessageSignal::state()` method will indicate the current state of the message (sending/sent/failed).
- Clients attempt to reconnect immediately instead of after one full reconnect interval.
- Incoming user messages are discarded while a client is reconnecting, to better match the usual behavior of a websocket connection. If you want messages to be buffered while reconnecting, you should implement your own buffer.
- rename `socket::Config` -> `socket::SocketConfig` and add a `heartbeat_ping_msg_fn` member variable in order to support custom Ping/Pong protocols
- add `ClientConfig::socket_config()` setter so clients can define their socket's config
- add `ezsockets::axum::Upgrade::on_upgrade_with_config()` that accepts a `SocketConfig`
- Rename `socket::Config` -> `socket::SocketConfig` and add a `heartbeat_ping_msg_fn` member variable in order to support custom Ping/Pong protocols.
- Add `ClientConfig::socket_config()` setter so clients can define their socket's config.
- Add `ezsockets::axum::Upgrade::on_upgrade_with_config()` that accepts a `SocketConfig`.
- Refactor `ezeockets::client::connect()` to use a retry loop for the initial connection. Add `max_initial_connect_attempts` and `max_reconnect_attempts` options to the `ClientConfig` (they default to 'infinite').


Migration guide:
Expand Down
38 changes: 32 additions & 6 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub const DEFAULT_RECONNECT_INTERVAL: Duration = Duration::new(5, 0);
#[derive(Debug)]
pub struct ClientConfig {
url: Url,
max_initial_connect_attempts: usize,
max_reconnect_attempts: usize,
reconnect_interval: Duration,
headers: http::HeaderMap,
socket_config: Option<SocketConfig>,
Expand All @@ -87,6 +89,8 @@ impl ClientConfig {
let url = url.try_into().expect("invalid URL");
Self {
url,
max_initial_connect_attempts: usize::MAX,
max_reconnect_attempts: usize::MAX,
reconnect_interval: DEFAULT_RECONNECT_INTERVAL,
headers: http::HeaderMap::new(),
socket_config: None,
Expand Down Expand Up @@ -152,6 +156,22 @@ impl ClientConfig {
self
}

/// Set the maximum number of connection attempts when starting a client.
///
/// Defaults to infinite.
pub fn max_initial_connect_attempts(mut self, max_initial_connect_attempts: usize) -> Self {
self.max_initial_connect_attempts = max_initial_connect_attempts;
self
}

/// Set the maximum number of attempts when reconnecting.
///
/// Defaults to infinite.
pub fn max_reconnect_attempts(mut self, max_reconnect_attempts: usize) -> Self {
self.max_reconnect_attempts = max_reconnect_attempts;
self
}

/// Set the reconnect interval.
pub fn reconnect_interval(mut self, reconnect_interval: Duration) -> Self {
self.reconnect_interval = reconnect_interval;
Expand Down Expand Up @@ -335,8 +355,13 @@ pub async fn connect<E: ClientExt + 'static>(
let mut client = client_fn(handle.clone());
let future = tokio::spawn(async move {
tracing::info!("connecting to {}...", config.url);
let Some(socket) =
client_connect(1usize, &config, &mut to_socket_receiver, &mut client).await?
let Some(socket) = client_connect(
config.max_initial_connect_attempts,
&config,
&mut to_socket_receiver,
&mut client,
)
.await?
else {
return Ok(());
};
Expand Down Expand Up @@ -393,7 +418,7 @@ impl<E: ClientExt> ClientActor<E> {
{
ClientCloseMode::Reconnect => {
let Some(socket) = client_connect(
usize::MAX,
self.config.max_reconnect_attempts,
&self.config,
&mut self.to_socket_receiver,
&mut self.client,
Expand All @@ -416,7 +441,7 @@ impl<E: ClientExt> ClientActor<E> {
{
ClientCloseMode::Reconnect => {
let Some(socket) = client_connect(
usize::MAX,
self.config.max_reconnect_attempts,
&self.config,
&mut self.to_socket_receiver,
&mut self.client,
Expand Down Expand Up @@ -454,7 +479,8 @@ async fn client_connect<E: ClientExt>(
Ok((socket, _)) => {
tracing::info!("successfully connected");
if let Err(err) = client.on_connect().await {
tracing::error!("calling on_connect() failed due to {}", err);
tracing::error!("calling on_connect() failed due to {}, closing client", err);
return Err(err);
}
let socket = Socket::new(socket, config.socket_config.clone().unwrap_or_default());
return Ok(Some(socket));
Expand All @@ -468,7 +494,7 @@ async fn client_connect<E: ClientExt>(
}
};

// abort if we have exceeded the max attempts
// abort if we have reached the max attempts
if i >= max_attempts {
return Err(Error::from(format!(
"failed to connect after {} attempt(s), aborting...",
Expand Down

0 comments on commit 6b9443b

Please sign in to comment.