cometd-client 0.3.6

Client for LongPolling CometD connections
Documentation
use crate::types::{CometdError, CometdResult, ErrorKind, Reconnect};
use core::future::Future;

pub(crate) async fn retry_with_advice<T, Fut, HandshakeFut>(
    number_of_retries: usize,
    handshake: impl Fn() -> HandshakeFut,
    f: impl Fn() -> Fut,
) -> CometdResult<T>
where
    Fut: Future<Output = CometdResult<T>>,
    HandshakeFut: Future<Output = CometdResult<()>>,
{
    let mut f_retries = number_of_retries;

    loop {
        match f().await {
            Ok(ret) => break Ok(ret),
            Err(CometdError::WrongResponse(kind, Reconnect::Handshake, _)) => {
                check_retries(kind, f_retries)?;
                handshake_retry(number_of_retries, &handshake).await?;
            }
            Err(CometdError::WrongResponse(kind, Reconnect::Retry, _)) => {
                check_retries(kind, f_retries)?
            }
            Err(error) => break Err(error),
        }
        f_retries -= 1;
    }
}

#[inline(always)]
async fn handshake_retry<HandshakeFut>(
    mut handshake_retries: usize,
    handshake: impl Fn() -> HandshakeFut,
) -> CometdResult<()>
where
    HandshakeFut: Future<Output = CometdResult<()>>,
{
    loop {
        match handshake().await {
            Ok(()) => break Ok(()),
            Err(CometdError::WrongResponse(kind, Reconnect::Handshake | Reconnect::Retry, _)) => {
                check_retries(kind, handshake_retries)?
            }
            Err(error) => break Err(error),
        }
        handshake_retries -= 1;
    }
}

#[inline(always)]
fn check_retries(kind: ErrorKind, retries: usize) -> CometdResult<()> {
    retries
        .gt(&0)
        .then_some(())
        .ok_or(CometdError::wrong_response(
            kind,
            Reconnect::None,
            "exhausted attempts",
        ))
}