feat(all): 源精度命名体系、工作流可观测台、节点停用管理与白名单归档

核心变更:

  1. GridAxisValue 源精度命名
     - 新增 GridAxisValue 类型,携带 f64 数值 + YAML 源书写文本(Deref 透明兼容算术)
     - config.rs 绕过 serde_yaml 归一化,逐 token 捕获轴值原文(logg: 5.0 → g5.0)
     - runner/executor/scheduler 全链路改用 DB TEXT 列权威 point_name,
       修复 REAL 列回读丢精度导致的 model_name 错配

  2. 工作流执行可观测台
     - 新增 stats/progress/points 三组 API(进度时间序列、经验速率 ETA、
       停滞预警、逐点明细分页、收敛性热力图数据)
     - 新增 workflow_progress_snapshots 表 + tasks/grid_points 耗时列
     - runner 携带 last_iter/worst_depth/n_depths 进 conv.json
     - 前端新增 hash 路由、工作流详情页(概览/网格点/收敛分析三 Tab)、YAML 编辑器

  3. 节点停用/启用管理
     - 新增 disabled 状态 + disable/enable API;停用节点保持心跳但停止分发,
       worker 空闲待命而非退出;移除 revoke API,token 失效统一走重发覆盖;
       移除 host_name 字段

  4. 白名单结果归档
     - 新增 result_filter 模块,只归档有语义产物,丢弃 Tlusty 中间单元(~2MB/模型)
     - executor 原子写入归档 + 200 点 LRU 上限

  5. 历史数据导入
     - sync_seeds 重写为 import_results:经 /admin/import_seed 标记 converged +
       按新版命名迁移产物树

  6. 部署与目录重规划
     - data/results→seeds、data/archive→result + migrate_data_dirs.sh
     - deploy.sh 增强(SSH 复用、Profile、远程 env);Dockerfile 瘦身

  7. 文档同步更新 api/database/architecture/deployment
This commit is contained in:
fmq
2026-07-31 01:34:05 +08:00
parent b91f1e4fa5
commit 1bfa240cb0
73 changed files with 12332 additions and 1608 deletions
+52 -25
View File
@@ -55,11 +55,7 @@ async fn main() -> Result<()> {
let db = Database::new(&server_cfg.db_path).await?;
let queue = Arc::new(SqliteTaskQueue::new(&server_cfg.queue_db_path).await?);
let scheduler = Arc::new(GridScheduler::new(
db.clone(),
queue.clone(),
server_cfg.results_dir.clone(),
));
let scheduler = Arc::new(GridScheduler::new(db.clone(), queue.clone()));
// Auto-register sdB_cno.yaml if exists and not yet in DB
let default_wf_path = Path::new(&server_cfg.grid_config);
@@ -81,18 +77,10 @@ async fn main() -> Result<()> {
}
}
// 弱口令凭据安全警告检测
let is_weak_token = |t: Option<&str>| -> bool {
match t {
Some(s) => {
s.len() < 12 || s == "fmqi123" || s == "admin" || s == "123456" || s == "secret"
}
None => false,
}
};
if is_weak_token(server_cfg.auth_token.as_deref())
|| is_weak_token(server_cfg.admin_token.as_deref())
{
// 弱口令凭据安全警告检测:仅按强度阈值判断(短于 16 字节视为弱口令)。
// 推荐用 `openssl rand -hex 32`64 字符)生成。
let is_weak_token = |t: Option<&str>| -> bool { t.map(|s| s.len() < 16).unwrap_or(false) };
if is_weak_token(server_cfg.admin_token.as_deref()) {
tracing::warn!("⚠️ 检测到系统当前正在使用弱口令凭据或默认 Token!建议生产环境在 .env 中配置使用 openssl rand -hex 32 生成的高强度 Token");
}
@@ -102,9 +90,8 @@ async fn main() -> Result<()> {
db,
queue: queue.clone(),
scheduler: scheduler.clone(),
results_dir: server_cfg.results_dir.clone(),
seeds_dir: server_cfg.seeds_dir.clone(),
rate_limiter,
auth_token: server_cfg.auth_token.clone(),
admin_token: server_cfg.admin_token.clone(),
auth_disabled: server_cfg.auth_disabled,
admin_sessions: std::sync::Arc::new(tokio::sync::RwLock::new(
@@ -188,6 +175,23 @@ async fn main() -> Result<()> {
has_error = true;
}
// P3 进度快照:对每个运行中工作流记录计数(record_progress_snapshot
// 内部去重——计数无变化不落库);顺带清理超过 7 天的旧快照。
// 观测性写入失败不回退调度退避(不置 has_error)。
match bg_db_clone.get_running_workflow_names().await {
Ok(names) => {
for wf in names {
if let Err(e) = bg_db_clone.record_progress_snapshot(&wf).await {
tracing::warn!("记录工作流 {} 进度快照失败: {}", wf, e);
}
}
}
Err(e) => tracing::warn!("获取运行中工作流列表失败: {}", e),
}
if let Err(e) = bg_db_clone.purge_progress_snapshots(7).await {
tracing::warn!("清理过期进度快照失败: {}", e);
}
has_error
});
@@ -234,6 +238,8 @@ async fn main() -> Result<()> {
let report_router = Router::new()
.route("/task/report", post(api::task::report_task))
// 历史种子导入同样上传 .7 大气文件,并入宽松 body limit / 并发限流组。
.route("/admin/import_seed", post(api::task::import_seed))
.layer(DefaultBodyLimit::max(REPORT_BODY_LIMIT))
.layer(tower::ServiceBuilder::new().concurrency_limit(REPORT_MAX_CONCURRENCY));
@@ -284,7 +290,24 @@ async fn main() -> Result<()> {
post(api::workflow::start_workflow),
)
.route("/workflows/:name/stop", post(api::workflow::stop_workflow))
// Admin Management API(节点凭据查看/审批/吊销/重发,均要求 Admin 角色)
// 工作流执行观测 API(进度统计 / 逐点明细 / 单点诊断,均要求 Admin 角色)
.route(
"/workflows/:name/stats",
get(api::workflow::get_workflow_stats),
)
.route(
"/workflows/:name/progress",
get(api::workflow::get_workflow_progress),
)
.route(
"/workflows/:name/points",
get(api::workflow::get_workflow_points),
)
.route(
"/workflows/:name/points/:point",
get(api::workflow::get_workflow_point_detail),
)
// Admin Management API(节点凭据查看/审批/重发/停用/启用,均要求 Admin 角色)
.route("/admin/nodes", get(api::admin::list_nodes))
.route(
"/admin/nodes/:node_id/approve",
@@ -294,14 +317,18 @@ async fn main() -> Result<()> {
"/admin/nodes/:node_id/reject",
post(api::admin::reject_node),
)
.route(
"/admin/nodes/:node_id/revoke",
post(api::admin::revoke_node),
)
.route(
"/admin/nodes/:node_id/reissue",
post(api::admin::reissue_node),
)
.route(
"/admin/nodes/:node_id/disable",
post(api::admin::disable_node),
)
.route(
"/admin/nodes/:node_id/enable",
post(api::admin::enable_node),
)
// 合并大体积上报路由(继承各自的 body limit)
.merge(report_router)
.layer(DefaultBodyLimit::max(DEFAULT_BODY_LIMIT));
@@ -320,7 +347,7 @@ async fn main() -> Result<()> {
api_router.layer(auth_layer).layer(rate_limit_layer)
} else {
tracing::warn!(
"⚠️ 警告:未配置 DCTS_ADMIN_TOKEN / DCTS_ENROLLMENT_TOKEN(且未启用 DCTS_AUTH_DISABLE),\
"⚠️ 警告:未配置 DCTS_ADMIN_TOKEN(且未启用 DCTS_AUTH_DISABLE),\
服务端运行在【无鉴权模式】!公网部署务必配置凭据。"
);
api_router