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