tina-core 0.0.2

Tina platform
Documentation
//! 注册中心客户端

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 {
    /// Namespace/Tenant
    pub namespace: String,
    /// DataId
    pub data_id: String,
    /// Group
    pub group: String,
    /// Content
    pub content: String,
    /// Content's Type; e.g. json,properties,xml,html,text,yaml
    pub content_type: RegistryDataType,
}

#[derive(Debug, Clone, Copy)]
/// 注册中心的数据配置类型
pub enum RegistryDataType {
    /// Json类型
    Json,
    /// Properties类型
    Properties,
    /// Xml类型
    Xml,
    /// Html类型
    Html,
    /// Text类型
    Text,
    /// Yaml类型
    Yaml,
}

/// 客户端的扩展Value
pub type RegistryClientExtentionValue = Arc<dyn Any + Send + Sync + 'static>;

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(crate = "serde")]
/// 客户端使用的配置信息
pub struct RegistryClientConfigInfo {
    /// 配置ID
    pub data_id: String,
    /// 配置所属group
    pub group: String,
}
/// 注册中心客户端
pub struct RegistryClient {
    /// 注册中心地址
    server_addr: String,
    /// Client的应用名
    app_name: String,
    /// 注册中心的用户名
    username: Option<String>,
    /// 注册中心的用户密码
    password: Option<String>,
    /// Client所属的namespace
    namespace: Option<String>,
    /// 使用的配置
    config_infos: Vec<RegistryClientConfigInfo>,
    /// 扩展
    extensions: FxHashMap<TypeId, RegistryClientExtentionValue>,
    /// 缓存的Client Props
    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()
    }
}

/// Client构造器
pub struct RegistryClientBuilder {
    /// 注册中心地址
    server_addr: String,
    /// Client的应用名
    app_name: String,
    /// 注册中心的用户名
    username: Option<String>,
    /// 注册中心的用户密码
    password: Option<String>,
    /// Client所属的namespace
    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>;
}