- server: 实现按 workflow_name 的多工作流数据隔离与旧数据库平滑迁移机制 - server: 新增 API Key 认证(auth)、限流中间件(rate_limit)与运维备份接口(admin) - server: 统一 AppError 错误处理体系,重构调度器 scheduler 支持工作流级重置与抢占 - node: 节点 ID 缺失时自动生成随机 UUID,原生支持 `docker compose --scale node=N` 动态扩容 - dashboard: 前端模块化重构(state/api/components),升级 CSS 变量设计系统与 Toast 通知 - docker/docs: 更新 /healthz 健康检查、部署脚本 IP 配置及数据库设计文档
119 lines
5.1 KiB
Markdown
119 lines
5.1 KiB
Markdown
# DCTS 数据库设计 (Database Schema)
|
||
|
||
> DCTS 采用轻量级、零配置、高并发安全的 **SQLite** 双数据库架构:主状态库 `dcts.db` 存储网格结构与历史记录;队列库 `dcts_queue.db` 由 `mq` 驱动管理原子任务状态机。
|
||
|
||
---
|
||
|
||
## 1. 数据库分库架构
|
||
|
||
```mermaid
|
||
erDiagram
|
||
WORKFLOWS ||--o{ GRID_POINTS : contains
|
||
GRID_POINTS ||--o{ TASK_HISTORY : logs
|
||
NODES ||--o{ TASK_QUEUE : executes
|
||
|
||
subgraph PrimaryDB ["主数据库 (dcts.db)"]
|
||
WORKFLOWS {
|
||
string name PK
|
||
string description
|
||
text yaml_config
|
||
string status
|
||
datetime created_at
|
||
}
|
||
GRID_POINTS {
|
||
string point_id PK
|
||
string workflow_name FK
|
||
double teff
|
||
double logg
|
||
double he_abund
|
||
double c_abund
|
||
double n_abund
|
||
double o_abund
|
||
string status
|
||
datetime updated_at
|
||
}
|
||
TASK_HISTORY {
|
||
string id PK
|
||
string point_id FK
|
||
string node_id
|
||
boolean success
|
||
text conv_info_json
|
||
datetime duration_sec
|
||
}
|
||
NODES {
|
||
string node_id PK
|
||
string hostname
|
||
integer cpu_cores
|
||
string status
|
||
datetime last_heartbeat
|
||
}
|
||
end
|
||
|
||
subgraph QueueDB ["队列库 (dcts_queue.db / mq)"]
|
||
TASK_QUEUE {
|
||
string task_id PK
|
||
string workflow_name
|
||
string payload_json
|
||
string status
|
||
string assigned_node
|
||
integer retry_count
|
||
datetime claimed_at
|
||
}
|
||
end
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 表结构定义 (Schema Specification)
|
||
|
||
### 2.1 `workflows` (工作流配置表)
|
||
存储用户定义的计算网格配置及整体状态。
|
||
- `name` (`VARCHAR(64) PRIMARY KEY`):工作流唯一标志(如 `sdB_cno`)。
|
||
- `description` (`TEXT`):描述信息。
|
||
- `yaml_config` (`TEXT`):完整的参数网格定义与物理配置 YAML 内容。
|
||
- `status` (`VARCHAR(32)`):状态:`idle` / `running` / `paused` / `completed`。
|
||
- `created_at` (`DATETIME DEFAULT CURRENT_TIMESTAMP`):创建时间。
|
||
|
||
### 2.2 `grid_points` (网格点物理参数表)
|
||
存储多维笛卡尔积展开后的每一个独立参数点。
|
||
- `id` (`INTEGER PRIMARY KEY AUTOINCREMENT`):自增主键。
|
||
- `name` (`TEXT NOT NULL`):点物理唯一名(由 6 维参数生成,如 `t35000_g5.5_he-1_c-2_n-2_o-2`)。
|
||
- `workflow_name` (`TEXT NOT NULL`):所属工作流。**多工作流分区键**——同一物理点可属于多个工作流,
|
||
与 `name` 共同构成复合唯一约束 `UNIQUE(workflow_name, name)`。
|
||
- `teff`, `logg`, `loghe`, `logc`, `logn`, `logo` (`REAL NOT NULL`):6 维物理参数。
|
||
- `cno_sum` (`REAL NOT NULL`):CNO 丰度之和(调度排序用)。
|
||
- `wave` (`INTEGER`):按 cno_sum 分组的批次波次(调度优先级用)。
|
||
- `status` (`VARCHAR(32)`):`pending` / `queued` / `running` / `converged` / `failed`。
|
||
- `attempt_count` (`INTEGER`):失败重试计数(仅观测用)。
|
||
- `success_method` (`VARCHAR(32)`):收敛时的成功手段 (`cold_run` 冷启动成功 / `seed_step` 种子步进成功)。
|
||
|
||
> **多工作流分区(per-workflow partitioning)**:`grid_points` 与 `task_queue` 均按 `workflow_name` 隔离。
|
||
> 调度、状态更新、stale 重投、`stop_workflow` 重置都限定在单个工作流内,互不影响。
|
||
> 历史旧库(无 `workflow_name` 列)在启动时自动迁移:表重建为复合唯一结构,旧行 `workflow_name`
|
||
> 标记为 `__legacy__`,不干扰新工作流查询。
|
||
|
||
### 2.3 `nodes` (计算节点心跳与状态表)
|
||
- `node_id` (`VARCHAR(64) PRIMARY KEY`):节点唯一标识。
|
||
- `hostname` (`VARCHAR(128)`):节点主机名或 IP。
|
||
- `cpu_cores` (`INTEGER`):节点 CPU 核心数。
|
||
- `status` (`VARCHAR(32)`):`online` / `offline` / `busy`。
|
||
- `last_heartbeat` (`DATETIME`):最后一次心跳上报时间。
|
||
|
||
### 2.4 `task_queue` (分布式任务队列表 - `mq`)
|
||
驱动分布式抢占与超时重试的核心表,使用 SQLite `WAL` 模式确保高吞吐并发安全。
|
||
- `task_id` (`VARCHAR(128) PRIMARY KEY`):任务 ID。
|
||
- `workflow_name` (`VARCHAR(64)`):工作流。
|
||
- `payload_json` (`TEXT`):任务所含参数 payload。
|
||
- `status` (`VARCHAR(32)`):`pending`(就绪) / `running`(计算中) / `completed`(完成) / `failed`(失败)。
|
||
- `assigned_node` (`VARCHAR(64)`):当前抢占该任务的节点 ID。
|
||
- `retry_count` (`INTEGER DEFAULT 0`):失败或超时重发次数。
|
||
- `claimed_at` (`DATETIME`):抢占时间戳(用于超时释放判定)。
|
||
|
||
---
|
||
|
||
## 3. 并发与事务安全设计
|
||
|
||
1. **WAL (Write-Ahead Logging) 模式**:SQLite 连接自动启用 `PRAGMA journal_mode=WAL;` 和 `PRAGMA busy_timeout=5000;`,解决多线程/多进程读写锁竞争。
|
||
2. **连接池机制**:借助 `r2d2` + `r2d2_sqlite` 维护异步连接池,防止高并发下数据库句柄冲突。
|
||
3. **原子 Claim 事务**:任务抢占在单个 SQLite 事务中完成(`UPDATE task_queue SET status='running', assigned_node=? WHERE status='pending' ... LIMIT 1`),保证绝对防重领。
|