feat(m203): CLI 三条下载命令改吃 download.* 设置(并发/重试/gh-proxy)

`ull install` / `ull java` / `ull pack` 此前各自 `DownloadEngine::new(EngineConfig::default(), …)`:
用户在设置里配的 `download.concurrency` / `retry_limit` / `gh_proxy` 一概不生效;M193 把出厂并发
从 64 改成 8 之后,它们还静默跟着降了。现在三处都经 `crates/cli/src/download.rs::engine(ctx)`:

- core:`shared/tuned.rs` 新增 `engine_with_tuning(cache_root, tune)` = `set_tuning` + `engine_for`,
  由 `shared.rs` 重导出;`engine_for` 的签名与行为一字未改(presenter 的两步语义原样保留)。
  放子模块是为了不动 `engine.rs`(那是 400 行零余量),`shared.rs` 仍 398 行。
- CLI:`download::tuning(ctx)` 用 `SettingStore::load(ctx.launcher_config(), launcher_schema())` 读
  三个键(与 `ull config set` 同一份文件),默认值/夹取/回落在 `DownloadTuning::from_settings`;
  键缺失或坏值静默回落出厂值,`engine()` 没有错误通道,安装不会因此中断。
- 顺带:`ull update` 复用 `install::build_engine`,也随之吃到设置。
- 测试:`crates/cli/src/download/tests.rs` 三条命令各一条(读 `config().max_concurrency` 与
  `concurrency_probe()` 的真实值)+ 一条「缺失/越界/负数/类型不对 ⇒ 静默回落出厂值」;
  `shared/tuned.rs` 两条守住「灌调优与取引擎是一步」。变异实测:pack 换回裸 `EngineConfig::default()`
  ⇒ 只有 pack 那条红(left 8 / right 2)。
This commit is contained in:
AskaEth committed 2026-11-09 10:07:41 +08:00
1 parent c97630d59e
commit b31ca636d1
9 files changed
+368 -81

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
//! CLI 侧的下载引擎:把 CLI 自己的 `launcher.json` 接到 core 的下载调优上(M203)。
//!
//! 三条下载命令(`install` / `java` / `pack`)此前各自 `DownloadEngine::new(EngineConfig::default(), …)`:
//! 用户在设置里配的 `download.concurrency` / `download.retry_limit` / `download.gh_proxy` 一概不生效。
//! M193 把出厂并发从 64 改成 8 之后,它们还**静默**跟着降了——「设置项说假话」的同期病灶
//! (`docs/download-settings.md` §3.1 记着这三条 ❌)。
//!
//! 现在三处一律经 [`engine`] 取引擎(进程内共享,见 `core::download::shared`):
//!
//! ```text
//! <数据根>/config/launcher.json(与 `ull config set` 同一份) → setting store → DownloadTuning
//! (默认值/夹取/回落在 core)
//! → shared::engine_with_tuning(<cache 根>, tuning) → 引擎的 Semaphore / attempts_for()
//! ```
//!
//! **回落是静默的**:`SettingStore::load` 永不失败(坏值只进 `problems()`);类型不对 → `None`,
//! 越界 → `DownloadTuning::from_settings` 的区间过滤。两种情况都落成出厂值,**不报错、不中断安装**。
use std::sync::Arc;
use unlucky_core::download::config::{
DownloadTuning, KEY_CONCURRENCY, KEY_GH_PROXY, KEY_RETRY_LIMIT,
};
use unlucky_core::download::{shared, DownloadEngine};
use unlucky_core::setting::keys::launcher_schema;
use unlucky_core::setting::store::SettingStore;
use crate::context::Ctx;
/// 从 CLI 自己的 setting store 读下载调优(`launcher.json` 的三个 `download.*` 键)。
///
/// 读的是 `ctx.launcher_config()`——与 `ull config set download.concurrency` 的落点同一份文件
/// (设置键的落点分流见 [`Ctx::setting_path_for`])。gh-proxy 空串 = 跟随内置默认,**不是**关。
#[must_use]
pub(crate) fn tuning(ctx: &Ctx) -> DownloadTuning {
let store = SettingStore::load(ctx.launcher_config(), launcher_schema());
let doc = store.doc();
let gh_proxy = doc
.effective_str(KEY_GH_PROXY)
.unwrap_or_default()
.to_string();
DownloadTuning::from_settings(
doc.effective_i64(KEY_CONCURRENCY),
doc.effective_i64(KEY_RETRY_LIMIT),
Some(gh_proxy.as_str()),
)
}
/// 建该数据根的下载引擎:参数来自 [`tuning`],引擎本体由 core 按缓存根共享。
#[must_use]
pub(crate) fn engine(ctx: &Ctx) -> Arc<DownloadEngine> {
shared::engine_with_tuning(ctx.layout().cache(), tuning(ctx))
}
#[cfg(test)]
mod tests;