use nullnet_liberror::{Error, ErrorHandler, Location, location};
use tonic::transport::{Channel, ClientTlsConfig};
#[derive(Debug, Clone)]
pub struct DatastoreConfig {
pub host: String,
pub port: u16,
pub tls: bool,
}
impl DatastoreConfig {
#[must_use]
pub fn from_env() -> Self {
Self {
host: read_host_value_from_env(String::from("127.0.0.1")),
port: read_port_value_from_env(6000),
tls: real_tls_value_from_env(false),
}
}
#[must_use]
pub fn new(host: String, port: u16, tls: bool) -> Self {
Self { host, port, tls }
}
pub(crate) async fn connect(&self) -> Result<Channel, Error> {
let protocol = if self.tls { "https" } else { "http" };
let host = self.host.as_str();
let port = self.port;
let mut endpoint = Channel::from_shared(format!("{protocol}://{host}:{port}"))
.handle_err(location!())?
.connect_timeout(std::time::Duration::from_secs(10));
if self.tls {
endpoint = endpoint
.tls_config(ClientTlsConfig::new().with_native_roots())
.handle_err(location!())?;
}
let channel = endpoint.connect().await.handle_err(location!())?;
Ok(channel)
}
}
fn read_host_value_from_env(default: String) -> String {
std::env::var("DATASTORE_HOST").unwrap_or_else(|err| {
log::warn!("Failed to read 'DATASTORE_HOST' env var: {err}. Using default value ...");
default
})
}
fn read_port_value_from_env(default: u16) -> u16 {
match std::env::var("DATASTORE_PORT") {
Ok(value) => value.parse::<u16>().unwrap_or_else(|err| {
log::warn!(
"Failed to parse 'DATASTORE_PORT' ({value}) as u16: {err}. Using default value ..."
);
default
}),
Err(err) => {
log::warn!("Failed to read 'DATASTORE_PORT' env var: {err}. Using default value ...");
default
}
}
}
fn real_tls_value_from_env(default: bool) -> bool {
match std::env::var("DATASTORE_TLS") {
Ok(value) => value.to_lowercase() == "true",
Err(err) => {
log::warn!("Failed to read 'DATASTORE_TLS' env var: {err}. Using default value ...");
default
}
}
}