detector 0.1.1

A set of types for service registration and discovery.
Documentation
mod error;
/// 提供服务注册与发现的trait定义
///
mod watch;

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::error::Error;
use std::ops::Add;

#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub enum ServiceState {
    /// 状态服
    Stateful,
    /// 无状态服
    Stateless,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ServiceKey {
    /// 服务实例唯一id
    pub id: Option<u32>,
    /// 服务名字
    pub name: String,
    /// 命名空间
    pub ns: Option<String>,
}

impl ServiceKey {
    pub fn new(name: String, ns: Option<String>) -> Self {
        assert_ne!(name, "");
        ServiceKey { id: None, name, ns }
    }

    pub fn id(&self) -> Option<u32> {
        self.id
    }

    pub fn has_id(&self) -> bool {
        self.id.is_some()
    }

    /// 路径
    pub fn path(&self) -> Option<String> {
        let id = self.id?;
        Some(self.path_with_id(id))
    }

    /// 组成一个路径
    pub fn path_with_id(&self, id: u32) -> String {
        self.path_fn(id, |sk| {
            format!("/{}/{}/{}", sk.ns(), sk.name, sk.id.unwrap())
        })
    }

    pub fn path_fn(&self, id: u32, f: fn(ServiceKey) -> String) -> String {
        let mut sk = self.clone();
        sk.id = Some(id);
        f(sk)
    }

    /// 父路径
    pub fn parent_path(&self) -> String {
        self.parent_path_fn(|sk| format!("/{}/{}/", sk.ns(), sk.name))
    }

    pub fn parent_path_fn(&self, f: fn(ServiceKey) -> String) -> String {
        f(self.clone())
    }

    /// 根路径
    pub fn root_path(&self) -> String {
        self.root_fn(|sk| format!("/{}/", sk.ns()))
    }

    pub fn root_fn(&self, f: fn(ServiceKey) -> String) -> String {
        f(self.clone())
    }

    /// 格式:/{ns}/{name}/{id}
    pub fn parse(value: &str) -> Result<ServiceKey, ()> {
        let v: Vec<&str> = value.trim().trim_start_matches('/').split('/').collect();
        if v.len() != 3 {
            return Err(());
        }

        let id = v[2].parse::<u32>().map_err(|_| ())?;
        let v2: Vec<&str> = v[0].split('-').collect();

        Ok(ServiceKey {
            id: Some(id),
            name: v[1].to_string(),
            ns: if v2.len() == 1 {
                None
            } else {
                Some(v2[0].to_string())
            },
        })
    }

    fn ns(&self) -> String {
        self.ns
            .clone()
            .and_then(|s| Some(s.add("-service")))
            .unwrap_or("service".to_string())
    }
}

impl TryFrom<String> for ServiceKey {
    type Error = String;
    fn try_from(value: String) -> Result<Self, Self::Error> {
        ServiceKey::parse(&value).map_err(|_| value)
    }
}

impl<'a> TryFrom<&'a str> for ServiceKey {
    type Error = &'a str;
    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
        ServiceKey::parse(value).map_err(|_| value)
    }
}

impl<'a> TryFrom<&'a [u8]> for ServiceKey {
    type Error = &'a [u8];
    fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
        let v = std::str::from_utf8(value).map_err(|_| value)?;
        ServiceKey::parse(v).map_err(|_| value)
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Service {
    /// key
    pub key: ServiceKey,
    /// ttl时间, 秒数
    pub ttl: i64,
    /// 服务地址
    pub ip: String,
    /// 服务端口
    pub port: u16,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MetaKey {
    /// 服务类型名字
    pub name: String,
    /// 命名空间
    pub ns: Option<String>,
}

impl MetaKey {
    pub fn new(name: String, ns: Option<String>) -> Self {
        assert_ne!(name, "");
        MetaKey { name, ns }
    }

    pub fn path(&self) -> String {
        self.path_fn(|mk| format!("/{}/{}", mk.ns(), mk.name))
    }

    pub fn path_fn(&self, f: fn(MetaKey) -> String) -> String {
        let mk = self.clone();
        f(mk)
    }

    /// 根路径
    pub fn root_path(&self) -> String {
        self.root_fn(|mk| format!("/{}/", mk.ns()))
    }

    pub fn root_fn(&self, f: fn(MetaKey) -> String) -> String {
        f(self.clone())
    }

    /// 格式:/{ns}/{name}
    pub fn parse(value: &str) -> Result<MetaKey, ()> {
        let v: Vec<&str> = value.trim().trim_start_matches('/').split('/').collect();
        if v.len() != 2 {
            return Err(());
        }

        let v2: Vec<&str> = v[0].split('-').collect();

        Ok(MetaKey {
            name: v[1].to_string(),
            ns: if v2.len() == 1 {
                None
            } else {
                Some(v2[0].to_string())
            },
        })
    }

    fn ns(&self) -> String {
        self.ns
            .as_ref()
            .and_then(|s| Some(s.clone().add("-meta")))
            .unwrap_or("meta".to_string())
    }
}

impl TryFrom<String> for MetaKey {
    type Error = String;
    fn try_from(value: String) -> Result<Self, Self::Error> {
        MetaKey::parse(&value).map_err(|_| value)
    }
}

impl<'a> TryFrom<&'a str> for MetaKey {
    type Error = &'a str;
    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
        MetaKey::parse(value).map_err(|_| value)
    }
}

impl<'a> TryFrom<&'a [u8]> for MetaKey {
    type Error = &'a [u8];
    fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
        let v = std::str::from_utf8(value).map_err(|_| value)?;
        MetaKey::parse(v).map_err(|_| value)
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Meta {
    /// key
    pub key: MetaKey,
    /// 状态类型
    pub state: ServiceState,
    /// 要部署的实例总数
    pub instances: u32,
    /// 服务类别
    pub category: Option<u32>,
}

#[derive(Clone, Debug)]
pub struct Services {
    /// 服务实例列表
    pub services: Vec<Service>,
}

impl Services {
    pub fn new() -> Services {
        Services { services: vec![] }
    }
}

/// 服务状态
#[derive(Copy, Clone, Debug)]
pub enum ServiceStatus {
    /// 已注册
    Registered = 0,
    /// 未注册
    Unregistered = 1,
}

impl From<u32> for ServiceStatus {
    fn from(value: u32) -> Self {
        match value {
            0 => ServiceStatus::Registered,
            1 => ServiceStatus::Unregistered,
            _ => panic!("invalid value:{} for ServiceStatus", value),
        }
    }
}

pub trait DetectMeta {
    /// 注册服务元数据, 不需要ttl
    fn register(&mut self) -> impl Future<Output = Result<(), Box<dyn Error + 'static>>>;

    /// 获取元数据
    fn fetch(&mut self) -> impl Future<Output = Result<Option<Meta>, Box<dyn Error + 'static>>>;

    /// 获取所有的元数据
    fn fetch_all(&mut self) -> impl Future<Output = Result<Vec<Meta>, Box<dyn Error + 'static>>>;

    /// 监听元数据
    fn watch(
        &mut self,
    ) -> impl Future<Output = Result<WatchRx<MetaEvent>, Box<dyn Error + 'static>>>;

    /// 监听所有的元数据
    fn watch_all(
        &mut self,
    ) -> impl Future<Output = Result<WatchRx<MetaEvent>, Box<dyn Error + 'static>>>;
}

/// 如果对象被释放掉, 则应该取消掉注册
pub trait Detector {
    /// 本服务数据
    fn service(&self) -> &Service;

    /// 服务id编号
    /// 一旦id有值后则永久不变, 即使被抢占了也不能变
    /// 如果id被抢占,那服务状态则会一直是Registering
    fn id(&self) -> Option<u32> {
        self.service().key.id()
    }

    /// ttl, 代表的是设置的ttl, 不是剩余的ttl
    fn ttl(&self) -> i64 {
        self.service().ttl
    }

    /// 服务状态
    fn status(&self) -> ServiceStatus;

    /// 是否处于已注册
    fn registered(&self) -> bool {
        match self.status() {
            ServiceStatus::Registered => true,
            _ => false,
        }
    }

    /// 是否处于注册过期了
    fn unregistered(&self) -> bool {
        match self.status() {
            ServiceStatus::Unregistered => true,
            _ => false,
        }
    }

    /// 注册服务, 且自动维护服务的有效
    fn register(&mut self) -> impl Future<Output = Result<(), Box<dyn Error + 'static>>>;

    /// 获取本类型服所有实例
    fn fetch(&mut self) -> impl Future<Output = Result<Services, Box<dyn Error + 'static>>>;

    /// 获取所有服务,一般是路由用
    fn fetch_all(
        &mut self,
    ) -> impl Future<Output = Result<HashMap<String, Services>, Box<dyn Error + 'static>>>;

    /// 监听本服务类型
    fn watch(
        &mut self,
    ) -> impl Future<Output = Result<WatchRx<ServiceEvent>, Box<dyn Error + 'static>>>;

    /// 监听所有类型服,一般是路由用
    fn watch_all(&mut self) -> impl Future<Output = Result<WatchRx<ServiceEvent>, Box<dyn Error>>>;

    /// 监听服务自己本身状态, 需要在第一次调用register成功后才能使用它
    fn oneself(&mut self) -> Option<OneselfRx>;
}

pub fn meta_with_only_key(key: MetaKey) -> Meta {
    Meta {
        key,
        // 以下是不要重字段
        state: ServiceState::Stateless,
        instances: 0,
        category: None,
    }
}

pub fn service_with_only_key(key: ServiceKey) -> Service {
    Service {
        key,
        // 以下是不要重字段
        ttl: 0,
        ip: String::new(),
        port: 0,
    }
}

// re-exports
pub use error::*;
pub use serde;
pub use watch::*;