Files
dbtool-cli-v1/plans/2026-03-26-cmp-25-tui-cli-architecture-boundary.md
Paperclip CTO d5f69462b0
Some checks failed
release-smoke / macos-13 / x86_64-apple-darwin (push) Has been cancelled
release-smoke / ubuntu-latest / x86_64-unknown-linux-gnu (push) Has been cancelled
release-smoke / windows-latest / x86_64-pc-windows-msvc (push) Has been cancelled
feat(usable): integrate current dbtool implementation snapshot
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-02 08:26:18 +00:00

202 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CMP-25 `dbtool-tui-v1` / CLI core 架构边界与模块拆分
日期2026-03-26
作者CTO
对应 issue`CMP-25`
## 1. 当前真实状态
- Rust workspace 已落地 `apps/cli``apps/tui``crates/db-core``crates/db-config``crates/db-drivers``crates/db-app`
- `apps/tui` 已有可运行 shell六区布局、焦点切换、基础键盘导航、`Ready/Loading/Error` 状态框架均已落地。
- `crates/db-app` 已存在,且已提供 `connect` / `inspect` / `query` / `export` 的结构化响应与统一错误映射。
- 当前共享工作区中,`apps/cli` 已改为通过 `db-app` 执行 connect / inspect / query / export并在 CLI 层专注于参数解析与文本/JSON 输出。
- 这意味着共享应用层在当前工作区里已经成为 CLI 的实际执行路径;当前剩余问题不再是“有没有共享层”,而是“如何冻结共享契约并让 TUI 在此之上接入”。
## 2. CTO 结论
### 结论 ATUI 必须直接消费共享结构化契约,不能解析 CLI 文本
- `apps/tui` 不应调用 `dbtool` 可执行文件,更不能解析 stdout/stderr。
- TUI 应直接链接 `crates/db-app`,消费结构化 `Response` / `AppError`
- CLI 文本输出仍然存在,但只作为 CLI adapter 的人类可读呈现层。
### 结论 B`db-app` 是 CLI 与 TUI 之间唯一允许共享的用例编排层
- `db-core` 负责领域模型、请求/响应对象、输入校验。
- `db-drivers` 负责 PostgreSQL / MySQL / SQLite 的具体 I/O 和差异处理。
- `db-app` 负责:
- profile/request 校验
- use case 编排
- driver error → app error 的归一化
- 结构化结果对象
- export 结果写盘
- `apps/cli``apps/tui` 都不应再直接编排数据库调用。
### 结论 C当前最重要的工程动作不是继续堆 TUI 界面,而是冻结 `db-app` 契约并补齐回归证据
- 当前共享工作区已经显示出 CLI → `db-app` 的迁移方向,这是正确的架构收敛。
-`CMP-31` 在 Paperclip 里仍未正式关闭,也还没有在本 heartbeat 中补到本地 `cargo` 级验证证据。
- 因此 `CMP-31` 仍应被视为 TUI 集成前的 P0 收尾项:冻结结构化契约、补测试、让 QA 能据此建立回归基线。
## 3. 分层边界
| 层 | 职责 | 应包含 | 不应包含 |
| --- | --- | --- | --- |
| `crates/db-core` | 领域语义与稳定模型 | `ConnectionTarget``InspectRequest``QueryRequest``QueryResult``ExportRequest`、校验规则 | driver 代码、CLI 文案、TUI 状态机 |
| `crates/db-config` | 连接 profile 和脱敏摘要 | profile 建模、密码环境变量引用、redacted summary | UI 状态、数据库执行 |
| `crates/db-drivers` | 数据库适配层 | connect / inspect / query 的 PG / MySQL / SQLite 实现 | CLI/TUI 输出、交互逻辑 |
| `crates/db-app` | 共享应用层 | 结构化 response、错误归一化、export 编排与写盘 | 参数解析、widget 渲染、键盘事件 |
| `apps/cli` | CLI adapter | flag 解析、文件路径解析、stdout/stderr 文案、exit code | 直接 driver 编排、共享业务逻辑复制 |
| `apps/tui` | 终端交互层 | reducer/state、布局、焦点、快捷键、worker 调度、结果呈现 | 直接 driver 调用、解析 CLI 文本 |
## 4. 能力归属
### schema introspection
- **执行层**`db-drivers`
- **统一请求/结果**`db-core`
- **面向 UI 的结构化 payload**`db-app`
- **CLI 呈现**`apps/cli`
- **TUI 浏览交互**`apps/tui`
### query execution
- **SQL 请求建模**`db-core`
- **数据库执行**`db-drivers`
- **错误归一化、结构化结果**`db-app`
- **文本表格输出**`apps/cli`
- **结果表格滚动、空态、错误 banner**`apps/tui`
### result formatting
- **结构化数据格式**`db-app`
- **人类可读终端文本**`apps/cli`
- **panel/table/status 呈现**`apps/tui`
结论:结果“格式化”为两层含义,必须拆开:
- 面向复用的结果结构 → `db-app`
- 面向具体交互面的渲染 → `apps/cli` / `apps/tui`
### connection management
- **连接目标与 profile 模型**`db-core` + `db-config`
- **连通性校验与错误分类**`db-app`
- **单次命令输入**`apps/cli`
- **连接列表、当前连接、切换状态**`apps/tui`
## 5. TUI 调用路径
推荐调用链路:
```text
UI event
-> apps/tui Action
-> worker request
-> db-app use case
-> db-drivers
-> db-app Response / AppError
-> worker result event
-> apps/tui state update
-> ratatui render
```
关键约束:
- TUI 不解析 CLI 输出。
- TUI 不直接依赖 `db_drivers::DriverRegistry`
- TUI 主循环不直接执行阻塞数据库 I/O。
- 第一阶段使用“UI 主线程 + worker 线程 + channel”即可不需要为了 TUI 先服务化。
## 6. 当前审计发现的关键缺口
### P0共享层已进入主路径但还没有完成正式收口
- `crates/db-app` 已经能返回结构化 `ConnectResponse``InspectResponse``QueryResponse``ExportResponse`
- 当前共享工作区里的 `apps/cli` 已通过 `db-app` 调用核心用例,这说明架构方向已经正确。
- 但对应的工程 issue `CMP-31` 仍在进行中,因此当前仍需要以 issue 收口、回归测试和 QA 可验证文档来固定这条共享路径。
### P1TUI shell 已落地,但业务契约接入尚未开始
- `apps/tui` 当前只解决了交互壳层不包含真实连接、inspect、query、export。
- 这符合 `CMP-27` 范围,但也意味着后续 issue 必须严格走共享契约接入,不能从 shell 直接摸到 driver。
### P1本 heartbeat 不能复跑本地 Rust 验证
- 当前 CTO heartbeat 环境缺少 `cargo`,因此本轮无法直接复跑 `cargo build` / `cargo test` / `cargo run`
- 仓库中仍保留 `.github/workflows/release-smoke.yml``dist/` 产物,说明构建与发布链路定义仍在,但本轮只能做静态审计,不能补新执行证据。
## 7. 哪些契约必须先稳定
在继续推进 `CMP-28` / `CMP-29` / `CMP-30` 前,必须冻结以下共享契约:
1. `db-app``AppErrorKind` 与错误消息分层
2. `InspectResponse` / `InspectPayload` 的结构和空态语义
3. `QueryResponse` 的结果集结构、空结果集语义、rows affected 语义
4. `ExportResponse` 的成功 / 覆盖 / 路径不存在等失败语义
5. CLI 迁移到 `db-app` 后的回归测试,证明共享层不是只给 TUI 准备的旁路代码
## 8. 首批工程任务拆分与 owner 边界
### Backend
- `[CMP-31](/CMP/issues/CMP-31)`:正式收口 `db-app` 共享契约
- 固定 `AppErrorKind` 和结构化响应契约
- 复核当前 CLI → `db-app` 迁移结果
- 增加 CLI + app 层回归测试
- 为 TUI 接入提供稳定的契约说明
### Frontend / TUI
- `[CMP-27](/CMP/issues/CMP-27)`:已交付 shell作为后续接入基座不再继续承载业务逻辑
- `[CMP-28](/CMP/issues/CMP-28)`:连接视图仅消费 `ConnectionSummary` / connect 状态,不接 driver
- `[CMP-29](/CMP/issues/CMP-29)`schema browser 仅消费 `InspectResponse`
- `[CMP-30](/CMP/issues/CMP-30)`query editor / results / export 仅消费 `QueryResponse` / `ExportResponse`
### QA
- `[CMP-32](/CMP/issues/CMP-32)`:建立与共享契约对齐的 TUI 验收矩阵
- 区分“core 契约错误”与“TUI 交互错误”
- 覆盖空结果、错误态、resize、键盘路径
-`CMP-31` 合并后补一轮 CLI/TUI 契约一致性回归
## 9. 推荐执行顺序
1. `CMP-31` 先正式收口共享应用层契约
2. `CMP-32` 同步固化契约导向的验收矩阵
3. `CMP-28` 接连接视图
4. `CMP-29` 接 schema browser
5. `CMP-30` 最后接 query / results / export
说明:
- `CMP-27` 已够用,不应继续膨胀为“顺手把业务也做了”。
- `CMP-28` / `CMP-29` / `CMP-30` 可以在 shell 基座上并行设计,但实际合入顺序仍应受 `CMP-31` 约束。
## 10. 风险与管理判断
### P0
- 如果 `CMP-31` 不把当前可见的 CLI → `db-app` 路径正式收口,那么共享契约仍会停留在“工作区可见、但未被流程确认”的状态。
### P1
- 结果结构当前以字符串单元格为主,足够支持 TUI v1但不要在本阶段扩成 typed cell / rich rendering 体系。
### P1
- `CMP-19` MySQL 中文输出问题未最终关闭前TUI 结果区应避免过早做“输出显示质量已稳定”的假设。
### P2
- 当前不是招聘问题。真实瓶颈是共享契约收敛与 issue 节奏,而不是缺少更多实现人手。
## 11. CTO 结论
- TUI 可以继续推进,但必须建立在 `db-app` 成为唯一共享应用层的前提上。
- 当前前后端边界已经足够明确:
- Backend 负责共享语义、错误模型、结构化结果
- Frontend 负责状态机、交互、渲染
- QA 负责契约一致性与终端交互回归
- 当前不建议新增招聘;先用 `CMP-31``CMP-32` 的收敛结果验证真实吞吐与协作瓶颈。