Skip to main content

natx_core/
lib.rs

1//! 数据库后端中立的 datasource 身份、受管所有权与事务裁决合同。
2//!
3//! 本 crate 不创建连接,也不依赖 SQLx 的数据库 feature。MySQL 与 PostgreSQL driver crate
4//! 通过同一进程协调器发布 typed registry,确保同一 Application 只有一张名称与 driver catalog。
5//! 连接观测按固定 datasource 与 purpose 区分 Pool acquire、事务槽等待和执行前拒绝;取消只收口
6//! 一次终态,Pool 状态为近似快照。等待日志与有界通知不能改变连接结果,不计作 Mapper 执行耗时。
7
8use std::collections::BTreeMap;
9use std::future::Future;
10use std::sync::atomic::{AtomicU64, AtomicU8, Ordering};
11use std::sync::{Arc, Mutex, OnceLock, Weak};
12
13/// 默认 datasource 的规范名称。
14pub const DEFAULT_DATASOURCE: &str = "default";
15
16pub mod observability;
17/// datasource qualifier 的最大 UTF-8 字节数。
18pub const MAX_DATASOURCE_NAME_BYTES: usize = 128;
19/// 单个受管 Application 可发布的 datasource 总数上限。
20pub const MAX_MANAGED_DATASOURCES: usize = 64;
21
22/// 业务作用:标识 datasource 使用的数据库协议与事务实现。
23#[derive(
24    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Deserialize, serde::Serialize,
25)]
26#[serde(rename_all = "lowercase")]
27pub enum DatabaseDriver {
28    /// MySQL 或兼容协议。
29    MySql,
30    /// PostgreSQL 协议。
31    PostgreSql,
32}
33
34/// 业务作用:声明当前编译产物实际包含的数据库后端,避免把可解析 driver 误当成已编入能力。
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
36pub struct DatabaseCapabilities(u8);
37
38impl DatabaseCapabilities {
39    const MYSQL: u8 = 1;
40    const POSTGRESQL: u8 = 1 << 1;
41
42    /// 业务作用:构造不包含任何数据库后端的能力集合。
43    ///
44    /// 参数说明: 无。
45    ///
46    /// 返回:可继续通过 [`Self::with`] 组合的空集合。
47    pub const fn empty() -> Self {
48        Self(0)
49    }
50
51    /// 业务作用:把一个已经编入的 typed driver 加入能力集合。
52    ///
53    /// 参数说明:`driver` 是由对应 Cargo feature 实际编入的后端。
54    ///
55    /// 返回:包含原集合和指定 driver 的新集合。
56    pub const fn with(self, driver: DatabaseDriver) -> Self {
57        let flag = match driver {
58            DatabaseDriver::MySql => Self::MYSQL,
59            DatabaseDriver::PostgreSql => Self::POSTGRESQL,
60        };
61        Self(self.0 | flag)
62    }
63
64    /// 业务作用:复验配置声明的 driver 是否已经编入当前运行产物。
65    ///
66    /// 参数说明:`driver` 是配置边界解析出的后端。
67    ///
68    /// 返回:对应 typed runtime 存在时返回真。
69    pub const fn contains(self, driver: DatabaseDriver) -> bool {
70        let flag = match driver {
71            DatabaseDriver::MySql => Self::MYSQL,
72            DatabaseDriver::PostgreSql => Self::POSTGRESQL,
73        };
74        self.0 & flag != 0
75    }
76}
77
78impl std::fmt::Display for DatabaseDriver {
79    /// 业务作用:输出稳定、低基数的 driver 名称。
80    ///
81    /// 参数说明:`formatter` 是标准格式化目标。
82    ///
83    /// 返回:名称写入成功时返回 `Ok`,否则返回格式化错误。
84    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85        formatter.write_str(match self {
86            Self::MySql => "mysql",
87            Self::PostgreSql => "postgresql",
88        })
89    }
90}
91
92/// 业务作用:描述 datasource qualifier 在配置边界被拒绝的稳定原因。
93#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
94pub enum DatasourceNameError {
95    /// 名称为空。
96    #[error("datasource name cannot be empty")]
97    Empty,
98    /// 名称包含首尾空白。
99    #[error("datasource name cannot contain leading or trailing whitespace")]
100    SurroundingWhitespace,
101    /// 名称超长或包含不受支持的字符。
102    #[error("datasource name must use ASCII letters, digits, '.', '_' or '-' and stay within the byte limit")]
103    InvalidCharacters,
104}
105
106/// 业务作用:携带经过统一校验的 datasource 身份,使各 driver 不依赖临时字符串解释名称。
107#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
108pub struct DatasourceRef(Arc<str>);
109
110impl DatasourceRef {
111    /// 业务作用:以既有兼容签名校验并固定一个 datasource qualifier。
112    ///
113    /// 参数说明:`name` 是配置边界或业务计划给出的数据源名。
114    ///
115    /// 返回:名称符合有界 canonical 合同时返回拥有型引用;失败时在 anyhow 错误链保留具名原因。
116    pub fn new(name: impl AsRef<str>) -> anyhow::Result<Self> {
117        Self::try_new(name).map_err(anyhow::Error::new)
118    }
119
120    /// 业务作用:为 checked 配置与事务入口校验 datasource qualifier 并保留结构化失败分类。
121    ///
122    /// 参数说明:`name` 是配置边界或业务计划给出的数据源名。
123    ///
124    /// 返回:名称符合有界 canonical 合同时返回拥有型引用,否则返回 [`DatasourceNameError`]。
125    pub fn try_new(name: impl AsRef<str>) -> Result<Self, DatasourceNameError> {
126        let name = name.as_ref();
127        validate_datasource_name(name)?;
128        Ok(Self(Arc::from(name)))
129    }
130
131    /// 业务作用:返回默认 datasource 的规范化身份。
132    ///
133    /// 参数说明: 无。
134    ///
135    /// 返回:名称固定为 `default` 的拥有型引用。
136    pub fn default_ref() -> Self {
137        Self(Arc::from(DEFAULT_DATASOURCE))
138    }
139
140    /// 业务作用:读取 datasource 的规范化 qualifier。
141    ///
142    /// 参数说明: 无。
143    ///
144    /// 返回:与该引用同生命周期的名称切片。
145    pub fn as_str(&self) -> &str {
146        &self.0
147    }
148}
149
150impl Default for DatasourceRef {
151    /// 业务作用:为兼容无参入口选择默认 datasource。
152    ///
153    /// 参数说明: 无。
154    ///
155    /// 返回:默认 datasource 引用。
156    fn default() -> Self {
157        Self::default_ref()
158    }
159}
160
161impl AsRef<str> for DatasourceRef {
162    /// 业务作用:让事务与连接 API 消费已校验 datasource 身份。
163    ///
164    /// 参数说明: 无。
165    ///
166    /// 返回:规范化 datasource 名称。
167    fn as_ref(&self) -> &str {
168        self.as_str()
169    }
170}
171
172impl std::fmt::Display for DatasourceRef {
173    /// 业务作用:输出不含连接信息的 datasource qualifier。
174    ///
175    /// 参数说明:`formatter` 是标准格式化目标。
176    ///
177    /// 返回:名称写入成功时返回 `Ok`,否则返回格式化错误。
178    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179        formatter.write_str(self.as_str())
180    }
181}
182
183/// 业务作用:校验 datasource 名称可安全用于配置键、指标 label 与诊断字段。
184///
185/// 参数说明:`name` 是待校验的 qualifier。
186///
187/// 返回:名称合法时返回 `Ok`,否则返回不包含输入内容的稳定分类。
188pub fn validate_datasource_name(name: &str) -> Result<(), DatasourceNameError> {
189    if name.is_empty() {
190        return Err(DatasourceNameError::Empty);
191    }
192    if name.trim() != name {
193        return Err(DatasourceNameError::SurroundingWhitespace);
194    }
195    if name.len() > MAX_DATASOURCE_NAME_BYTES
196        || !name
197            .bytes()
198            .all(|value| value.is_ascii_alphanumeric() || matches!(value, b'.' | b'_' | b'-'))
199    {
200        return Err(DatasourceNameError::InvalidCharacters);
201    }
202    Ok(())
203}
204
205/// 业务作用:承载两种数据库连接池共同使用的启动配置,不解释具体 URL scheme。
206#[derive(Clone, serde::Deserialize)]
207#[serde(deny_unknown_fields)]
208pub struct DataSourcePoolConfig {
209    /// 数据库连接串;driver 包装层负责校验 scheme。
210    pub url: String,
211    /// 连接池上限。
212    #[serde(default = "default_max_connections")]
213    pub max_connections: u32,
214    /// 连接池下限。
215    #[serde(default)]
216    pub min_connections: u32,
217    /// 从池中获取连接的等待上限,毫秒。
218    #[serde(default = "default_acquire_timeout_ms")]
219    pub acquire_timeout_ms: u64,
220    /// 建立单条连接的等待上限,毫秒。
221    #[serde(default = "default_connect_timeout_ms")]
222    pub connect_timeout_ms: u64,
223    /// 启动时是否先执行真实单连接探测。
224    #[serde(default = "default_probe_on_start")]
225    pub probe_on_start: bool,
226}
227
228impl std::fmt::Debug for DataSourcePoolConfig {
229    /// 业务作用:输出不含用户名和口令的池配置诊断视图。
230    ///
231    /// 参数说明:`formatter` 是标准格式化目标。
232    ///
233    /// 返回:脱敏字段写入成功时返回 `Ok`,否则返回格式化错误。
234    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235        formatter
236            .debug_struct("DataSourcePoolConfig")
237            .field("url", &redact_url(&self.url))
238            .field("max_connections", &self.max_connections)
239            .field("min_connections", &self.min_connections)
240            .field("acquire_timeout_ms", &self.acquire_timeout_ms)
241            .field("connect_timeout_ms", &self.connect_timeout_ms)
242            .field("probe_on_start", &self.probe_on_start)
243            .finish()
244    }
245}
246
247/// 业务作用:描述公共池参数在任何网络 I/O 前被拒绝的原因。
248#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
249pub enum PoolConfigError {
250    /// URL 为空。
251    #[error("datasource url cannot be empty")]
252    EmptyUrl,
253    /// 连接池上限为零。
254    #[error("datasource max_connections must be greater than zero")]
255    ZeroMaxConnections,
256    /// 连接池下限超过上限。
257    #[error("datasource min_connections cannot exceed max_connections")]
258    InvalidConnectionRange,
259    /// 获取连接超时为零。
260    #[error("datasource acquire_timeout_ms must be greater than zero")]
261    ZeroAcquireTimeout,
262    /// 建连超时为零。
263    #[error("datasource connect_timeout_ms must be greater than zero")]
264    ZeroConnectTimeout,
265}
266
267impl DataSourcePoolConfig {
268    /// 业务作用:校验与 driver 无关的池容量和超时合同。
269    ///
270    /// 参数说明: 无。
271    ///
272    /// 返回:公共配置可用于建池时返回 `Ok`;失败时不产生连接副作用。
273    pub fn validate_common(&self) -> Result<(), PoolConfigError> {
274        if self.url.trim().is_empty() {
275            return Err(PoolConfigError::EmptyUrl);
276        }
277        if self.max_connections == 0 {
278            return Err(PoolConfigError::ZeroMaxConnections);
279        }
280        if self.min_connections > self.max_connections {
281            return Err(PoolConfigError::InvalidConnectionRange);
282        }
283        if self.acquire_timeout_ms == 0 {
284            return Err(PoolConfigError::ZeroAcquireTimeout);
285        }
286        if self.connect_timeout_ms == 0 {
287            return Err(PoolConfigError::ZeroConnectTimeout);
288        }
289        Ok(())
290    }
291
292    /// 业务作用:返回可安全写入日志的 host、端口与 database 定位信息。
293    ///
294    /// 参数说明: 无。
295    ///
296    /// 返回:移除 scheme、userinfo、query 与 fragment 后的 endpoint;无法识别时返回固定占位符。
297    pub fn endpoint(&self) -> String {
298        redacted_endpoint(&self.url)
299    }
300}
301
302/// 业务作用:去掉 URL 中的 userinfo,同时保留 scheme 供 Debug 识别 driver。
303///
304/// 参数说明:`url` 是可能包含凭据的数据库连接串。
305///
306/// 返回:不包含用户名和口令的字符串;scheme 或 endpoint 无法安全识别时返回固定占位符。
307pub fn redact_url(url: &str) -> String {
308    let Some((scheme, rest)) = url.split_once("://") else {
309        return "<redacted-url>".to_owned();
310    };
311    if scheme.is_empty()
312        || !scheme
313            .bytes()
314            .all(|value| value.is_ascii_alphanumeric() || matches!(value, b'+' | b'-' | b'.'))
315    {
316        return "<redacted-url>".to_owned();
317    }
318    let endpoint = redacted_endpoint(url);
319    if endpoint == "<unknown-endpoint>" {
320        return "<redacted-url>".to_owned();
321    }
322    let authority = rest.split(['/', '?', '#']).next().unwrap_or(rest);
323    if authority.contains('@') {
324        format!("{scheme}://***@{endpoint}")
325    } else {
326        format!("{scheme}://{endpoint}")
327    }
328}
329
330/// 业务作用:生成不包含 scheme、用户信息和连接参数的数据库 endpoint。
331///
332/// 参数说明:`url` 是 driver 已校验或即将校验的连接串。
333///
334/// 返回:可用于脱敏诊断的 endpoint;格式不完整时返回固定占位符。
335pub fn redacted_endpoint(url: &str) -> String {
336    let Some((_, rest)) = url.split_once("://") else {
337        return "<unknown-endpoint>".to_owned();
338    };
339    let authority_and_path = rest.rsplit_once('@').map_or(rest, |(_, value)| value);
340    let endpoint = authority_and_path
341        .split(['?', '#'])
342        .next()
343        .unwrap_or(authority_and_path);
344    if endpoint.is_empty() {
345        "<unknown-endpoint>".to_owned()
346    } else {
347        endpoint.to_owned()
348    }
349}
350
351/// 业务作用:返回连接池上限的公共缺省值。
352///
353/// 参数说明: 无。
354///
355/// 返回:面向普通服务实例的连接数上限。
356fn default_max_connections() -> u32 {
357    10
358}
359
360/// 业务作用:返回获取连接等待上限的公共缺省值。
361///
362/// 参数说明: 无。
363///
364/// 返回:毫秒单位的有限等待预算。
365fn default_acquire_timeout_ms() -> u64 {
366    2_000
367}
368
369/// 业务作用:返回建立连接等待上限的公共缺省值。
370///
371/// 参数说明: 无。
372///
373/// 返回:毫秒单位的握手预算。
374fn default_connect_timeout_ms() -> u64 {
375    5_000
376}
377
378/// 业务作用:返回是否默认在启动期探测真实连接。
379///
380/// 参数说明: 无。
381///
382/// 返回:固定为真,使地址、凭据和 database 错误在启动期暴露。
383fn default_probe_on_start() -> bool {
384    true
385}
386
387static NEXT_OWNER_ID: AtomicU64 = AtomicU64::new(1);
388
389#[derive(Debug)]
390/// 业务作用:为单个 Application 的数据库 registry 所有权提供不可由数值相等伪造的 Arc 身份。
391struct OwnerIdentity {
392    id: u64,
393}
394
395/// 业务作用:标识唯一 Application 对 catalog 与 typed registry 的共同所有权。
396#[derive(Clone)]
397pub struct ManagedRegistryOwner(Arc<OwnerIdentity>);
398
399impl ManagedRegistryOwner {
400    /// 业务作用:为一次 Application 数据库启动创建不可伪造的进程内所有权身份。
401    ///
402    /// 参数说明: 无。
403    ///
404    /// 返回:可安全 clone、按 Arc 身份复验的 owner。
405    pub fn new() -> Self {
406        Self(Arc::new(OwnerIdentity {
407            id: NEXT_OWNER_ID.fetch_add(1, Ordering::Relaxed),
408        }))
409    }
410
411    /// 业务作用:比较两个 owner 是否代表同一次 Application 启动。
412    ///
413    /// 参数说明:`other` 是待复验的 owner。
414    ///
415    /// 返回:底层身份相同时返回真。
416    pub fn ptr_eq(&self, other: &Self) -> bool {
417        Arc::ptr_eq(&self.0, &other.0)
418    }
419
420    /// 业务作用:返回不包含资源信息的进程内诊断编号。
421    ///
422    /// 参数说明: 无。
423    ///
424    /// 返回:本进程单调分配的 owner 编号,不作为跨进程协议值。
425    pub fn diagnostic_id(&self) -> u64 {
426        self.0.id
427    }
428
429    /// 业务作用:把 owner 降级为不延长 Application 生命周期的进程模式身份。
430    ///
431    /// 参数说明: 无。
432    ///
433    /// 返回:owner 最后一个强引用释放后无法升级的弱身份。
434    fn downgrade(&self) -> Weak<OwnerIdentity> {
435        Arc::downgrade(&self.0)
436    }
437}
438
439impl Default for ManagedRegistryOwner {
440    /// 业务作用:兼容需要 Default 构造的启动 staging,仍创建唯一 owner。
441    ///
442    /// 参数说明: 无。
443    ///
444    /// 返回:新的独立 owner。
445    fn default() -> Self {
446        Self::new()
447    }
448}
449
450impl std::fmt::Debug for ManagedRegistryOwner {
451    /// 业务作用:输出不包含连接资源的 owner 诊断视图。
452    ///
453    /// 参数说明:`formatter` 是标准格式化目标。
454    ///
455    /// 返回:诊断编号写入成功时返回 `Ok`。
456    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
457        formatter
458            .debug_tuple("ManagedRegistryOwner")
459            .field(&self.diagnostic_id())
460            .finish()
461    }
462}
463
464/// 业务作用:区分常规配置建池与 UserHook 延后 default 引导。
465#[derive(Debug, Clone, Copy, PartialEq, Eq)]
466pub enum BootstrapKind {
467    /// Application 根据冻结配置建立全部 datasource。
468    Configured,
469    /// UserHook 只安装一个 default,Prepare 再接管。
470    DeferredDefault,
471}
472
473/// 业务作用:证明调用方持有当前 Bootstrapping owner,可执行关闭态安装与状态迁移。
474#[derive(Clone, Debug)]
475pub struct ManagedInstallationToken {
476    owner: ManagedRegistryOwner,
477    kind: BootstrapKind,
478}
479
480impl ManagedInstallationToken {
481    /// 业务作用:读取 token 绑定的 Application owner。
482    ///
483    /// 参数说明: 无。
484    ///
485    /// 返回:只读 owner 引用,供 typed registry 绑定同一身份。
486    pub fn owner(&self) -> &ManagedRegistryOwner {
487        &self.owner
488    }
489
490    /// 业务作用:读取本次启动采用的引导路径。
491    ///
492    /// 参数说明: 无。
493    ///
494    /// 返回:配置建池或延后 default 类型。
495    pub fn kind(&self) -> BootstrapKind {
496        self.kind
497    }
498}
499
500/// 业务作用:作为单个 Application 的冻结 datasource 名称与 driver 权威。
501pub struct DataSourceCatalog {
502    owner: ManagedRegistryOwner,
503    entries: BTreeMap<DatasourceRef, DatabaseDriver>,
504    lifecycle: AtomicU8,
505}
506
507const CATALOG_STAGING: u8 = 0;
508const CATALOG_OPEN: u8 = 1;
509const CATALOG_STOPPED: u8 = 2;
510
511impl DataSourceCatalog {
512    /// 业务作用:构造尚未对 getter 开放的冻结 catalog。
513    ///
514    /// 参数说明:
515    /// - `owner`:本次 Application 的共同 owner。
516    /// - `entries`:datasource qualifier 与 driver 的完整集合。
517    ///
518    /// 返回:名称合法、不重复、非空且数量有界时返回关闭态 catalog;失败不发布部分表。
519    pub fn try_new(
520        owner: ManagedRegistryOwner,
521        entries: impl IntoIterator<Item = (String, DatabaseDriver)>,
522    ) -> Result<Self, CatalogBuildError> {
523        let mut catalog = BTreeMap::new();
524        for (name, driver) in entries {
525            if catalog.len() >= MAX_MANAGED_DATASOURCES {
526                return Err(CatalogBuildError::TooManyDatasources);
527            }
528            let reference = DatasourceRef::try_new(name).map_err(CatalogBuildError::InvalidName)?;
529            if catalog.insert(reference.clone(), driver).is_some() {
530                return Err(CatalogBuildError::Duplicate(reference));
531            }
532        }
533        if catalog.is_empty() {
534            return Err(CatalogBuildError::Empty);
535        }
536        Ok(Self {
537            owner,
538            entries: catalog,
539            lifecycle: AtomicU8::new(CATALOG_STAGING),
540        })
541    }
542
543    /// 业务作用:读取 catalog 绑定的 Application owner。
544    ///
545    /// 参数说明: 无。
546    ///
547    /// 返回:共同 owner 的只读引用。
548    pub fn owner(&self) -> &ManagedRegistryOwner {
549        &self.owner
550    }
551
552    /// 业务作用:返回冻结 catalog 的 datasource 数量。
553    ///
554    /// 参数说明: 无。
555    ///
556    /// 返回:跨 driver 合计的条目数。
557    pub fn len(&self) -> usize {
558        self.entries.len()
559    }
560
561    /// 业务作用:判断 catalog 是否没有 datasource。
562    ///
563    /// 参数说明: 无。
564    ///
565    /// 返回:构造成功后固定为假;该入口供通用容器检查使用。
566    pub fn is_empty(&self) -> bool {
567        self.entries.is_empty()
568    }
569
570    /// 业务作用:复制冻结后的 datasource 与 driver 表,供资源登记和观测快照使用。
571    ///
572    /// 参数说明: 无。
573    ///
574    /// 返回:按 datasource 名排序的拥有型条目。
575    pub fn entries(&self) -> Vec<(DatasourceRef, DatabaseDriver)> {
576        self.entries
577            .iter()
578            .map(|(reference, driver)| (reference.clone(), *driver))
579            .collect()
580    }
581
582    /// 业务作用:在 catalog 已开放时解析名称并复验调用方期待的 driver。
583    ///
584    /// 参数说明:
585    /// - `datasource`:待解析名称。
586    /// - `expected`:typed getter 对应的 driver。
587    ///
588    /// 返回:名称和 driver 同时匹配时返回规范引用;关闭、缺失或错配时返回结构化错误。
589    pub fn resolve(
590        &self,
591        datasource: &str,
592        expected: DatabaseDriver,
593    ) -> Result<DatasourceRef, DataSourceLookupError> {
594        match self.lifecycle.load(Ordering::Acquire) {
595            CATALOG_OPEN => {}
596            CATALOG_STOPPED => return Err(DataSourceLookupError::Stopped),
597            _ => return Err(DataSourceLookupError::RegistryUnavailable),
598        }
599        let reference =
600            DatasourceRef::new(datasource).map_err(|_| DataSourceLookupError::InvalidName)?;
601        let actual = self.entries.get(&reference).copied().ok_or_else(|| {
602            DataSourceLookupError::NotFound {
603                datasource: reference.clone(),
604            }
605        })?;
606        if actual != expected {
607            return Err(DataSourceLookupError::DriverMismatch {
608                datasource: reference,
609                expected,
610                actual,
611            });
612        }
613        Ok(reference)
614    }
615
616    /// 业务作用:在全部 typed registry 与资源容器提交后开放 catalog 查询。
617    ///
618    /// 参数说明: 无。
619    ///
620    /// 返回:无;Release 写入保证后续 getter 看见完整冻结条目。
621    fn open(&self) {
622        self.lifecycle.store(CATALOG_OPEN, Ordering::Release);
623    }
624
625    /// 业务作用:在关闭连接池前永久封口 catalog,阻止停机期发放新资源。
626    ///
627    /// 参数说明: 无。
628    ///
629    /// 返回:无;后续查询得到 stopped 分类。
630    fn stop_accepting(&self) {
631        self.lifecycle.store(CATALOG_STOPPED, Ordering::Release);
632    }
633}
634
635/// 业务作用:描述冻结 catalog 构造失败的无连接副作用原因。
636#[derive(Debug, thiserror::Error)]
637pub enum CatalogBuildError {
638    /// 没有 datasource。
639    #[error("managed datasource catalog cannot be empty")]
640    Empty,
641    /// 数量超过受管上限。
642    #[error("managed datasource count exceeds the supported limit")]
643    TooManyDatasources,
644    /// 名称非法。
645    #[error("invalid datasource name")]
646    InvalidName(#[source] DatasourceNameError),
647    /// 名称重复。
648    #[error("datasource `{0}` is configured more than once")]
649    Duplicate(DatasourceRef),
650}
651
652/// 业务作用:为 typed getter 提供稳定的 datasource 查找失败分类。
653#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
654pub enum DataSourceLookupError {
655    /// 名称格式非法。
656    #[error("invalid datasource name")]
657    InvalidName,
658    /// catalog 尚未安装、尚未开放或已失去受管身份。
659    #[error("datasource registry is unavailable")]
660    RegistryUnavailable,
661    /// catalog 已完成封口,旧 Application 不再发放连接。
662    #[error("datasource registry is stopped")]
663    Stopped,
664    /// 名称不在当前 Application catalog。
665    #[error("datasource `{datasource}` is not managed by this application")]
666    NotFound {
667        /// 已校验的 datasource 名称。
668        datasource: DatasourceRef,
669    },
670    /// 名称存在但属于另一数据库 driver。
671    #[error("datasource `{datasource}` uses {actual}, not {expected}")]
672    DriverMismatch {
673        /// 已校验的 datasource 名称。
674        datasource: DatasourceRef,
675        /// typed getter 期待的 driver。
676        expected: DatabaseDriver,
677        /// catalog 中的实际 driver。
678        actual: DatabaseDriver,
679    },
680}
681
682/// 业务作用:对显式事务裁决的全部失败阶段进行封闭分类。
683#[must_use]
684#[derive(Debug, Clone, PartialEq, Eq)]
685pub enum TxDecision<T, E> {
686    /// 当前执行已得到允许提交的领域结果。
687    Commit(T),
688    /// 当前执行没有可提交结果,必须回滚。
689    Rollback(E),
690}
691
692/// 业务作用:保留物理回滚失败之前的原始裁决来源。
693#[derive(Debug)]
694pub enum TxRollbackCause<E> {
695    /// 最外层事务体显式要求回滚。
696    Decision(E),
697    /// 内层事务要求 rollback-only,但外层吞掉了原始错误。
698    RollbackOnly {
699        /// 首次置位时保存的脱敏原因。
700        reason: String,
701    },
702}
703
704/// 业务作用:封闭提交、回滚和基础设施失败分类,供消息 ACK 与重试策略裁决。
705#[derive(Debug)]
706pub enum TxRunError<E> {
707    /// 业务要求回滚,且数据库确认回滚完成。
708    Rollback(E),
709    /// 内层回滚要求被外层吞掉,最外层已确认整体回滚。
710    RollbackOnly {
711        /// 首次置位 rollback-only 时保存的脱敏原因。
712        reason: String,
713    },
714    /// 数据库明确拒绝 COMMIT。
715    CommitRejected {
716        /// 稳定、脱敏的失败分类。
717        reason: String,
718    },
719    /// COMMIT 后连接或协议状态不确定。
720    CommitUncertain {
721        /// 稳定、脱敏的失败分类。
722        reason: String,
723    },
724    /// 物理回滚失败。
725    RollbackFailed {
726        /// 触发回滚的原始裁决。
727        cause: TxRollbackCause<E>,
728        /// 稳定、脱敏的基础设施分类。
729        reason: String,
730    },
731    /// 在事务开始前或内核执行中发生基础设施错误。
732    Infrastructure {
733        /// 稳定、脱敏的失败分类。
734        reason: String,
735    },
736}
737
738/// 业务作用:让加法事务入口分别保留 datasource 查找与事务执行失败,避免调用方解析文本。
739#[derive(Debug)]
740pub enum TxEntryError<E> {
741    /// 事务开始前的 datasource 名称、状态或 driver 校验失败。
742    Lookup(DataSourceLookupError),
743    /// 已进入对应 typed runtime 后的事务裁决失败。
744    Run(TxRunError<E>),
745}
746
747impl<E: std::fmt::Display> std::fmt::Display for TxEntryError<E> {
748    /// 业务作用:输出 checked 事务入口的脱敏失败阶段和稳定原因。
749    ///
750    /// 参数说明:`formatter` 是标准格式化目标。
751    ///
752    /// 返回:分类写入成功时返回 `Ok`,否则返回格式化错误。
753    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
754        match self {
755            Self::Lookup(error) => {
756                write!(formatter, "transaction datasource lookup failed: {error}")
757            }
758            Self::Run(error) => std::fmt::Display::fmt(error, formatter),
759        }
760    }
761}
762
763impl<E> std::error::Error for TxEntryError<E> where E: std::fmt::Debug + std::fmt::Display {}
764
765/// 业务作用:描述数据库对 COMMIT 的可确认结果,供 driver 映射协议级错误。
766#[derive(Debug, Clone, Copy, PartialEq, Eq)]
767pub enum CommitOutcome {
768    /// 数据库明确确认提交完成。
769    Committed,
770    /// 数据库返回明确拒绝,事务没有获得成功确认。
771    Rejected,
772    /// 请求发出后连接或协议中断,无法确认服务端最终结果。
773    OutcomeUnknown,
774}
775
776impl<E: std::fmt::Display> std::fmt::Display for TxRunError<E> {
777    /// 业务作用:输出不含 SQL、连接串和 payload 的事务失败分类。
778    ///
779    /// 参数说明:`formatter` 是标准格式化目标。
780    ///
781    /// 返回:分类写入成功时返回 `Ok`,否则返回格式化错误。
782    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
783        match self {
784            Self::Rollback(error) => write!(formatter, "transaction rolled back: {error}"),
785            Self::RollbackOnly { reason } => {
786                write!(formatter, "transaction was rollback-only: {reason}")
787            }
788            Self::CommitRejected { reason } => write!(formatter, "commit rejected: {reason}"),
789            Self::CommitUncertain { reason } => write!(formatter, "commit uncertain: {reason}"),
790            Self::RollbackFailed { reason, .. } => write!(formatter, "rollback failed: {reason}"),
791            Self::Infrastructure { reason } => {
792                write!(formatter, "transaction infrastructure failed: {reason}")
793            }
794        }
795    }
796}
797
798impl<E> std::error::Error for TxRunError<E> where E: std::fmt::Debug + std::fmt::Display {}
799
800/// 业务作用:描述 driver task-local 的跨后端嵌套拒绝。
801#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
802#[error("ambient transaction driver mismatch: active={active}, requested={requested}")]
803pub struct DriverScopeError {
804    /// 当前任务已绑定的 driver。
805    pub active: DatabaseDriver,
806    /// 本次调用请求的 driver。
807    pub requested: DatabaseDriver,
808}
809
810tokio::task_local! {
811    static ACTIVE_DRIVER: DatabaseDriver;
812}
813
814/// 业务作用:读取当前任务的 ambient transaction driver 哨兵。
815///
816/// 参数说明: 无。
817///
818/// 返回:事务体内返回对应 driver;普通任务与新 spawn 的任务返回 `None`。
819pub fn current_driver() -> Option<DatabaseDriver> {
820    ACTIVE_DRIVER.try_with(|driver| *driver).ok()
821}
822
823/// 业务作用:在执行 SQL 或进入 driver 事务前拒绝跨 driver 复用。
824///
825/// 参数说明:`requested` 是本次 typed 入口对应的 driver。
826///
827/// 返回:当前无哨兵或 driver 一致时成功;错配时返回两侧身份。
828pub fn ensure_driver(requested: DatabaseDriver) -> Result<(), DriverScopeError> {
829    match current_driver() {
830        Some(active) if active != requested => Err(DriverScopeError { active, requested }),
831        _ => Ok(()),
832    }
833}
834
835/// 业务作用:仅在事务业务体执行期间发布 driver 哨兵,阻止嵌套进入另一后端。
836///
837/// 参数说明:
838/// - `driver`:本地事务使用的数据库后端。
839/// - `future`:需要在该后端事务上下文中执行的业务 future。
840///
841/// 返回:无外层 driver 或与外层一致时返回业务输出;错配时不执行 future。
842pub async fn scope_driver<F>(
843    driver: DatabaseDriver,
844    future: F,
845) -> Result<F::Output, DriverScopeError>
846where
847    F: Future,
848{
849    match current_driver() {
850        Some(active) if active != driver => Err(DriverScopeError {
851            active,
852            requested: driver,
853        }),
854        Some(_) => Ok(future.await),
855        None => Ok(ACTIVE_DRIVER.scope(driver, future).await),
856    }
857}
858
859/// 业务作用:对进程级 datasource 模式变化给出稳定拒绝原因。
860#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
861pub enum RegistryCoordinationError {
862    /// 另一 driver 已占用 standalone 模式。
863    #[error("standalone datasource driver conflicts with the active driver")]
864    StandaloneDriverConflict,
865    /// 受管或引导模式拒绝普通 standalone 注册。
866    #[error("standalone datasource registration conflicts with managed application state")]
867    ManagedModeConflict,
868    /// 延后引导只允许 default。
869    #[error("deferred datasource bootstrap accepts only the default datasource")]
870    DeferredOnlyDefault,
871    /// 延后引导已记录另一 driver。
872    #[error("deferred datasource bootstrap already uses another driver")]
873    DeferredDriverConflict,
874    /// 当前模式不能开始新的 Application 引导。
875    #[error("datasource registry is already occupied")]
876    RegistryOccupied,
877    /// owner token 不属于当前启动。
878    #[error("managed registry owner token does not match the active bootstrap")]
879    OwnerMismatch,
880    /// catalog 与 typed registry 没有使用同一 owner。
881    #[error("datasource catalog owner does not match the installation token")]
882    CatalogOwnerMismatch,
883    /// catalog 实例与已发布实例不同。
884    #[error("datasource catalog identity does not match the active managed catalog")]
885    CatalogIdentityMismatch,
886    /// 延后引导没有安装对应 driver 的 default。
887    #[error("deferred datasource bootstrap did not install the expected default driver")]
888    DeferredDriverMissing,
889    /// 清理前仍有延后 standalone 资源。
890    #[error("deferred datasource resources must be removed before bootstrap cleanup")]
891    DeferredResourcesRemain,
892    /// 无 token 的公开 adopt 不能越过 Bootstrapping。
893    #[error("public standalone adopt is unavailable during application bootstrap")]
894    PublicAdoptDuringBootstrap,
895    /// 模式已失去 owner,但仍记录待清理资源。
896    #[error("orphaned deferred datasource resources require explicit cleanup")]
897    OrphanedDeferredResources,
898    /// catalog 不符合延后 default 的单 driver 合同。
899    #[error("deferred datasource catalog must contain only the installed default driver")]
900    InvalidDeferredCatalog,
901}
902
903#[derive(Debug)]
904enum RegistryMode {
905    Empty,
906    Standalone(DatabaseDriver),
907    Bootstrapping {
908        owner: Weak<OwnerIdentity>,
909        kind: BootstrapKind,
910        deferred_driver: Option<DatabaseDriver>,
911    },
912    Managed {
913        owner: Weak<OwnerIdentity>,
914        catalog: Weak<DataSourceCatalog>,
915    },
916}
917
918#[derive(Debug)]
919/// 业务作用:保存进程级 datasource 安装模式与当前 owner 弱引用,线性化独立和受管入口。
920struct RegistryState {
921    mode: RegistryMode,
922}
923
924impl Default for RegistryState {
925    /// 业务作用:初始化尚无任何 datasource 权威的进程协调状态。
926    ///
927    /// 参数说明: 无。
928    ///
929    /// 返回:模式为 Empty 的协调器内部状态。
930    fn default() -> Self {
931        Self {
932            mode: RegistryMode::Empty,
933        }
934    }
935}
936
937static REGISTRY_STATE: OnceLock<Mutex<RegistryState>> = OnceLock::new();
938
939/// 业务作用:暴露进程 datasource 模式的低基数诊断快照。
940#[derive(Debug, Clone, Copy, PartialEq, Eq)]
941pub enum RegistryModeSnapshot {
942    /// 没有 datasource 权威。
943    Empty,
944    /// standalone driver 已占用进程入口。
945    Standalone(DatabaseDriver),
946    /// Application 正在构造受管资源。
947    Bootstrapping {
948        /// 启动路径。
949        kind: BootstrapKind,
950        /// UserHook 已安装的 default driver。
951        deferred_driver: Option<DatabaseDriver>,
952    },
953    /// catalog 已安装,可能仍处于关闭态。
954    Managed,
955    /// owner 已失效但 driver 资源尚待精确清理。
956    OrphanedDeferred(DatabaseDriver),
957}
958
959/// 业务作用:在唯一协调锁内组合 core 模式与 driver typed registry 的状态变化。
960///
961/// 参数说明:`operation` 必须只获取当前 driver 的 registry 锁,并保持 core → driver 的锁顺序。
962///
963/// 返回:原样返回闭包结果;协调锁 poison 时取回内部状态继续执行。
964#[doc(hidden)]
965pub fn coordinate<T>(operation: impl FnOnce(&mut RegistryCoordinator<'_>) -> T) -> T {
966    let mut state = REGISTRY_STATE
967        .get_or_init(|| Mutex::new(RegistryState::default()))
968        .lock()
969        .unwrap_or_else(|error| error.into_inner());
970    let mut coordinator = RegistryCoordinator { state: &mut state };
971    coordinator.sanitize();
972    operation(&mut coordinator)
973}
974
975/// 业务作用:在唯一协调锁内执行受管模式迁移,供 typed driver crate 原子组合本地资源变化。
976#[doc(hidden)]
977pub struct RegistryCoordinator<'a> {
978    state: &'a mut RegistryState,
979}
980
981impl RegistryCoordinator<'_> {
982    /// 业务作用:清除不再持有资源的失效弱 owner,使同一进程能够启动新的 Application。
983    ///
984    /// 参数说明: 无。
985    ///
986    /// 返回:无;仍记录 deferred pool 时保留模式并要求精确清理。
987    fn sanitize(&mut self) {
988        match &self.state.mode {
989            RegistryMode::Bootstrapping {
990                owner,
991                deferred_driver: None,
992                ..
993            } if owner.upgrade().is_none() => {
994                self.state.mode = RegistryMode::Empty;
995            }
996            RegistryMode::Managed { owner, catalog }
997                if owner.upgrade().is_none() && catalog.upgrade().is_none() =>
998            {
999                self.state.mode = RegistryMode::Empty;
1000            }
1001            _ => {}
1002        }
1003    }
1004
1005    /// 业务作用:登记一个 typed standalone datasource,并阻止跨 driver 或受管模式并存。
1006    ///
1007    /// 参数说明:
1008    /// - `driver`:执行登记的 typed driver。
1009    /// - `datasource`:即将写入 driver 本地表的名称。
1010    ///
1011    /// 返回:当前模式允许本地原子写入时成功;失败时调用方不得修改 pool 表。
1012    pub fn register_standalone(
1013        &mut self,
1014        driver: DatabaseDriver,
1015        datasource: &str,
1016    ) -> Result<(), RegistryCoordinationError> {
1017        match &mut self.state.mode {
1018            RegistryMode::Empty => {
1019                self.state.mode = RegistryMode::Standalone(driver);
1020                Ok(())
1021            }
1022            RegistryMode::Standalone(active) if *active == driver => Ok(()),
1023            RegistryMode::Standalone(_) => Err(RegistryCoordinationError::StandaloneDriverConflict),
1024            RegistryMode::Bootstrapping {
1025                owner,
1026                kind: BootstrapKind::DeferredDefault,
1027                deferred_driver,
1028            } => {
1029                if owner.upgrade().is_none() && deferred_driver.is_some() {
1030                    return Err(RegistryCoordinationError::OrphanedDeferredResources);
1031                }
1032                if datasource != DEFAULT_DATASOURCE {
1033                    return Err(RegistryCoordinationError::DeferredOnlyDefault);
1034                }
1035                match deferred_driver {
1036                    Some(active) if *active != driver => {
1037                        Err(RegistryCoordinationError::DeferredDriverConflict)
1038                    }
1039                    Some(_) => Ok(()),
1040                    slot @ None => {
1041                        *slot = Some(driver);
1042                        Ok(())
1043                    }
1044                }
1045            }
1046            RegistryMode::Bootstrapping { .. } | RegistryMode::Managed { .. } => {
1047                Err(RegistryCoordinationError::ManagedModeConflict)
1048            }
1049        }
1050    }
1051
1052    /// 业务作用:在 driver 已确认本地 standalone 表为空后释放进程模式。
1053    ///
1054    /// 参数说明:`driver` 是刚完成精确清理的 typed driver。
1055    ///
1056    /// 返回:模式属于该 driver 时成功;另一 driver 或受管状态返回冲突。
1057    pub fn release_standalone(
1058        &mut self,
1059        driver: DatabaseDriver,
1060    ) -> Result<(), RegistryCoordinationError> {
1061        match &mut self.state.mode {
1062            RegistryMode::Standalone(active) if *active == driver => {
1063                self.state.mode = RegistryMode::Empty;
1064                Ok(())
1065            }
1066            RegistryMode::Bootstrapping {
1067                owner,
1068                kind: BootstrapKind::DeferredDefault,
1069                deferred_driver: Some(active),
1070            } if *active == driver => {
1071                let owner_alive = owner.upgrade().is_some();
1072                if owner_alive {
1073                    if let RegistryMode::Bootstrapping {
1074                        deferred_driver, ..
1075                    } = &mut self.state.mode
1076                    {
1077                        *deferred_driver = None;
1078                    }
1079                } else {
1080                    self.state.mode = RegistryMode::Empty;
1081                }
1082                Ok(())
1083            }
1084            RegistryMode::Empty => Ok(()),
1085            _ => Err(RegistryCoordinationError::ManagedModeConflict),
1086        }
1087    }
1088
1089    /// 业务作用:开始一次配置建池或延后 default 的受管启动。
1090    ///
1091    /// 参数说明:
1092    /// - `owner`:本次 Application 唯一 owner。
1093    /// - `kind`:启动路径类型。
1094    ///
1095    /// 返回:进程入口为空时返回 owner token;已有资源时不改变模式。
1096    pub fn begin_bootstrap(
1097        &mut self,
1098        owner: &ManagedRegistryOwner,
1099        kind: BootstrapKind,
1100    ) -> Result<ManagedInstallationToken, RegistryCoordinationError> {
1101        if !matches!(self.state.mode, RegistryMode::Empty) {
1102            return Err(RegistryCoordinationError::RegistryOccupied);
1103        }
1104        self.state.mode = RegistryMode::Bootstrapping {
1105            owner: owner.downgrade(),
1106            kind,
1107            deferred_driver: None,
1108        };
1109        Ok(ManagedInstallationToken {
1110            owner: owner.clone(),
1111            kind,
1112        })
1113    }
1114
1115    /// 业务作用:把普通 standalone 转入旧公开 adopt 使用的受管安装窗口。
1116    ///
1117    /// 参数说明:
1118    /// - `owner`:旧入口内部新建的 owner。
1119    /// - `driver`:必须与当前 standalone driver 一致。
1120    ///
1121    /// 返回:普通 standalone 时返回 token;Bootstrapping 明确拒绝无 token 越权接管。
1122    pub fn begin_legacy_adopt(
1123        &mut self,
1124        owner: &ManagedRegistryOwner,
1125        driver: DatabaseDriver,
1126    ) -> Result<ManagedInstallationToken, RegistryCoordinationError> {
1127        match &self.state.mode {
1128            RegistryMode::Standalone(active) if *active == driver => {
1129                self.state.mode = RegistryMode::Bootstrapping {
1130                    owner: owner.downgrade(),
1131                    kind: BootstrapKind::Configured,
1132                    deferred_driver: None,
1133                };
1134                Ok(ManagedInstallationToken {
1135                    owner: owner.clone(),
1136                    kind: BootstrapKind::Configured,
1137                })
1138            }
1139            RegistryMode::Bootstrapping { .. } => {
1140                Err(RegistryCoordinationError::PublicAdoptDuringBootstrap)
1141            }
1142            _ => Err(RegistryCoordinationError::RegistryOccupied),
1143        }
1144    }
1145
1146    /// 业务作用:旧 adopt 发布失败时恢复调用前的 standalone 模式。
1147    ///
1148    /// 参数说明:
1149    /// - `token`:旧 adopt 创建的安装 token。
1150    /// - `driver`:恢复后的 standalone driver。
1151    ///
1152    /// 返回:owner 仍匹配时恢复;状态已被其它 owner 替换时拒绝。
1153    pub fn restore_legacy_standalone(
1154        &mut self,
1155        token: &ManagedInstallationToken,
1156        driver: DatabaseDriver,
1157    ) -> Result<(), RegistryCoordinationError> {
1158        self.verify_bootstrap_owner(token)?;
1159        self.state.mode = RegistryMode::Standalone(driver);
1160        Ok(())
1161    }
1162
1163    /// 业务作用:复验延后 default 已由同一 owner 安装指定 driver,允许关闭态接管。
1164    ///
1165    /// 参数说明:
1166    /// - `token`:Application 在 Start 领取的 token。
1167    /// - `driver`:typed adopt 对应的 driver。
1168    ///
1169    /// 返回:owner、kind 与 deferred driver 全部匹配时成功。
1170    pub fn verify_deferred_adopt(
1171        &mut self,
1172        token: &ManagedInstallationToken,
1173        driver: DatabaseDriver,
1174    ) -> Result<(), RegistryCoordinationError> {
1175        self.verify_bootstrap_owner(token)?;
1176        match &self.state.mode {
1177            RegistryMode::Bootstrapping {
1178                kind: BootstrapKind::DeferredDefault,
1179                deferred_driver: Some(active),
1180                ..
1181            } if *active == driver => Ok(()),
1182            _ => Err(RegistryCoordinationError::DeferredDriverMissing),
1183        }
1184    }
1185
1186    /// 业务作用:复验 typed registry 安装者持有当前 Bootstrapping owner token。
1187    ///
1188    /// 参数说明:`token` 是 driver crate 收到的安装凭据。
1189    ///
1190    /// 返回:owner 与启动类型同时匹配时成功;错配时不得修改 driver 本地槽。
1191    pub fn verify_installation_token(
1192        &self,
1193        token: &ManagedInstallationToken,
1194    ) -> Result<(), RegistryCoordinationError> {
1195        self.verify_bootstrap_owner(token)
1196    }
1197
1198    /// 业务作用:把关闭态 catalog 安装为进程唯一受管权威,但尚不开放 getter。
1199    ///
1200    /// 参数说明:
1201    /// - `token`:当前 Application token。
1202    /// - `catalog`:已冻结且 owner 相同的完整 catalog。
1203    ///
1204    /// 返回:模式和 owner 匹配时转入 Managed;失败时 catalog 保持关闭。
1205    pub fn install_catalog(
1206        &mut self,
1207        token: &ManagedInstallationToken,
1208        catalog: &Arc<DataSourceCatalog>,
1209    ) -> Result<(), RegistryCoordinationError> {
1210        self.verify_bootstrap_owner(token)?;
1211        if !catalog.owner().ptr_eq(token.owner()) {
1212            return Err(RegistryCoordinationError::CatalogOwnerMismatch);
1213        }
1214        if let RegistryMode::Bootstrapping {
1215            kind: BootstrapKind::DeferredDefault,
1216            deferred_driver: Some(driver),
1217            ..
1218        } = &self.state.mode
1219        {
1220            let entries = catalog.entries();
1221            if entries.len() != 1
1222                || entries[0].0.as_str() != DEFAULT_DATASOURCE
1223                || entries[0].1 != *driver
1224            {
1225                return Err(RegistryCoordinationError::InvalidDeferredCatalog);
1226            }
1227        }
1228        self.state.mode = RegistryMode::Managed {
1229            owner: token.owner.downgrade(),
1230            catalog: Arc::downgrade(catalog),
1231        };
1232        Ok(())
1233    }
1234
1235    /// 业务作用:在 typed registry 与 Application 资源表全部提交后开放唯一 catalog。
1236    ///
1237    /// 参数说明:
1238    /// - `token`:当前 Application token。
1239    /// - `catalog`:必须是已安装的同一 Arc 实例。
1240    ///
1241    /// 返回:身份复验通过时开放 getter;错配时保持关闭。
1242    pub fn open_catalog(
1243        &mut self,
1244        token: &ManagedInstallationToken,
1245        catalog: &Arc<DataSourceCatalog>,
1246    ) -> Result<(), RegistryCoordinationError> {
1247        match &self.state.mode {
1248            RegistryMode::Managed {
1249                owner,
1250                catalog: active,
1251            } => {
1252                let Some(active_owner) = owner.upgrade() else {
1253                    return Err(RegistryCoordinationError::OwnerMismatch);
1254                };
1255                if !Arc::ptr_eq(&active_owner, &token.owner.0) {
1256                    return Err(RegistryCoordinationError::OwnerMismatch);
1257                }
1258                let Some(active_catalog) = active.upgrade() else {
1259                    return Err(RegistryCoordinationError::CatalogIdentityMismatch);
1260                };
1261                if !Arc::ptr_eq(&active_catalog, catalog) {
1262                    return Err(RegistryCoordinationError::CatalogIdentityMismatch);
1263                }
1264                catalog.open();
1265                Ok(())
1266            }
1267            _ => Err(RegistryCoordinationError::OwnerMismatch),
1268        }
1269    }
1270
1271    /// 业务作用:按 owner 封口并撤销当前 managed catalog,阻止旧 Application 清理新实例。
1272    ///
1273    /// 参数说明:`owner` 是正在逆序停机的 Application owner。
1274    ///
1275    /// 返回:owner 命中时撤销;不命中时保持现有权威并返回错误。
1276    pub fn clear_managed(
1277        &mut self,
1278        owner: &ManagedRegistryOwner,
1279    ) -> Result<(), RegistryCoordinationError> {
1280        match &self.state.mode {
1281            RegistryMode::Managed {
1282                owner: active,
1283                catalog,
1284            } => {
1285                let Some(active_owner) = active.upgrade() else {
1286                    return Err(RegistryCoordinationError::OwnerMismatch);
1287                };
1288                if !Arc::ptr_eq(&active_owner, &owner.0) {
1289                    return Err(RegistryCoordinationError::OwnerMismatch);
1290                }
1291                if let Some(catalog) = catalog.upgrade() {
1292                    catalog.stop_accepting();
1293                }
1294                self.state.mode = RegistryMode::Empty;
1295                Ok(())
1296            }
1297            _ => Err(RegistryCoordinationError::OwnerMismatch),
1298        }
1299    }
1300
1301    /// 业务作用:在 typed deferred pool 已被精确取走后清除 driver 记录。
1302    ///
1303    /// 参数说明:
1304    /// - `token`:当前 Application token。
1305    /// - `driver`:刚完成本地清理的 driver。
1306    ///
1307    /// 返回:owner 与 driver 匹配时清除记录;错配时保留模式。
1308    pub fn clear_deferred_driver(
1309        &mut self,
1310        token: &ManagedInstallationToken,
1311        driver: DatabaseDriver,
1312    ) -> Result<(), RegistryCoordinationError> {
1313        self.verify_bootstrap_owner(token)?;
1314        match &mut self.state.mode {
1315            RegistryMode::Bootstrapping {
1316                kind: BootstrapKind::DeferredDefault,
1317                deferred_driver: Some(active),
1318                ..
1319            } if *active == driver => {
1320                if let RegistryMode::Bootstrapping {
1321                    deferred_driver, ..
1322                } = &mut self.state.mode
1323                {
1324                    *deferred_driver = None;
1325                }
1326                Ok(())
1327            }
1328            _ => Err(RegistryCoordinationError::DeferredDriverMissing),
1329        }
1330    }
1331
1332    /// 业务作用:在本轮 typed 资源全部清空后释放 Bootstrapping 占用。
1333    ///
1334    /// 参数说明:`token` 是待撤销启动的 owner token。
1335    ///
1336    /// 返回:owner 匹配且没有 deferred 资源时回到 Empty;否则保留模式。
1337    pub fn abort_bootstrap(
1338        &mut self,
1339        token: &ManagedInstallationToken,
1340    ) -> Result<(), RegistryCoordinationError> {
1341        self.verify_bootstrap_owner(token)?;
1342        match &self.state.mode {
1343            RegistryMode::Bootstrapping {
1344                deferred_driver: Some(_),
1345                ..
1346            } => Err(RegistryCoordinationError::DeferredResourcesRemain),
1347            RegistryMode::Bootstrapping { .. } => {
1348                self.state.mode = RegistryMode::Empty;
1349                Ok(())
1350            }
1351            _ => Err(RegistryCoordinationError::OwnerMismatch),
1352        }
1353    }
1354
1355    /// 业务作用:返回协调锁保护下的低基数模式快照。
1356    ///
1357    /// 参数说明: 无。
1358    ///
1359    /// 返回:不暴露 owner、URL 或 datasource 名称的模式分类。
1360    pub fn snapshot(&self) -> RegistryModeSnapshot {
1361        match &self.state.mode {
1362            RegistryMode::Empty => RegistryModeSnapshot::Empty,
1363            RegistryMode::Standalone(driver) => RegistryModeSnapshot::Standalone(*driver),
1364            RegistryMode::Bootstrapping {
1365                owner,
1366                kind,
1367                deferred_driver,
1368            } => match (owner.upgrade(), deferred_driver) {
1369                (None, Some(driver)) => RegistryModeSnapshot::OrphanedDeferred(*driver),
1370                _ => RegistryModeSnapshot::Bootstrapping {
1371                    kind: *kind,
1372                    deferred_driver: *deferred_driver,
1373                },
1374            },
1375            RegistryMode::Managed { .. } => RegistryModeSnapshot::Managed,
1376        }
1377    }
1378
1379    /// 业务作用:复验 token 仍代表当前 Bootstrapping owner 与引导类型,阻止旧实例越权迁移状态。
1380    ///
1381    /// 参数说明:`token` 是 typed driver 收到的安装凭据。
1382    ///
1383    /// 返回:owner Arc 身份与 kind 同时匹配时成功;其它状态返回 owner mismatch。
1384    fn verify_bootstrap_owner(
1385        &self,
1386        token: &ManagedInstallationToken,
1387    ) -> Result<(), RegistryCoordinationError> {
1388        match &self.state.mode {
1389            RegistryMode::Bootstrapping { owner, kind, .. } => {
1390                let Some(active) = owner.upgrade() else {
1391                    return Err(RegistryCoordinationError::OwnerMismatch);
1392                };
1393                if Arc::ptr_eq(&active, &token.owner.0) && *kind == token.kind {
1394                    Ok(())
1395                } else {
1396                    Err(RegistryCoordinationError::OwnerMismatch)
1397                }
1398            }
1399            _ => Err(RegistryCoordinationError::OwnerMismatch),
1400        }
1401    }
1402}
1403
1404/// 业务作用:读取当前进程 datasource 模式,供启动门禁和诊断复验。
1405///
1406/// 参数说明: 无。
1407///
1408/// 返回:已经执行弱 owner 自愈后的低基数模式快照。
1409pub fn registry_mode() -> RegistryModeSnapshot {
1410    coordinate(|coordinator| coordinator.snapshot())
1411}
1412
1413/// 业务作用:为 Application 领取唯一 owner 并进入配置建池或延后 default 的启动模式。
1414///
1415/// 参数说明:`kind` 指明 datasource 来自冻结配置还是 UserHook。
1416///
1417/// 返回:进程入口为空时返回 owner 与同身份 token;已有资源时不改变当前权威。
1418pub fn begin_managed_bootstrap(
1419    kind: BootstrapKind,
1420) -> Result<(ManagedRegistryOwner, ManagedInstallationToken), RegistryCoordinationError> {
1421    let owner = ManagedRegistryOwner::new();
1422    let token = coordinate(|coordinator| coordinator.begin_bootstrap(&owner, kind))?;
1423    Ok((owner, token))
1424}
1425
1426/// 业务作用:安装完整关闭态 catalog,形成尚不可读的 Managed 权威。
1427///
1428/// 参数说明:
1429/// - `token`:当前 Application 安装 token。
1430/// - `catalog`:已冻结且绑定同 owner 的 catalog。
1431///
1432/// 返回:owner 与模式匹配时完成安装;失败时 catalog 保持关闭。
1433pub fn install_managed_catalog(
1434    token: &ManagedInstallationToken,
1435    catalog: &Arc<DataSourceCatalog>,
1436) -> Result<(), RegistryCoordinationError> {
1437    coordinate(|coordinator| coordinator.install_catalog(token, catalog))
1438}
1439
1440/// 业务作用:在 typed registry 与资源容器全部提交后开放 managed catalog。
1441///
1442/// 参数说明:
1443/// - `token`:当前 Application 安装 token。
1444/// - `catalog`:必须是此前安装的同一 Arc。
1445///
1446/// 返回:身份复验通过时开放;失败时 getter 继续返回不可用。
1447pub fn open_managed_catalog(
1448    token: &ManagedInstallationToken,
1449    catalog: &Arc<DataSourceCatalog>,
1450) -> Result<(), RegistryCoordinationError> {
1451    coordinate(|coordinator| coordinator.open_catalog(token, catalog))
1452}
1453
1454/// 业务作用:在 driver 资源已封口后按 owner 撤销 managed catalog。
1455///
1456/// 参数说明:`owner` 是正在停机的 Application owner。
1457///
1458/// 返回:owner 命中时撤销;旧 owner 或非 Managed 模式返回错误且不影响新实例。
1459pub fn clear_managed_catalog(
1460    owner: &ManagedRegistryOwner,
1461) -> Result<(), RegistryCoordinationError> {
1462    coordinate(|coordinator| coordinator.clear_managed(owner))
1463}
1464
1465/// 业务作用:在 typed 资源尚未发布或已经清空时释放 Bootstrapping。
1466///
1467/// 参数说明:`token` 是待撤销启动的 owner token。
1468///
1469/// 返回:没有延后资源时回到 Empty;仍有资源时拒绝,要求先由对应 driver 精确清理。
1470pub fn abort_managed_bootstrap(
1471    token: &ManagedInstallationToken,
1472) -> Result<(), RegistryCoordinationError> {
1473    coordinate(|coordinator| coordinator.abort_bootstrap(token))
1474}
1475
1476/// 业务作用:解析全局 datasource 并复验 typed getter 的 driver 身份。
1477///
1478/// 参数说明:
1479/// - `datasource`:业务请求的 qualifier。
1480/// - `expected`:调用入口对应的 driver。
1481///
1482/// 返回:standalone、UserHook 延后引导期的同 driver `default`,或开放 managed catalog
1483/// 允许该 driver 时返回规范引用;其它模式返回结构化错误。
1484pub fn resolve_datasource(
1485    datasource: &str,
1486    expected: DatabaseDriver,
1487) -> Result<DatasourceRef, DataSourceLookupError> {
1488    coordinate(|coordinator| match &coordinator.state.mode {
1489        RegistryMode::Empty => {
1490            // 尚未安装任何 runtime 时只规范化名称,具体 typed registry 继续给出既有 NotFound 语义;
1491            // Bootstrapping 则必须保持不可读,不能把正在建立的权威误判成普通未初始化。
1492            DatasourceRef::new(datasource).map_err(|_| DataSourceLookupError::InvalidName)
1493        }
1494        RegistryMode::Bootstrapping {
1495            kind: BootstrapKind::DeferredDefault,
1496            deferred_driver: Some(actual),
1497            ..
1498        } if *actual == expected && datasource == DEFAULT_DATASOURCE => {
1499            // UserHook 只能在应用尚未 Ready 的窗口内使用刚注入的唯一 default;开放这条精确入口
1500            // 才能完成 schema 自举与运行时装配,命名库、另一 driver 和其它引导模式仍保持不可读。
1501            DatasourceRef::new(datasource).map_err(|_| DataSourceLookupError::InvalidName)
1502        }
1503        RegistryMode::Bootstrapping { .. } => Err(DataSourceLookupError::RegistryUnavailable),
1504        RegistryMode::Standalone(actual) if *actual == expected => {
1505            DatasourceRef::new(datasource).map_err(|_| DataSourceLookupError::InvalidName)
1506        }
1507        RegistryMode::Standalone(actual) => {
1508            let reference =
1509                DatasourceRef::new(datasource).map_err(|_| DataSourceLookupError::InvalidName)?;
1510            Err(DataSourceLookupError::DriverMismatch {
1511                datasource: reference,
1512                expected,
1513                actual: *actual,
1514            })
1515        }
1516        RegistryMode::Managed { catalog, .. } => catalog
1517            .upgrade()
1518            .ok_or(DataSourceLookupError::RegistryUnavailable)?
1519            .resolve(datasource, expected),
1520    })
1521}
1522
1523/// 业务作用:读取当前开放的 managed catalog,供 Application getter 与观测聚合使用。
1524///
1525/// 参数说明: 无。
1526///
1527/// 返回:Managed 且 catalog owner 仍存活时返回同一 Arc;其它模式返回不可用。
1528pub fn managed_catalog() -> Result<Arc<DataSourceCatalog>, DataSourceLookupError> {
1529    coordinate(|coordinator| match &coordinator.state.mode {
1530        RegistryMode::Managed { catalog, .. } => catalog
1531            .upgrade()
1532            .ok_or(DataSourceLookupError::RegistryUnavailable)
1533            .and_then(|catalog| match catalog.lifecycle.load(Ordering::Acquire) {
1534                CATALOG_OPEN => Ok(catalog),
1535                CATALOG_STOPPED => Err(DataSourceLookupError::Stopped),
1536                _ => Err(DataSourceLookupError::RegistryUnavailable),
1537            }),
1538        _ => Err(DataSourceLookupError::RegistryUnavailable),
1539    })
1540}