hiqlite 0.13.0

Hiqlite - highly-available, embeddable, raft-based SQLite + cache
use crate::app_state::AppState;
use crate::client::stream::ClientStreamReq;
use crate::{Client, Error};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::watch;
use tokio::time;
use tracing::{debug, info};

pub struct ShutdownHandle {
    state: Arc<AppState>,
    #[cfg(feature = "cache")]
    with_tls: bool,
    #[cfg(feature = "cache")]
    tls_no_verify: bool,
    #[cfg(feature = "cache")]
    tx_client_cache: flume::Sender<ClientStreamReq>,
    #[cfg(feature = "sqlite")]
    tx_client_db: flume::Sender<ClientStreamReq>,
    tx_shutdown: Option<watch::Sender<bool>>,
    rx_shutdown: watch::Receiver<bool>,
}

impl ShutdownHandle {
    pub async fn wait(&mut self) -> Result<(), Error> {
        let _ = self.rx_shutdown.changed().await;
        info!("ShutdownHandle received shutdown signal - shutting down the Raft node now");

        if time::timeout(
            Duration::from_secs(15),
            Client::shutdown_execute(
                &self.state,
                #[cfg(feature = "cache")]
                self.with_tls,
                #[cfg(feature = "cache")]
                self.tls_no_verify,
                #[cfg(feature = "cache")]
                &self.tx_client_cache,
                #[cfg(feature = "sqlite")]
                &self.tx_client_db,
                &self.tx_shutdown,
            ),
        )
        .await
        .is_err()
        {
            debug!("Timeout reached while waiting for Client::shutdown_execute");
        }
        Ok(())
    }
}

impl Client {
    #[allow(unused)]
    pub fn shutdown_handle(&self) -> Result<ShutdownHandle, Error> {
        if let Some(state) = self.inner.state.clone() {
            let (tx, rx_shutdown) = watch::channel(false);

            ctrlc::set_handler(move || {
                let _ = tx.send(true);
            })
            .expect("Error setting shutdown handle");

            Ok(ShutdownHandle {
                state,
                #[cfg(feature = "cache")]
                with_tls: self.inner.tls_config.is_some(),
                #[cfg(feature = "cache")]
                tls_no_verify: self.inner.tls_no_verify,
                #[cfg(feature = "cache")]
                tx_client_cache: self.inner.tx_client_cache.clone(),
                #[cfg(feature = "sqlite")]
                tx_client_db: self.inner.tx_client_db.clone(),
                tx_shutdown: self.inner.tx_shutdown.clone(),
                rx_shutdown,
            })
        } else {
            Err(Error::Error(
                "A shutdown handle can only be registered for local clients".into(),
            ))
        }
    }
}