use crate::app_state::{AppState, RaftType};
use crate::client::DbClient;
use crate::http_client::build_http_client;
use crate::{Client, Error, tls};
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use tokio::sync::{RwLock, watch};
#[cfg(feature = "listen_notify")]
use crate::client::listen_notify::remote::RemoteListener;
#[cfg(feature = "sqlite")]
use crate::client::stream::ClientStreamReq;
impl Client {
pub(crate) async fn new_local(
state: Arc<AppState>,
tls_config: Option<Arc<rustls::ClientConfig>>,
#[cfg(feature = "cache")] tls_no_verify: bool,
#[cfg(feature = "sqlite")] tx_client_db: flume::Sender<ClientStreamReq>,
#[cfg(feature = "sqlite")] rx_client_db: flume::Receiver<ClientStreamReq>,
tx_shutdown: watch::Sender<bool>,
) -> Self {
let leader_id = state.id;
let leader_addr = state.addr_api.clone();
let secret = state.secret_api.as_bytes().to_vec();
#[cfg(feature = "cache")]
let leader_cache = Arc::new(RwLock::new((leader_id, leader_addr.clone())));
#[cfg(feature = "sqlite")]
let leader_db = Arc::new(RwLock::new((leader_id, leader_addr)));
#[cfg(feature = "cache")]
let (tx_client_cache, rx_client_cache) = flume::bounded(1);
let db_client = DbClient {
state: Some(state),
#[cfg(feature = "cache")]
leader_cache,
#[cfg(feature = "sqlite")]
leader_db,
nodes: Vec::default(),
client: None,
#[cfg(feature = "cache")]
tx_client_cache,
#[cfg(feature = "sqlite")]
tx_client_db,
tls_config,
#[cfg(feature = "cache")]
tls_no_verify,
api_secret: None,
request_id: AtomicUsize::new(0),
tx_shutdown: Some(tx_shutdown),
#[cfg(feature = "listen_notify_local")]
app_start: chrono::Utc::now().timestamp_micros(),
#[cfg(feature = "listen_notify_local")]
rx_notify: None,
};
let slf = Self {
inner: Arc::new(db_client),
};
slf.find_set_active_leader().await;
#[cfg(feature = "cache")]
slf.open_stream(
secret.clone(),
slf.inner.leader_cache.clone(),
rx_client_cache,
RaftType::Cache,
);
#[cfg(feature = "sqlite")]
slf.open_stream(
secret,
slf.inner.leader_db.clone(),
rx_client_db,
RaftType::Sqlite,
);
slf
}
pub async fn remote(
nodes: Vec<String>,
tls: bool,
tls_no_verify: bool,
api_secret: String,
with_proxy: bool,
) -> Result<Self, Error> {
if nodes.is_empty() {
return Err(Error::Config(
"You must provide at least 1 node to connect to".into(),
));
}
let tls_config = if tls {
Some(tls::build_tls_config(tls_no_verify))
} else {
None
};
let node_id = 0;
let node_addr = nodes[0].clone();
#[cfg(feature = "cache")]
let leader_cache = Arc::new(RwLock::new((node_id, node_addr.clone())));
#[cfg(feature = "sqlite")]
let leader_db = Arc::new(RwLock::new((node_id, node_addr)));
#[cfg(feature = "sqlite")]
let (tx_client_db, rx_client_db) = flume::bounded(1);
#[cfg(feature = "cache")]
let (tx_client_cache, rx_client_cache) = flume::bounded(1);
#[cfg(feature = "listen_notify")]
let rx_notify = Some(RemoteListener::spawn(
leader_cache.clone(),
tls,
api_secret.clone(),
));
#[cfg(all(feature = "listen_notify_local", not(feature = "listen_notify")))]
let rx_notify = None;
let api_secret_bytes = api_secret.as_bytes().to_vec();
let db_client = DbClient {
state: None,
#[cfg(feature = "sqlite")]
leader_db,
#[cfg(feature = "cache")]
leader_cache,
nodes,
client: Some(build_http_client(tls_no_verify)),
#[cfg(feature = "cache")]
tx_client_cache,
#[cfg(feature = "sqlite")]
tx_client_db,
tls_config,
#[cfg(feature = "cache")]
tls_no_verify,
api_secret: Some(api_secret),
request_id: AtomicUsize::new(0),
tx_shutdown: None,
#[cfg(feature = "listen_notify_local")]
app_start: chrono::Utc::now().timestamp_micros(),
#[cfg(feature = "listen_notify_local")]
rx_notify,
};
let slf = Self {
inner: Arc::new(db_client),
};
if !with_proxy {
slf.find_set_active_leader().await;
}
#[cfg(feature = "cache")]
slf.open_stream(
api_secret_bytes.clone(),
slf.inner.leader_cache.clone(),
rx_client_cache,
RaftType::Cache,
);
#[cfg(feature = "sqlite")]
slf.open_stream(
api_secret_bytes,
slf.inner.leader_db.clone(),
rx_client_db,
RaftType::Sqlite,
);
Ok(slf)
}
}