From bb87316773e08009bb8dc71c5e5c874046b9a4b8 Mon Sep 17 00:00:00 2001 From: panxiao81 Date: Sun, 13 Sep 2026 15:20:26 +0000 Subject: [PATCH] docs: clarify Instance identity and deletion semantics --- docs/api-reference.md | 10 ++++++++-- docs/domain-instance.md | 22 +++++++++++++++++----- docs/domain-model.md | 19 +++++++++++-------- docs/specification.md | 12 ++++++++++++ 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/docs/api-reference.md b/docs/api-reference.md index 7112082..2eb6ae4 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -50,6 +50,9 @@ namespace,名称须合法,两个字段须存在且非空。管理员维护 E Instance endpoint、管理凭据引用和 allowlist 可以修改。修改后 controller 重新验证; 删除 allowlist 项目不会自动从已有 Tenant database 删除 extension。 +endpoint 由管理员负责,不校验变更前后是否同一物理服务器/registry,只重验新配置 +的连接与管理能力。新 UID 按新 Instance 处理,不授权接管旧 UID 的 Tenant 资源。 + ### Status | JSON path | 类型 | 含义 | @@ -147,8 +150,11 @@ phase 用于进度展示、恢复和排障。 - `Retain` 不需要等待外部依赖;删除 CR 后外部记录保留原 UID 并标记 unmanaged。 - `Delete` 添加 finalizer,严格按规格的所有权验证和清理顺序执行;失败保持 finalizer。 -- controller 不为 `PostgreSQLInstance` 级联删除 Tenant 或外部资源;存在引用时 Instance - 删除应被 finalizer 阻止,直到 Tenant 被删除或管理员使用运维逃生流程。 +- Instance 开始受管时即添加并保存 finalizer;删除时停止新供应,存在 Tenant 引用 + (包括正在删除的 Tenant)就保留 finalizer,无引用才移除。引用查询失败时继续等待。 + 不级联删除 Tenant 或外部资源;管理员可使用运维逃生流程。 +- finalizer 不禁止创建 Tenant CR;并发创建者遇到删除中或不存在的 Instance 不得 + 开始供应。首版不增加跨对象锁或准入控制,不承诺跨对象原子删除。 ## 示例 diff --git a/docs/domain-instance.md b/docs/domain-instance.md index ddd6a92..1824194 100644 --- a/docs/domain-instance.md +++ b/docs/domain-instance.md @@ -1,6 +1,6 @@ # Instance 领域对象规格 -状态:Draft,待批准。日期:2026-09-12。 +状态:Draft,含已确认决策。日期:2026-09-13。 上层边界见 [领域模型](domain-model.md)。本文只展开 Instance,不包含 Tenant 的供应 实现,也不新增 CRD 字段。设计签名用于评审职责与行为,不是待复制的 Go 接口代码。 @@ -18,6 +18,11 @@ context、客户端或 IO 接口。领域行为不是公共 SetReady:调用方 每轮从 CR 重建一个 Instance;对象不跨 reconcile 缓存,也不是线程共享单例。 管理连接可由装配层跨轮次复用,但连接复用不代表上次能力验证仍然成立。 +身份与 endpoint 以管理员声明为准。改变 endpoint 不验证是否同一物理服务器或 +registry,不增加安装身份连续性检查;只使旧观察失效,按新配置重验管理能力。 +新 CR 是新 Instance,不自动获得旧 UID 资源的所有权,也不迁移或清理旧目标。 +下文“观察绑定匹配”仅指结果属于本轮身份/配置,不是物理服务器身份认证协议。 + ## 2. 字段与值对象 所有可变状态封装在对象内部。构造后身份和本轮 definition 不可变;配置变更通过 @@ -130,8 +135,8 @@ EnsureRegistry(context, target) -> Completed | AccessFailure endpoint 的成功结果不得用于新 endpoint。Inspect 是只读;EnsureRegistry 是幂等初始化/迁移, 不能顺带建立 Tenant 数据库或接管未知 schema。Completed 不足以推进 Ready,必须回读。 -适配器由装配层绑定管理连接;凭据源、连接池释放及 Bao token 重新认证留在该边界 -之后。适配器不得自行把基础设施异常转换成 Ready。返回的失败至少区分依赖不可用、 +适配器由装配层绑定管理连接;Secret 读取与连接池释放留在该边界之后,Instance +管理连接不涉及 Bao token。适配器不得把基础设施异常转换成 Ready。失败区分依赖不可用、 认证失败、权限不足和 registry 不兼容;不兼容属于不可安全继续,不自动覆写。 registry 不兼容的具体 Condition 映射须在接口规格中确定,不能统一误报权限不足。 @@ -184,7 +189,13 @@ Ready --registry 需修复/保存--> InitializingRegistry - 外部 IO 超时:产生安全失败结果;保存 status 使用仍有效的外层上下文,不能复用 已超时的 IO 上下文而丢失失败状态。 - 已请求删除的 Instance 不允许新供应;BeginDeletion 不删除 PostgreSQL、Tenant 或 - Bao。Tenant 引用检查及 Instance 删除竞争协议仍需另行批准。 + Bao。应用层在开始受管时添加并保存 finalizer,而非出现 Tenant 后再添加。 + 删除时查询所有引用它的 Tenant(含删除中的对象);有引用或查询失败就保留 + finalizer,确认无引用才移除。引用查询、finalizer 写入和本地连接释放均不属于 + 领域 IO,Instance 只根据删除请求禁用供应能力。 +- 首版不为 Instance 删除增加跨对象锁或准入控制。并发创建的 Tenant CR 不被 + finalizer 拦截,但遇到删除中/不存在的 Instance 不得开始供应;不承诺取消 + 已在途的外部操作,也不声称引用查询与移除 finalizer 是跨对象原子事务。 - CheckExtensions 失败不能产生任何外部写入;修改 allowlist 不会自行卸载扩展。 - Snapshot、错误、日志和领域对象格式化不输出明文凭据或 token。 - 领域测试只提供观察值,无需数据库、网络、context 或 IO mock;相同状态和输入 @@ -197,6 +208,7 @@ Ready --registry 需修复/保存--> InitializingRegistry 本轮请先确认字段归属、应用层采集事实/Instance 纯决策的分工、方法与状态转换合同。 管理 Secret 来源、Bao 故障不单独撤销 Instance Ready,以及管理用户名/密码变化时 -重建连接池已确认。其他决策及未决项见总体草案,不增加后台清扫器或状态字段。 +重建连接池,以及管理员声明的 Instance 身份/endpoint 和简化 finalizer 删除规则 +均已确认。其他决策及未决项见总体草案,不增加后台清扫器或状态字段。 批准本对象结构不等于批准这些未决行为,也不意味着立刻实现完整供应链路。 diff --git a/docs/domain-model.md b/docs/domain-model.md index bb789ca..81cd951 100644 --- a/docs/domain-model.md +++ b/docs/domain-model.md @@ -1,6 +1,6 @@ # 领域模型设计草案 -状态:Draft,待评审。日期:2026-09-12。 +状态:Draft,含已确认决策。日期:2026-09-13。 本文定义领域职责、身份与一致性边界,并用对象规格细化字段和方法合同;方法使用 设计签名,不固定 Go 目录、SDK 或框架,也不批准实现。外部行为以 @@ -124,12 +124,11 @@ phase 只决定候选步骤,外部证据决定该步骤是否允许执行、 测试验证 checkpoint 持久化和重启恢复;E2E 验证最终合同。不能只验证一串 mock 调用 就声称实现了最终一致性。 -## 6. 批准前需明确的边界 +## 6. 决策记录与待细化边界 -1. **Instance 身份与物理目标**:规格允许 endpoint 变化,但同一个 Instance UID 指向 - 另一台服务器,或者多个 Instance 指向同一台服务器时,既有 Claim 怎么解释?不能 - 仅凭 CR UID 判断物理隔离,或将已有租户无声迁移。需决定限制还是引入可验证的 - 服务器/安装身份;本文不新增限制。 +1. **Instance 身份与物理目标(已确认)**:以管理员声明为准,endpoint 变更不验证 + 物理服务器/registry 连续性,不增加安装身份绑定检查;旧观察失效,重验新配置 + 的连接与管理能力。新 CR 视为新 Instance,不自动接管旧 UID 资源或迁移数据。 2. **Retain 完成条件**:外部依赖不可用不能永久阻止 CR 删除,但 registry 又需标记 unmanaged。需定义 CR 消失后的补偿/清扫入口及所需身份依据,不能承诺同时原子 完成两者,也不能在没有回读时声称已写入保留标记。 @@ -142,5 +141,9 @@ phase 只决定候选步骤,外部证据决定该步骤是否允许执行、 不可变”。应明确绑定在认领、首次外部写入还是 Ready 时固定,及如何在 status 丢失 后恢复;否则供应中途改名称可能产生无人管理的资源。 -本轮先评审第 1–3 节的对象与职责划分;上述问题记录在案,相关用例在决策批准前不 -进入实现。下一份小改动只细化一个用例,不同时实现整套模型。 +5. **Instance 删除(已确认)**:开始受管即添加 finalizer;删除期间停止新供应, + 有 Tenant 引用就等待,无引用才解除,不级联删除外部资源。首版采用 finalizer + 与引用检查,不引入跨对象锁/准入控制;不保证并发创建与删除的原子性。 + +Tenant 的 Retain 等待决行为留到 Tenant 设计,不属于本轮 Instance 设计范围。 +相关用例在决策批准前不进入实现,不同时实现整套模型。 diff --git a/docs/specification.md b/docs/specification.md index 698f5ff..bd8580c 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -99,6 +99,18 @@ PostgreSQL 管理 role。应用或 GitOps 流程在获得 namespace RBAC 后管 实例 Ready 不代表 PostgreSQL 数据有备份或高可用,只表示 controller 当前可以安全 建立管理连接、读取 server metadata、访问 controller registry 并使用所需管理能力。 +Instance 身份和 endpoint 以管理员声明为准。修改 endpoint 不验证是否仍是原物理 +服务器或原 registry,不增加服务器/安装身份绑定检查;但旧配置观察失效,必须按 +新配置重新检查连接和管理能力。新 CR 按新 Instance 处理,不自动接管旧 UID 的租户 +资源。controller 不迁移旧服务器上的数据,也不清理旧目标,影响由管理员负责评估。 + +Instance 开始受管时即添加 finalizer,成功保存后才参与供应,不等发现 Tenant 后 +再补加。删除期间停止新供应;仍有引用它的 Tenant(包括正在删除的 Tenant)时保留 +finalizer,无引用后才移除。不级联删除 Tenant 或任何外部数据库、角色、凭据。 +引用检查失败不得当作无引用。首版不引入跨对象锁或准入控制:finalizer 不禁止同时 +创建 Tenant CR,新 Tenant 遇到正在删除或已不存在的 Instance 时不得开始供应。 +这不保证列表检查、CR 创建和在途外部操作之间的原子性;不是严格的跨对象事务。 + ### 5.2 PostgreSQLTenant `PostgreSQLTenant` 是 namespaced 资源。v1alpha1 中,一个 Tenant 精确对应: