- server/db: 拆 4929 行 db.rs 单体为 db/ 目录,migrations.rs 引入 PRAGMA user_version
版本化迁移运行器(M1~M13)
- 任务引擎 Phase 6/7b/7c 改名收敛:EngineStageConfig→PhaseConfig、StagePolicy→ResumePolicy、
Converged→Completed、删除 task_type 列、success_method 拆 tlusty_/synspec_ 双列、
新增 tlusty_status/synspec_status 半失败阶段守卫
- 科学正确性加固:conv_check 任意行 NaN/Inf/溢出判无效(0 行容忍)、新增 spec_is_valid
校验 SYNSPEC 脏谱、itek_history 逐次迭代全量保真、fmt_abn powf 溢出饱和
- 用户配置真正接通:tlusty_chain/tlusty_input 由死字段经 调度器→TaskSpec→executor→runner
透传生效;config 加载期 validate + deny_unknown_fields + 解析失败记 warn
- 调度修复:H1 活锁(pending_strategies 跳过已失败策略)、种子查找错误不再静默降级冷启动
- dashboard: 阶段配置面板 tlusty_stage/synspec_stage、"已完成"标签、迭代诊断展示
- docs: 新增 database_refactor_design.md,同步 database/api/PIPELINE/workflow_detail
14 KiB
DCTS 数据库设计 (Database Schema)
DCTS 采用轻量级、零配置、高并发安全的 SQLite 双数据库架构:主状态库
dcts.db存储网格结构与历史记录;队列库dcts_queue.db由mq驱动管理原子任务状态机。
1. 数据库分库架构
erDiagram
WORKFLOWS ||--o{ GRID_POINTS : contains
GRID_POINTS ||--o{ TASKS : logs
WORKFLOWS ||--o{ WORKFLOW_PROGRESS_SNAPSHOTS : samples
NODES ||--o{ TASK_QUEUE : executes
NODES ||--o| NODE_CREDENTIALS : authenticates
SEEDS }o--o{ GRID_POINTS : hot-starts
subgraph PrimaryDB ["主数据库 (dcts.db)"]
WORKFLOWS {
string name PK
string description
text config_yaml
string status
datetime created_at
datetime updated_at
}
GRID_POINTS {
integer id PK
string name
string workflow_name FK
double teff
double logg
double loghe
double logc
double logn
double logo
double cno_sum
integer wave
string status
integer attempt_count
string tlusty_success_method
string synspec_success_method
double last_elapsed_sec
}
TASKS {
string task_id PK
string point_name
string node_id
string seed_point_name
string status
double max_relc
boolean atmosphere_has_nan
integer retry_count
datetime created_at
datetime started_at
datetime completed_at
string error_message
string workflow_name
boolean tlusty_enabled
string tlusty_policy
text tlusty_strategies
boolean synspec_enabled
string synspec_policy
text synspec_strategies
string atmosphere_ref
double elapsed_sec
string failed_stage
text summary_json
}
NODES {
string node_id PK
integer max_slots
integer active_slots
string status
double cpu_usage
double memory_usage
datetime last_heartbeat
string registration_secret
integer admin_max_slots
}
NODE_CREDENTIALS {
string node_id PK
string token_hash
datetime issued_at
string raw_token_pending
}
SEEDS {
integer id PK
string point_name UK
double teff
double logg
double loghe
double logc
double logn
double logo
string file_path
boolean is_clean
}
WORKFLOW_PROGRESS_SNAPSHOTS {
integer id PK
string workflow_name
datetime ts
integer total
integer pending
integer queued
integer running
integer completed
integer failed
}
end
subgraph QueueDB ["队列库 (dcts_queue.db / mq)"]
TASK_QUEUE {
string task_id PK
string payload
string status
datetime created_at
datetime claimed_at
string workflow_name
string claimed_by_node_id
integer wave
}
end
2. 表结构定义 (Schema Specification)
2.1 workflows (工作流配置表)
存储用户定义的计算网格配置及整体状态。
name(TEXT PRIMARY KEY):工作流唯一标志(如sdB_cno)。description(TEXT):描述信息。config_yaml(TEXT NOT NULL):完整的参数网格定义与物理配置 YAML 内容。status(TEXT NOT NULL DEFAULT 'idle'):idle(就绪)→initializing(原子抢占加载中)→running(运行中)/ 回退idle;running→paused(暂停)/completed(全部网格点收敛)。created_at/updated_at(DATETIME NOT NULL):创建 / 最后更新时间。
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 NOT NULL DEFAULT 0):按 cno_sum 分组的批次波次(调度优先级用)。status(VARCHAR(32)):pending/queued/running/completed/failed(7c 由converged改名,M9 迁移)。attempt_count(INTEGER):失败重试计数(仅观测用)。tlusty_success_method(VARCHAR(32)):大气收敛归因(P9 拆分)——TLUSTY 阶段以何策略收敛 (cold_run冷启动成功 /seed_step种子步进成功 / 策略名);TLUSTY 禁用(synspec-only)为 NULL。 Phase 6 起由tlusty_strategies[0]派生。整体归因由消费方派生(tlusty ?? synspec)。synspec_success_method(VARCHAR(32)):光谱收敛归因(Phase 5a)——synspec 阶段以何策略收敛 (如standard);TLUSTY-only 成功为 NULL。解锁"光谱以 standard 等策略收敛了多少点"的统计与过滤。last_elapsed_sec(REAL):最近一次尝试的墙钟耗时(详情页 ETA 估算用,兼容旧数据回退)。
多工作流分区(per-workflow partitioning):
grid_points与task_queue均按workflow_name隔离。 调度、状态更新、stale 重投、stop_workflow重置都限定在单个工作流内,互不影响。 历史旧库(无workflow_name列)在启动时自动迁移:表重建为复合唯一结构,旧行workflow_name标记为__legacy__,不干扰新工作流查询。
2.3 tasks (任务尝试记录表)
每次派发/尝试生成一行,记录任务的阶段配置快照与执行结果(详情页/归因/回退弹栈的数据源)。
task_id(VARCHAR(128) PRIMARY KEY):任务 ID(UUID)。point_name(TEXT NOT NULL):网格点权威名(源精度,非 params 重推)。node_id(TEXT):执行节点 ID。seed_point_name(TEXT):种子步进时注入的近邻种子点(GET /api/seed/<name>下载依据)。 双义:SYNSPEC-only(TLUSTY 关闭)时恒为 NULL(大气来源见atmosphere_ref)。status(VARCHAR(32)):pending/claimed/running/completed/failed/timeout。max_relc(REAL):最终最大相对变化(收敛判据量)。atmosphere_has_nan(BOOLEAN):最终大气是否含 >10% NaN 行(无效化标记)。retry_count(INTEGER):重试计数。created_at/started_at/completed_at(DATETIME):创建 / 开始 / 完成时间。error_message(TEXT):失败原因(含 synspec 错误/超时等)。workflow_name(TEXT):所属工作流(多工作流分区键)。- 阶段独立配置快照(派发时落库):
tlusty_enabled(BOOLEAN)、tlusty_policy(TEXT)、tlusty_strategies(JSON)、synspec_enabled(BOOLEAN)、synspec_policy(TEXT)、synspec_strategies(JSON)、atmosphere_ref(TEXT,显式大气来源点)。 回退时弹*_strategies链首(见task_engine_decoupling_design.md §4.2),policy/策略链取派发时快照。 elapsed_sec(REAL):任务墙钟耗时(详情页 ETA 估算优先用此值)。failed_stage(TEXT):失败阶段归因("tlusty"/"synspec";旧节点/旧行 NULL → 服务端兜底按 TLUSTY 归因)。summary_json(TEXT):完整ModelSummaryJSON(含synspec_rc/synspec_error/synspec_sec与各子步骤摘要); 错误路径为{"error": ...}。全量保真(Phase 5b 起):逐次 itek 迭代诊断 (itek_history: [{iter, max_relc, n_depths}])随 summary_json 落库,与 conv.json 同源。
2.4 nodes (计算节点心跳与状态表)
node_id(TEXT PRIMARY KEY):节点唯一标识(未指定DCTS_NODE_ID时自动生成node-<uuid>)。max_slots(INTEGER NOT NULL):节点声明的最大并发计算槽位数(即DCTS_MAX_SLOTS,领用上限)。active_slots(INTEGER NOT NULL DEFAULT 0):当前正在执行的任务数,随 claim 自增、report 完结自减。status(VARCHAR(32) NOT NULL DEFAULT 'online'):pending_approval(注册待审批)/online(在线)/offline(心跳超时离线)/disabled(管理员手动停用,保持心跳但不再分发任务)/rejected。cpu_usage/memory_usage(REAL NOT NULL DEFAULT 0.0):心跳上报的 CPU/内存使用率(仅观测展示用,不参与任务分发决策)。last_heartbeat(DATETIME NOT NULL):最后一次心跳上报时间,后台线程据此判定online → offline。registration_secret(TEXT):节点注册时下发的一次性凭据,用于/node/check_status取走专属 token 的二次鉴权。admin_max_slots(INTEGER,可空):管理员强制并发槽位配额(NULL= 无限制,沿用物理max_slots),经心跳响应下发给节点动态生效。
2.5 node_credentials (节点 L2 鉴权凭据表)
node_id(TEXT PRIMARY KEY):关联nodes.node_id。token_hash(TEXT NOT NULL):节点专属 token 的 SHA-256 哈希(不存明文)。issued_at(DATETIME NOT NULL):颁发时间。raw_token_pending(TEXT):暂存待确认的明文 token(颁发流程过渡用,确认后清除)。
token 失效靠重发覆盖
token_hash(旧 hash 不存在 → 鉴权失败),无独立吊销标记; 历史revoked死列已由迁移 M4 清除(Phase 4)。
2.6 seeds (种子缓存池表)
全局共享的已收敛大气 .7 索引(跨工作流复用,种子步进热启动数据源)。
id(INTEGER PRIMARY KEY AUTOINCREMENT)。point_name(TEXT UNIQUE NOT NULL):种子点权威名(源精度,与磁盘文件名一致)。teff,logg,loghe,logc,logn,logo(REAL NOT NULL):6 维物理参数(种子匹配距离计算用)。file_path(TEXT NOT NULL):.7大气文件在seeds_dir的路径。is_clean(BOOLEAN NOT NULL DEFAULT 1):大气是否干净(无 NaN)——仅干净种子可被匹配(reload_seed_cache只加载is_clean=1)。
运行期维护内存
seed_cache+seed_index(exact_family 桶索引),find_best_seed_from_db先查桶索引(O(1)~O(小)),未命中退化为全量 global 扫描(见seed_finder.rs/design.md §3)。
2.7 workflow_progress_snapshots (工作流进度时间序列表)
后台定期(每分钟)为每个 running 工作流记录进度计数,供详情页进度曲线与 ETA 估算。
id(INTEGER PRIMARY KEY AUTOINCREMENT)。workflow_name(TEXT NOT NULL)。ts(DATETIME NOT NULL DEFAULT (datetime('now'))):采样时间。total/pending/queued/running/completed/failed(7c 由converged改名,M9 迁移) (INTEGER NOT NULL):该时刻各状态计数。
2.8 task_queue (分布式任务队列表 - mq)
驱动分布式抢占与超时重试的核心表,使用 SQLite WAL 模式确保高吞吐并发安全(详见 sqlite_queue.rs)。
task_id(VARCHAR(128) PRIMARY KEY):任务 ID(UUID)。payload(TEXT NOT NULL):序列化的TaskSpec(含 point_name / params / seed_point_name / workflow_name / tlusty_config / synspec_config 等; Phase 6 起无task_type字段,执行链由tlusty_config.strategies[0]派生)。status(TEXT NOT NULL):pending(就绪待领用)/claimed(已被某 node 领用,计算中)。created_at(DATETIME NOT NULL):推入队列时间(同wave内 FIFO 排序键)。claimed_at(DATETIME):被领用的时间戳(requeue_stale_tasks据此判定超时回投)。workflow_name(TEXT):所属工作流(多工作流分区键)。claimed_by_node_id(TEXT):领用方节点 ID(claim 时写入,report 阶段据此校验归属,防跨节点伪造)。wave(INTEGER NOT NULL DEFAULT 0):难度波次(pop_task出队第一排序键,低wave优先)。
任务完成后由
remove_task直接从本表删除(不保留completed/failed终态行),历史记录落在主库tasks表。超时的claimed行由requeue_stale_tasks改回pending重投。
3. 并发与事务安全设计
- WAL (Write-Ahead Logging) 模式:SQLite 连接自动启用
PRAGMA journal_mode=WAL;和PRAGMA busy_timeout=15000;,解决多线程/多进程读写锁竞争。 - 连接池机制:借助
r2d2+r2d2_sqlite维护异步连接池,防止高并发下数据库句柄冲突。 - 原子 Claim 事务:任务抢占在单个
IMMEDIATE事务内完成——先SELECT ... WHERE status='pending' ORDER BY wave ASC, created_at ASC LIMIT 1取队首,再UPDATE SET status='claimed', claimed_by_node_id=?,提交后返回。事务保证同一任务不会被两个 node 同时领用;遇到SQLITE_BUSY/LOCKED最多退避重试 5 次(详见pop_task)。 - 凭据零明文存储:
node_credentials.token_hash只存 SHA-256 哈希;节点注册的一次性registration_secret也仅在审批前短期有效,避免数据库泄漏直接泄露有效 token。