Skip to main content

nadisc_runtime/
providers.rs

1//! 本地静态表与 DNS 的受管桥,不把地址解析提升为后端健康证据。
2
3use nadisc::managed::{
4    Capabilities, DiscoveryError, ErrorCode, EvidenceKind, ManagedProvider, ProviderSnapshot,
5    Result,
6};
7use nadisc::{DiscoveryClient, DnsDiscovery, DnsService, Instance, StaticDiscovery};
8use std::{
9    collections::BTreeMap,
10    sync::atomic::{AtomicBool, Ordering},
11};
12
13enum Backend {
14    Static(StaticDiscovery),
15    Dns(DnsDiscovery),
16}
17
18/// 静态实例或 DNS 地址的只读适配器,不提供注册中心健康证据或写入能力。
19pub struct LocalProvider {
20    backend: Backend,
21    closed: AtomicBool,
22}
23
24impl LocalProvider {
25    /// 业务作用:冻结普通服务的静态实例表,不产生自注册副作用。
26    /// 参数说明:`services` 为服务到完整实例列表的显式映射。
27    /// 返回:合法静态表对应的只读 provider。
28    pub fn static_services(services: BTreeMap<String, Vec<Instance>>) -> Result<Self> {
29        let backend = StaticDiscovery::new(services)
30            .map_err(|_| crate::config::invalid("invalid static discovery table"))?;
31        Ok(Self {
32            backend: Backend::Static(backend),
33            closed: AtomicBool::new(false),
34        })
35    }
36
37    /// 业务作用:复用 A/AAAA 地址解析,只允许显式服务绑定。
38    /// 参数说明:`services` 为服务别名与主机端口映射。
39    /// 返回:只读 DNS provider,不承诺 SRV、DNS TTL 或业务健康。
40    pub fn dns_services(services: BTreeMap<String, DnsService>) -> Result<Self> {
41        if services.is_empty() {
42            return Err(crate::config::invalid(
43                "DNS service bindings cannot be empty",
44            ));
45        }
46        let backend = DnsDiscovery::new(services)
47            .map_err(|_| crate::config::invalid("invalid DNS discovery table"))?;
48        Ok(Self {
49            backend: Backend::Dns(backend),
50            closed: AtomicBool::new(false),
51        })
52    }
53
54    /// 业务作用:统一拒绝已关闭本地 provider 的新请求。
55    /// 参数说明:无。
56    /// 返回:仍开放时成功,关闭后拒绝。
57    fn check(&self) -> Result<()> {
58        if self.closed.load(Ordering::Acquire) {
59            Err(crate::closed())
60        } else {
61            Ok(())
62        }
63    }
64}
65
66#[async_trait::async_trait]
67impl ManagedProvider for LocalProvider {
68    /// 业务作用:准确声明本地后端只读与证据边界。
69    /// 参数说明:无。
70    /// 返回:Static 或 Address 证据,永不声明远端健康。
71    fn capabilities(&self) -> Capabilities {
72        Capabilities {
73            registration: false,
74            enumeration: true,
75            evidence: match self.backend {
76                Backend::Static(_) => EvidenceKind::Static,
77                Backend::Dns(_) => EvidenceKind::Address,
78            },
79        }
80    }
81
82    /// 业务作用:确认本地配置 provider 仍开放。
83    /// 参数说明:无。
84    /// 返回:不把 DNS 配置有效误报为远端服务健康。
85    async fn prepare(&self) -> Result<()> {
86        self.check()
87    }
88
89    /// 业务作用:读取完整静态表或执行一次 DNS 地址解析。
90    /// 参数说明:`service` 是显式服务别名。
91    /// 返回:完整候选或地址解析失败,不使用旧 DNS 缓存伪造新证据。
92    async fn observe(&self, service: &str) -> Result<ProviderSnapshot> {
93        self.check()?;
94        let instances = match &self.backend {
95            Backend::Static(provider) => provider.discover_all(service).await,
96            Backend::Dns(provider) => provider.discover_all(service).await,
97        }
98        .map_err(|_| {
99            DiscoveryError::new(ErrorCode::Unavailable, "local provider observation failed")
100        })?;
101        self.check()?;
102        Ok(ProviderSnapshot {
103            instances,
104            evidence: self.capabilities().evidence,
105        })
106    }
107
108    /// 业务作用:只枚举显式配置服务,不执行全局目录扫描。
109    /// 参数说明:无。
110    /// 返回:本连接配置的服务名。
111    async fn services(&self) -> Result<Vec<String>> {
112        self.check()?;
113        match &self.backend {
114            Backend::Static(provider) => provider.list_services().await,
115            Backend::Dns(provider) => provider.list_services().await,
116        }
117        .map_err(|_| {
118            DiscoveryError::new(ErrorCode::Unavailable, "local service enumeration failed")
119        })
120    }
121
122    /// 业务作用:禁止该本地适配器接受新观察。
123    /// 参数说明:无。
124    /// 返回:重复关闭幂等,没有独立后台循环。
125    async fn close(&self) -> Result<()> {
126        self.closed.store(true, Ordering::Release);
127        Ok(())
128    }
129}