use std::sync::Arc;
use tracing::debug;
use crate::{
ANYTYPE_DESKTOP_URL, Result,
cache::AnytypeCache,
config::{
ANYTYPE_URL_ENV, DEFAULT_SERVICE_NAME, RATE_LIMIT_MAX_RETRIES_DEFAULT,
RATE_LIMIT_MAX_RETRIES_ENV,
},
http_client::HttpClient,
prelude::*,
verify::VerifyConfig,
};
#[derive(Debug, Clone)]
pub struct ClientConfig {
pub base_url: String,
pub app_name: String,
pub limits: ValidationLimits,
pub rate_limit_max_retries: u32,
pub disable_cache: bool,
pub verify: Option<VerifyConfig>,
}
impl Default for ClientConfig {
fn default() -> Self {
ClientConfig {
base_url: std::env::var(ANYTYPE_URL_ENV).unwrap_or(ANYTYPE_DESKTOP_URL.to_string()),
app_name: DEFAULT_SERVICE_NAME.to_string(),
limits: Default::default(),
rate_limit_max_retries: std::env::var(RATE_LIMIT_MAX_RETRIES_ENV)
.ok()
.and_then(|value| value.parse::<u32>().ok())
.unwrap_or(RATE_LIMIT_MAX_RETRIES_DEFAULT),
disable_cache: false,
verify: None,
}
}
}
impl ClientConfig {
pub fn app_name(self, app_name: &str) -> Self {
ClientConfig {
app_name: app_name.to_string(),
..self
}
}
pub fn limits(self, limits: ValidationLimits) -> Self {
ClientConfig { limits, ..self }
}
pub fn disable_cache(self, disable_cache: bool) -> Self {
ClientConfig {
disable_cache,
..self
}
}
pub fn ensure_available(self, verify: VerifyConfig) -> Self {
ClientConfig {
verify: Some(verify),
..self
}
}
pub fn verify_config(self, verify: Option<VerifyConfig>) -> Self {
ClientConfig { verify, ..self }
}
pub fn get_limits(&self) -> &ValidationLimits {
&self.limits
}
pub fn get_verify_config(&self) -> Option<&VerifyConfig> {
self.verify.as_ref()
}
}
pub struct AnytypeClient {
pub(crate) client: Arc<HttpClient>,
pub(crate) config: ClientConfig,
pub(crate) keystore: Arc<Box<dyn KeyStore>>,
pub(crate) cache: Arc<AnytypeCache>,
}
impl std::fmt::Debug for AnytypeClient {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AnytypeClient")
.field("config", &self.config)
.field("keystore", &self.keystore)
.field("cache", &self.cache)
.finish()
}
}
impl AnytypeClient {
pub fn new(app_name: &str) -> Result<Self> {
Self::with_config(ClientConfig::default().app_name(app_name))
}
pub fn with_config(config: ClientConfig) -> Result<Self> {
let client = reqwest::Client::builder().no_proxy();
Self::with_client(client, config)
}
pub fn with_client(client: reqwest::ClientBuilder, config: ClientConfig) -> Result<Self> {
debug!(url=?config.base_url, "new client");
let client = HttpClient::new(
client,
config.base_url.clone(),
config.limits.clone(),
config.rate_limit_max_retries,
)?;
let cache = Arc::new(AnytypeCache::default());
if config.disable_cache {
cache.disable();
}
Ok(Self {
client: Arc::new(client),
config,
keystore: Arc::new(Box::new(NoKeyStore::default())),
cache,
})
}
pub fn get_config(&self) -> &ClientConfig {
&self.config
}
pub fn api_version(&self) -> String {
crate::ANYTYPE_API_VERSION.to_string()
}
pub fn http_metrics(&self) -> HttpMetricsSnapshot {
self.client.metrics_snapshot()
}
pub fn enable_cache(&self) {
self.cache.enable();
}
pub fn disable_cache(&self) {
self.cache.disable();
}
pub fn cache_is_enabled(&self) {
self.cache.is_enabled();
}
}
impl AnytypeClient {
#[doc(hidden)]
pub fn cache(&self) -> Arc<AnytypeCache> {
self.cache.clone()
}
}