use std::{
any::{Any, TypeId},
fmt::Debug,
sync::Arc,
};
use config::Config;
use dashmap::DashMap;
use futures::future::BoxFuture;
use fxhash::FxHashMap;
use serde::de::DeserializeOwned;
use crate::tina::{data::AppResult, server::application::Application};
mod nacos;
#[cfg(feature = "client-nacos")]
pub use self::nacos::*;
use super::GrpcClientProps;
pub type ConfigChangeListener = Box<dyn Fn(Application, RegistryDataConfig) -> BoxFuture<'static, AppResult<()>> + Send + Sync + 'static>;
#[derive(Debug)]
pub struct RegistryDataConfig {
pub namespace: String,
pub data_id: String,
pub group: String,
pub content: String,
pub content_type: RegistryDataType,
}
#[derive(Debug, Clone, Copy)]
pub enum RegistryDataType {
Json,
Properties,
Xml,
Html,
Text,
Yaml,
}
pub type RegistryClientExtentionValue = Arc<dyn Any + Send + Sync + 'static>;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(crate = "serde")]
pub struct RegistryClientConfigInfo {
pub data_id: String,
pub group: String,
}
pub struct RegistryClient {
server_addr: String,
app_name: String,
username: Option<String>,
password: Option<String>,
namespace: Option<String>,
config_infos: Vec<RegistryClientConfigInfo>,
extensions: FxHashMap<TypeId, RegistryClientExtentionValue>,
props: DashMap<GrpcClientPropsKey, GrpcClientProps>,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct GrpcClientPropsKey {
pub(crate) app_name: String,
pub(crate) service_name: String,
pub(crate) group: String,
}
impl Debug for RegistryClient {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RegistryClient")
.field("server_addr", &self.server_addr)
.field("app_name", &self.app_name)
.field("username", &self.username)
.field("password", &self.password)
.field("namespace", &self.namespace)
.field("config_infos", &self.config_infos)
.finish()
}
}
pub struct RegistryClientBuilder {
server_addr: String,
app_name: String,
username: Option<String>,
password: Option<String>,
namespace: Option<String>,
config_infos: Vec<RegistryClientConfigInfo>,
}
impl Debug for RegistryClientBuilder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RegistryClientBuilder")
.field("server_addr", &self.server_addr)
.field("app_name", &self.app_name)
.field("username", &self.username)
.field("password", &self.password)
.field("namespace", &self.namespace)
.field("config_infos", &self.config_infos)
.finish()
}
}
impl RegistryClientBuilder {
pub fn new(server_addr: impl Into<String>, app_name: impl Into<String>) -> Self {
Self {
server_addr: server_addr.into(),
app_name: app_name.into(),
username: None,
password: None,
namespace: None,
config_infos: Vec::new(),
}
}
pub fn auth_username(mut self, username: impl Into<String>) -> Self {
self.username = Some(username.into());
self
}
pub fn auth_password(mut self, password: impl Into<String>) -> Self {
self.password = Some(password.into());
self
}
pub fn namespace(mut self, namespace: impl Into<String>) -> Self {
self.namespace = Some(namespace.into());
self
}
pub fn add_config_info(mut self, data_id: impl Into<String>, group: impl Into<String>) -> Self {
let config_info = RegistryClientConfigInfo {
data_id: data_id.into(),
group: group.into(),
};
self.config_infos.push(config_info);
self
}
pub fn build(self) -> RegistryClient {
let Self {
server_addr,
app_name,
username,
password,
namespace,
config_infos,
} = self;
RegistryClient {
server_addr,
app_name,
username,
password,
namespace,
extensions: Default::default(),
config_infos,
props: DashMap::new(),
}
}
}
#[async_trait]
pub trait IRegistryClient {
async fn init(&mut self, application: &Application) -> AppResult<()>;
async fn get_config<C>(&self, application: &Application, data_id: String, group: String) -> AppResult<Option<C>>
where
C: DeserializeOwned + Send + Sync + 'static;
async fn get_raw_config(&self, application: &Application, data_id: String, group: String) -> AppResult<Option<Config>>;
async fn regist_grpc_service<S>(&self, application: &Application, services: S) -> AppResult<()>
where
S: Into<RegistryServiceInstance> + Send + Sync + 'static;
async fn deregist_grpc_service<S>(&self, application: &Application, services: S) -> AppResult<()>
where
S: Into<RegistryServiceInstance> + Send + Sync + 'static;
async fn regist_batch_grpc_service<S>(&self, application: &Application, service: Vec<S>) -> AppResult<()>
where
S: Into<RegistryServiceInstance> + Send + Sync + 'static;
async fn get_grpc_client_props(
&self,
app_name: &str,
service_name: &str,
group: impl Into<String> + Send,
) -> AppResult<GrpcClientProps>;
}