feat(download): download.* 三个超时/阈值键接进 schema 与引擎(M292 2/2)
P21 第 1 条:M289 的四个超时/阈值只挂在 `EngineConfig`,`DownloadTuning::apply_to` 只搬并发与
每源尝试次数 ⇒ 慢链路用户没有任何自救手段。出厂等价于「平均吞吐 ≥32 KiB/s 才活得下来」:
188MB 在 20 KiB/s 上要 160min > 100.3min 预算,必被杀;被杀后不再重试、不再换源,所以是
「下不完」而不是「慢一点」。
## 键(schema 1.9.0,新键推 minor)
| 键 | 默认 | 范围 | 落到 |
|---|---|---|---|
| `download.throughput_floor_kib` | 32 KiB/s | 4~4096 | `EngineConfig::min_avg_throughput`(×1024 → 字节/秒)|
| `download.stall_timeout_secs` | 120s | 30~600 | `EngineConfig::chunk_stall_timeout` |
| `download.response_timeout_secs` | 60s | 10~600 | `EngineConfig::response_timeout` |
三个默认值与 M289 的硬编码**逐值相等** ⇒ 不设 = 当前行为。上界(`MAX_*` 常量)就是「把挂住变成
无界」那道兜底:越界值在写入口被 schema 拒、引擎侧再回落一次出厂值。
## 通路
`RawTuning`(宿主只按 `KEY_*` 常量取裸值)→ `DownloadTuning::from_raw`(默认/区间/回落/KiB→字节
全在 core 一处)→ `apply_to` → `EngineConfig` → `stall::job_budget(total, floor, min_throughput)`。
`job_budget` 内部 `min_throughput.max(1)` 挡除零(设置层已拒 0,这是纵深防御)。
两个宿主都读六个键:`crates/cli/src/download.rs::tuning`、`presenter::host::settings::download::
tuning_of`。CLI 在**非出厂值**时往 stderr 打一行 `DownloadTuning::summary()`(`--dry-run` 也会经过
它;实测 `ull --data-dir … java install 21 --dry-run` 的 stderr 是
「下载调优:并发=8 单源尝试=3 吞吐下限=16KiB/s 无进展窗口=300s 单次请求上界=180s gh_proxy=跟随内置默认」,
出厂/非法值时一行都不打)。
## 文档口径(各只写一处)
- `stall.rs` 模块头:「改这几个数要付的代价」(调低下限换到的是「慢」不是「无界」;两档窗口是
单次尝试的界,最坏要乘候选数×尝试次数)+「数字从哪来」改成「默认值 / 能不能改」+ 补上 P21
第 3 条要的「`permit_timeout` 是按一次尝试反推,不是一个作业」。
## 两个纯搬移(为 400 行硬线)
- `config.rs` 423 → 261:`DownloadTuning` / `RawTuning` / `secs_in_range` / `impl` 整段搬到
`config/tuning.rs`(194 行),`pub use tuning::{DownloadTuning, RawTuning};` 保住原路径;
搬移块 172 行原样 diff = 0(无归一化)。
- `stall.rs` 440 → 343:测试搬到 `stall/tests.rs`(103 行),唯一变换是整体去 4 格缩进;两个
未改动的用例函数体与 HEAD 逐字符(去空白)相同。
## 用例
core(`config/tests.rs` + `stall/tests.rs` + `keys/download.rs`):默认值与 schema/引擎三处同源、
改设置 ⇒ 引擎配置与总期限都变、0 与越界回落且不除零、doc 里的数字、`summary()` 的生效值、键顺序。
cli:生产入口 `build_engine` 拿到三个新值 + `announce` 只在非出厂值时给行 + 非法值回落。
presenter:文件 → `tuning_of` → `EngineConfig` 三段一致 + 键名常量与 schema 登记绑定。
This commit is contained in:
1 parent
f4b5a73594
commit
2ecb33afae
14 files changed
+950
-211
No files matched your search
@@ -13,10 +13,16 @@
|
||||
//! ```text
|
||||
//! config/launcher.json ←── store.set(`settings::set`,本模块只读)
|
||||
//! download.concurrency ─┐
|
||||
//! download.retry_limit ─┼─→ DownloadTuning(core 决定默认值与夹取)─→ shared::set_tuning
|
||||
//! download.gh_proxy ───┘ (引擎重建时生效)
|
||||
//! download.retry_limit ─┤
|
||||
//! download.gh_proxy ────┼─→ DownloadTuning(core 决定默认值与夹取)─→ shared::set_tuning
|
||||
//! download.throughput_floor_kib ─┤ (引擎重建时生效)
|
||||
//! download.stall_timeout_secs ───┤
|
||||
//! download.response_timeout_secs ┘
|
||||
//! ```
|
||||
//!
|
||||
//! M292:后三个键(吞吐下限 / 无进展窗口 / 单次请求上界)只经 [`tuning_of`] 进引擎,**没有**对应的
|
||||
//! 界面行——它们的说明与代价写在 `core::download::stall` 的模块头,界面行是另一个 mission 的事。
|
||||
//!
|
||||
//! **调优的同步点是显式的**:`host/engine.rs` 每次取引擎前、`dispatch.rs` 的 `SetSetting` 分支里,
|
||||
//! 都调 [`apply_tuning`](幂等:值没变就什么都不做)。它**不是**藏在某个读函数里的副作用——
|
||||
//! 「读起来是纯读、实际改全局状态」正是本仓吃过亏的那类形状。
|
||||
@@ -241,20 +247,29 @@ fn gh_proxy_state(state: &GhProxyOverride) -> String {
|
||||
}
|
||||
|
||||
/// 从 `launcher.json` 读出下载调优(默认值与夹取口径在 core,本函数只做「取原始值」)。
|
||||
///
|
||||
/// M292:六个键一起读(并发 / 单源尝试 / gh-proxy / 吞吐下限 / 无进展窗口 / 单次请求上界),
|
||||
/// 缺省与越界一律由 core 的 [`DownloadTuning::from_raw`] 回落——本函数不判断任何区间。
|
||||
#[must_use]
|
||||
pub(crate) fn tuning_of(env: &HostEnv) -> DownloadTuning {
|
||||
use unlucky_core::download::config::{KEY_CONCURRENCY, KEY_GH_PROXY, KEY_RETRY_LIMIT};
|
||||
use unlucky_core::download::config::{
|
||||
RawTuning, KEY_CHUNK_STALL, KEY_CONCURRENCY, KEY_GH_PROXY, KEY_RESPONSE_TIMEOUT,
|
||||
KEY_RETRY_LIMIT, KEY_THROUGHPUT_FLOOR,
|
||||
};
|
||||
let store = env.store();
|
||||
let doc = store.doc();
|
||||
let gh = doc
|
||||
.effective_str(KEY_GH_PROXY)
|
||||
.map(str::to_string)
|
||||
.unwrap_or_default();
|
||||
DownloadTuning::from_settings(
|
||||
doc.effective_i64(KEY_CONCURRENCY),
|
||||
doc.effective_i64(KEY_RETRY_LIMIT),
|
||||
Some(gh.as_str()),
|
||||
)
|
||||
DownloadTuning::from_raw(RawTuning {
|
||||
concurrency: doc.effective_i64(KEY_CONCURRENCY),
|
||||
retry_limit: doc.effective_i64(KEY_RETRY_LIMIT),
|
||||
gh_proxy: Some(gh.as_str()),
|
||||
throughput_floor_kib: doc.effective_i64(KEY_THROUGHPUT_FLOOR),
|
||||
stall_timeout_secs: doc.effective_i64(KEY_CHUNK_STALL),
|
||||
response_timeout_secs: doc.effective_i64(KEY_RESPONSE_TIMEOUT),
|
||||
})
|
||||
}
|
||||
|
||||
/// 把当前设置灌进 core 的下载调优(按数据根),返回**是否真的变了**(变了就失效该根的引擎)。
|
||||
|
||||
Reference in new issue
Block a user