vite-rust 0.2.4

A Vite back-end integration for Rust applications.
Documentation
use std::{future::Future, pin::Pin, time::Duration};

use crate::CLIENT_SCRIPT_PATH;

pub(crate) async fn check_heart_beat(host: &str, timeout: Option<Duration>, retries: u8) -> bool {
    let timeout = match timeout {
        Some(t) => t,
        None => Duration::from_secs(10),
    };

    let ping_endpoint = match host.ends_with("/") {
        true => {
            let mut host = host.to_string();
            host.push_str(CLIENT_SCRIPT_PATH);
            host.into_boxed_str()
        }
        false => {
            let mut host = host.to_string();
            host.push('/');
            host.push_str(CLIENT_SCRIPT_PATH);
            host.into_boxed_str()
        }
    };

    let response = retry_cb(retries, move || {
        let ping_endpoint = ping_endpoint.clone().to_string();
        Box::pin(async move {
            reqwest::Client::new()
                .get(ping_endpoint.as_str())
                .timeout(timeout)
                .send()
                .await
        })
    })
    .await;

    match response {
        Err(err) => {
            log::warn!("Vite development server handshake has failed: {}.", err);
            false
        }
        Ok(response) => response.status() == 200,
    }
}

async fn retry_cb<T, E>(
    mut retries_count: u8,
    cb: impl Send + Sync + 'static + Fn() -> Pin<Box<dyn Future<Output = Result<T, E>>>> + 'static,
) -> Result<T, E> {
    let mut response = cb().await;

    while response.is_err() && retries_count > 0 {
        response = cb().await;
        retries_count -= 1;
    }

    response
}

#[cfg(test)]
mod test {
    use super::retry_cb;
    use std::sync::{Arc, Mutex};

    #[tokio::test]
    async fn test_retry_cb() {
        let tries_count = Arc::new(Mutex::new(0));
        let tries_clone = Arc::clone(&tries_count);

        let success_on_last_retry = retry_cb(2, move || {
            let tries_count = tries_clone.clone();
            Box::pin(async move {
                let count = *tries_count.lock().unwrap();
                if count > 0 {
                    *tries_count.lock().unwrap() = count + 1;
                    return Err(());
                }

                Ok(())
            })
        })
        .await;

        let tries_count = Arc::new(Mutex::new(0));
        let tries_clone = Arc::clone(&tries_count);
        let total_failure = retry_cb(2, move || {
            let tries_count = tries_clone.clone();
            Box::pin(async move {
                let count = *tries_count.lock().unwrap();
                if count >= 0 {
                    *tries_count.lock().unwrap() = count + 1;
                    return Err(());
                }

                Ok(())
            })
        })
        .await;

        assert!(success_on_last_retry.is_ok());
        assert!(total_failure.is_err());
    }
}