复审 r1 P2-1(p2-1items / fix-then-merge):`ull update` 复用 `install::build_engine` 后成了第 4 条 吃设置的路径,但没有任何用例钉它——把 update 换回裸引擎,四条 download::tests 全绿。按 pack 的完全 同形接缝补上: - `commands/update.rs` 新增 `pub(crate) fn engine(ctx)`(`job()` 改调它),doc 写明这条路径上并发 不可观测(自更新只下一个 artifact),随设置变的是每源重试次数与 gh-proxy 前缀; - `download/tests.rs` 新增 `update_engine_takes_the_concurrency_from_the_setting_store`: 写 concurrency=4 ⇒ 断言 `config().max_concurrency` 与 `concurrency_probe()` 都是 4。 顺带收掉复审的三条观察: 1. 新增 `the_gh_proxy_setting_reaches_the_candidate_chain`:镜像优先地区档案下,出厂(空串 = 跟随 内置)确实生成 gh-proxy 候选;手写 `gh_proxy: "off"` 后候选里没有 gh-proxy(读的是 `plan()` 的 候选链,不是配置值;两段式,避免「本来就没有候选」的白绿)。 2. 测试写侧改用 `ctx.setting_path_for(KEY_CONCURRENCY)`(`ull config set` 用的那个表达式),不再与 实现读侧的 `launcher_config()` 共用同一个表达式——实现改读别的文件时用例会红而不是一起漂移。 3. `core/download/config.rs` 的 `KEY_GH_PROXY` doc 已腐化(写「暂未登记、M197 才登记、别删这条弱 断言」,而该键在 main 上就已登记、本文件根本没有针对该常量的断言):改成事实,并保留「弱在哪」 ——常量值与 schema 登记没被断言绑在一起,改名只会让宿主侧静默退化成 Builtin。 变异验证(只改实现侧,逐次还原): - update::engine 换回裸 `EngineConfig::default()` ⇒ 只有 update 那条红(left 8 / right 4),另五条绿; - `download::tuning` 不读 `KEY_GH_PROXY`(传 None)⇒ 只有 gh_proxy 那条红(off 档仍有 `https://gh-proxy.com/...` 候选),另五条绿; - `gh_proxy_override("")` 返回 Off ⇒ gh_proxy 那条的「出厂该套内置前缀」与回落用例的 `tuning == default` 同时红(两处都该红)。
58 lines
2.7 KiB
Rust
58 lines
2.7 KiB
Rust
//! 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 记着这三条 ❌)。第四条路径 `update`(自更新)复用 `install`
|
||
//! 的装配,也随之吃设置;它只下一个 artifact,所以并发在那条路径上不可观测。
|
||
//!
|
||
//! 现在四条一律经 [`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;
|