refactor(download): 纯搬移为 M289 腾出行数余量(config 单测 / engine 只读查询面)
两个文件都是 400 行零余量的硬线,本 mission 要加超时字段与失速诊断,先纯搬移: * `config.rs` 的 `#[cfg(test)] mod tests`(174 行)→ `config/tests.rs`, 原文件用 `#[cfg(test)] #[path = "config/tests.rs"] mod tests;` 声明; * `engine.rs` 的七个只读 getter(`config` / `concurrency_probe` / `client` / `region` / `mirrors` / `health` / `cache`,44 行)→ `engine/inspect.rs`。 逐字节未改:搬移块去缩进后与 HEAD 原文 `diff` 均为 exit 0。 行为零变化(同一批测试仍全绿);新文件都在 `crates/core/src/download/**` 内, 外部路径(`download::config::EngineConfig` 等)不变。
This commit is contained in:
1 parent
8b48c494cd
commit
61c8a4eff9
4 files changed
+237
-219
No files matched your search
@@ -223,178 +223,5 @@ pub fn publish(cache_root: &Path, next: DownloadTuning) -> bool {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::setting::keys::{launcher_schema, launcher_version};
|
||||
|
||||
/// **守门③**:schema 的默认值 / 区间 / 键名与 `EngineConfig::default()` / 调优默认值取同一组常量。
|
||||
/// 变异证明(只改实现侧):`EngineConfig::default()` 的并发写回 64、schema 默认值写成 16、
|
||||
/// `MAX_CONCURRENCY` 改了而 schema 仍写 64 ⇒ 各自红。
|
||||
#[test]
|
||||
fn the_schema_contract_is_single_sourced() {
|
||||
let schema = launcher_schema();
|
||||
assert_eq!(schema.version(), launcher_version());
|
||||
let cfg = EngineConfig::default();
|
||||
let tune = DownloadTuning::default();
|
||||
|
||||
// 并发 1~64(0 张许可没意义);尝试次数 **0**~10(P2-1:0 = 只试一次,旧配置里真有)。
|
||||
let contract: [(&str, i64, i64, usize); 2] = [
|
||||
(
|
||||
KEY_CONCURRENCY,
|
||||
i64::try_from(DEFAULT_MAX_CONCURRENCY).expect("装得下"),
|
||||
1,
|
||||
MAX_CONCURRENCY,
|
||||
),
|
||||
(
|
||||
KEY_RETRY_LIMIT,
|
||||
i64::from(DEFAULT_MAX_ATTEMPTS_PER_SOURCE),
|
||||
0,
|
||||
usize::try_from(MAX_ATTEMPTS_PER_SOURCE).expect("装得下"),
|
||||
),
|
||||
];
|
||||
for (key, default, min, max) in contract {
|
||||
let spec = schema.spec(key).expect("键已登记");
|
||||
assert_eq!(spec.default, serde_json::json!(default), "{key}");
|
||||
assert_eq!(
|
||||
spec.kind,
|
||||
crate::setting::spec::ValueKind::Int {
|
||||
min,
|
||||
max: i64::try_from(max).expect("装得下"),
|
||||
},
|
||||
"{key}"
|
||||
);
|
||||
}
|
||||
assert_eq!(cfg.max_concurrency, DEFAULT_MAX_CONCURRENCY);
|
||||
assert_eq!(tune.max_concurrency, DEFAULT_MAX_CONCURRENCY);
|
||||
assert_eq!(cfg.max_attempts_per_source, DEFAULT_MAX_ATTEMPTS_PER_SOURCE);
|
||||
assert_eq!(
|
||||
tune.max_attempts_per_source,
|
||||
DEFAULT_MAX_ATTEMPTS_PER_SOURCE
|
||||
);
|
||||
}
|
||||
|
||||
/// `SettingSpec.doc` 是 `&'static str`(`concat!` 插不进常量),描述里的数字只能手写——这条钉住它,
|
||||
/// 改常量不改文案就红(`catalog.rs` 会把这些 doc 当 JSON schema 的 description 发出去)。
|
||||
#[test]
|
||||
fn the_key_docs_quote_the_real_limits() {
|
||||
let schema = launcher_schema();
|
||||
let doc = |key: &str| schema.spec(key).expect("键已登记").doc;
|
||||
assert!(doc(KEY_CONCURRENCY).contains(&format!("1~{MAX_CONCURRENCY}")));
|
||||
assert!(doc(KEY_CONCURRENCY).contains(&format!("出厂 {DEFAULT_MAX_CONCURRENCY}")));
|
||||
assert!(doc(KEY_RETRY_LIMIT).contains(&format!("出厂 {DEFAULT_MAX_ATTEMPTS_PER_SOURCE}")));
|
||||
}
|
||||
|
||||
/// 未填 / 越界回落默认(不阻断下载);**`retry_limit: 0` 是合法值**,语义 = 只试一次。
|
||||
///
|
||||
/// 变异证明:把并发的区间过滤删掉 ⇒ `0` / `9999` 两条红;把尝试次数的 `.max(1)` 删掉 ⇒
|
||||
/// `0 → 1` 那条红(引擎会拿到 0 次尝试);把 `0` 判成越界 ⇒ 同样红。
|
||||
#[test]
|
||||
fn missing_or_illegal_values_fall_back_to_the_defaults() {
|
||||
assert_eq!(
|
||||
DownloadTuning::from_settings(None, None, None),
|
||||
DownloadTuning::default()
|
||||
);
|
||||
|
||||
let just_over = i64::try_from(MAX_CONCURRENCY).expect("上限装得下") + 1;
|
||||
for bad in [0_i64, -1, 9_999, just_over] {
|
||||
let tune = DownloadTuning::from_settings(Some(bad), None, None);
|
||||
assert_eq!(tune.max_concurrency, DEFAULT_MAX_CONCURRENCY, "{bad}");
|
||||
}
|
||||
// 0 与 1 都 = 只试一次:旧配置里的 0 不许回落成出厂 3(那正是「界面 0、引擎 3」)。
|
||||
for zero_or_one in [0_i64, 1] {
|
||||
let tune = DownloadTuning::from_settings(None, Some(zero_or_one), None);
|
||||
assert_eq!(tune.max_attempts_per_source, 1, "{zero_or_one}");
|
||||
}
|
||||
for bad in [-1_i64, 9_999] {
|
||||
let tune = DownloadTuning::from_settings(None, Some(bad), None);
|
||||
assert_eq!(
|
||||
tune.max_attempts_per_source,
|
||||
DEFAULT_MAX_ATTEMPTS_PER_SOURCE
|
||||
);
|
||||
}
|
||||
|
||||
let tune = DownloadTuning::from_settings(Some(2), Some(2), None);
|
||||
assert_eq!(tune.max_concurrency, 2);
|
||||
assert_eq!(tune.max_attempts_per_source, 2);
|
||||
}
|
||||
|
||||
/// 三态:**空串 ≠ 关**(这条是「设置项说假话」的高发点,M197 的键语义同源)。
|
||||
#[test]
|
||||
fn empty_gh_proxy_means_follow_builtin_not_off() {
|
||||
assert_eq!(gh_proxy_override(""), GhProxyOverride::Builtin);
|
||||
assert_eq!(gh_proxy_override(" "), GhProxyOverride::Builtin);
|
||||
for off in [
|
||||
"off", "OFF", " none ", "direct", "disable", "disabled", "no",
|
||||
] {
|
||||
assert_eq!(gh_proxy_override(off), GhProxyOverride::Off, "{off}");
|
||||
}
|
||||
assert_eq!(
|
||||
gh_proxy_override(" https://gh.example/ "),
|
||||
GhProxyOverride::Prefix("https://gh.example/".to_string())
|
||||
);
|
||||
// 未填(键不存在)也是 Builtin,不是 Off。
|
||||
assert_eq!(
|
||||
DownloadTuning::from_settings(None, None, None).gh_proxy,
|
||||
GhProxyOverride::Builtin
|
||||
);
|
||||
}
|
||||
|
||||
/// `apply_gh_proxy` 的三档真的改到档案上、并且**改到候选链上**(`expand()` 读的就是档案里那个
|
||||
/// 前缀;自定义前缀那一档的链断言在 `shared.rs`)。变异证明:`Off` 分支改成原样返回 ⇒ `off` 红。
|
||||
#[test]
|
||||
fn gh_proxy_override_reaches_the_profile_and_the_chain() {
|
||||
use crate::download::mirrors::{MirrorTable, SOURCE_GH_PROXY};
|
||||
use crate::download::types::ResourceKind;
|
||||
|
||||
let url = "https://github.com/o/r/releases/download/v1/a.jar";
|
||||
let table = MirrorTable::builtin();
|
||||
let sources = |profile: &RegionProfile| -> Vec<String> {
|
||||
table
|
||||
.expand(url, ResourceKind::Other, profile)
|
||||
.into_iter()
|
||||
.map(|candidate| candidate.source)
|
||||
.collect()
|
||||
};
|
||||
|
||||
let mirror_first = RegionProfile::mirror_first(0);
|
||||
let kept = DownloadTuning::default().apply_gh_proxy(mirror_first.clone());
|
||||
assert_eq!(kept.gh_proxy, mirror_first.gh_proxy, "Builtin 不该动档案");
|
||||
assert!(
|
||||
sources(&kept).contains(&SOURCE_GH_PROXY.to_string()),
|
||||
"出厂套前缀"
|
||||
);
|
||||
|
||||
let off = DownloadTuning::from_settings(None, None, Some("off"))
|
||||
.apply_gh_proxy(mirror_first.clone());
|
||||
assert!(
|
||||
!sources(&off).contains(&SOURCE_GH_PROXY.to_string()),
|
||||
"关了就没候选"
|
||||
);
|
||||
|
||||
let prefix = DownloadTuning::from_settings(None, None, Some("https://gh.example/"))
|
||||
.apply_gh_proxy(mirror_first);
|
||||
assert_eq!(prefix.gh_proxy.as_deref(), Some("https://gh.example/"));
|
||||
assert!(prefix.gh_proxy_enabled(), "前缀生效");
|
||||
}
|
||||
|
||||
/// 每个数据根的调优互不串味(一个根改成 2 不该改另一个根的引擎)。
|
||||
/// 变异证明:把 `wanted`/`publish` 的键改回单一进程级槽位 ⇒ 第二个根读到 2,红。
|
||||
#[test]
|
||||
fn tuning_is_per_cache_root_and_no_change_is_reported_as_such() {
|
||||
let a = PathBuf::from("/tmp/ull-tuning-a");
|
||||
let b = PathBuf::from("/tmp/ull-tuning-b");
|
||||
assert_eq!(wanted(&a), DownloadTuning::default());
|
||||
|
||||
let changed = DownloadTuning::from_settings(Some(2), None, None);
|
||||
assert!(publish(&a, changed.clone()), "真变了要报变更");
|
||||
assert_eq!(wanted(&a), changed);
|
||||
assert!(!publish(&a, changed.clone()), "同值不该报变更");
|
||||
assert_eq!(wanted(&b), DownloadTuning::default(), "别的根不受影响");
|
||||
|
||||
assert!(
|
||||
publish(&a, DownloadTuning::default()),
|
||||
"恢复默认也是一次变更"
|
||||
);
|
||||
assert_eq!(wanted(&a), DownloadTuning::default());
|
||||
}
|
||||
}
|
||||
#[path = "config/tests.rs"]
|
||||
mod tests;
|
||||
@@ -0,0 +1,175 @@
|
||||
//! `download::config` 的单测:**从 `config.rs` 拆出只为守 400 行硬线**(M289 加超时字段前先纯搬移,逐字节未改)。
|
||||
|
||||
use super::*;
|
||||
use crate::setting::keys::{launcher_schema, launcher_version};
|
||||
|
||||
/// **守门③**:schema 的默认值 / 区间 / 键名与 `EngineConfig::default()` / 调优默认值取同一组常量。
|
||||
/// 变异证明(只改实现侧):`EngineConfig::default()` 的并发写回 64、schema 默认值写成 16、
|
||||
/// `MAX_CONCURRENCY` 改了而 schema 仍写 64 ⇒ 各自红。
|
||||
#[test]
|
||||
fn the_schema_contract_is_single_sourced() {
|
||||
let schema = launcher_schema();
|
||||
assert_eq!(schema.version(), launcher_version());
|
||||
let cfg = EngineConfig::default();
|
||||
let tune = DownloadTuning::default();
|
||||
|
||||
// 并发 1~64(0 张许可没意义);尝试次数 **0**~10(P2-1:0 = 只试一次,旧配置里真有)。
|
||||
let contract: [(&str, i64, i64, usize); 2] = [
|
||||
(
|
||||
KEY_CONCURRENCY,
|
||||
i64::try_from(DEFAULT_MAX_CONCURRENCY).expect("装得下"),
|
||||
1,
|
||||
MAX_CONCURRENCY,
|
||||
),
|
||||
(
|
||||
KEY_RETRY_LIMIT,
|
||||
i64::from(DEFAULT_MAX_ATTEMPTS_PER_SOURCE),
|
||||
0,
|
||||
usize::try_from(MAX_ATTEMPTS_PER_SOURCE).expect("装得下"),
|
||||
),
|
||||
];
|
||||
for (key, default, min, max) in contract {
|
||||
let spec = schema.spec(key).expect("键已登记");
|
||||
assert_eq!(spec.default, serde_json::json!(default), "{key}");
|
||||
assert_eq!(
|
||||
spec.kind,
|
||||
crate::setting::spec::ValueKind::Int {
|
||||
min,
|
||||
max: i64::try_from(max).expect("装得下"),
|
||||
},
|
||||
"{key}"
|
||||
);
|
||||
}
|
||||
assert_eq!(cfg.max_concurrency, DEFAULT_MAX_CONCURRENCY);
|
||||
assert_eq!(tune.max_concurrency, DEFAULT_MAX_CONCURRENCY);
|
||||
assert_eq!(cfg.max_attempts_per_source, DEFAULT_MAX_ATTEMPTS_PER_SOURCE);
|
||||
assert_eq!(
|
||||
tune.max_attempts_per_source,
|
||||
DEFAULT_MAX_ATTEMPTS_PER_SOURCE
|
||||
);
|
||||
}
|
||||
|
||||
/// `SettingSpec.doc` 是 `&'static str`(`concat!` 插不进常量),描述里的数字只能手写——这条钉住它,
|
||||
/// 改常量不改文案就红(`catalog.rs` 会把这些 doc 当 JSON schema 的 description 发出去)。
|
||||
#[test]
|
||||
fn the_key_docs_quote_the_real_limits() {
|
||||
let schema = launcher_schema();
|
||||
let doc = |key: &str| schema.spec(key).expect("键已登记").doc;
|
||||
assert!(doc(KEY_CONCURRENCY).contains(&format!("1~{MAX_CONCURRENCY}")));
|
||||
assert!(doc(KEY_CONCURRENCY).contains(&format!("出厂 {DEFAULT_MAX_CONCURRENCY}")));
|
||||
assert!(doc(KEY_RETRY_LIMIT).contains(&format!("出厂 {DEFAULT_MAX_ATTEMPTS_PER_SOURCE}")));
|
||||
}
|
||||
|
||||
/// 未填 / 越界回落默认(不阻断下载);**`retry_limit: 0` 是合法值**,语义 = 只试一次。
|
||||
///
|
||||
/// 变异证明:把并发的区间过滤删掉 ⇒ `0` / `9999` 两条红;把尝试次数的 `.max(1)` 删掉 ⇒
|
||||
/// `0 → 1` 那条红(引擎会拿到 0 次尝试);把 `0` 判成越界 ⇒ 同样红。
|
||||
#[test]
|
||||
fn missing_or_illegal_values_fall_back_to_the_defaults() {
|
||||
assert_eq!(
|
||||
DownloadTuning::from_settings(None, None, None),
|
||||
DownloadTuning::default()
|
||||
);
|
||||
|
||||
let just_over = i64::try_from(MAX_CONCURRENCY).expect("上限装得下") + 1;
|
||||
for bad in [0_i64, -1, 9_999, just_over] {
|
||||
let tune = DownloadTuning::from_settings(Some(bad), None, None);
|
||||
assert_eq!(tune.max_concurrency, DEFAULT_MAX_CONCURRENCY, "{bad}");
|
||||
}
|
||||
// 0 与 1 都 = 只试一次:旧配置里的 0 不许回落成出厂 3(那正是「界面 0、引擎 3」)。
|
||||
for zero_or_one in [0_i64, 1] {
|
||||
let tune = DownloadTuning::from_settings(None, Some(zero_or_one), None);
|
||||
assert_eq!(tune.max_attempts_per_source, 1, "{zero_or_one}");
|
||||
}
|
||||
for bad in [-1_i64, 9_999] {
|
||||
let tune = DownloadTuning::from_settings(None, Some(bad), None);
|
||||
assert_eq!(
|
||||
tune.max_attempts_per_source,
|
||||
DEFAULT_MAX_ATTEMPTS_PER_SOURCE
|
||||
);
|
||||
}
|
||||
|
||||
let tune = DownloadTuning::from_settings(Some(2), Some(2), None);
|
||||
assert_eq!(tune.max_concurrency, 2);
|
||||
assert_eq!(tune.max_attempts_per_source, 2);
|
||||
}
|
||||
|
||||
/// 三态:**空串 ≠ 关**(这条是「设置项说假话」的高发点,M197 的键语义同源)。
|
||||
#[test]
|
||||
fn empty_gh_proxy_means_follow_builtin_not_off() {
|
||||
assert_eq!(gh_proxy_override(""), GhProxyOverride::Builtin);
|
||||
assert_eq!(gh_proxy_override(" "), GhProxyOverride::Builtin);
|
||||
for off in [
|
||||
"off", "OFF", " none ", "direct", "disable", "disabled", "no",
|
||||
] {
|
||||
assert_eq!(gh_proxy_override(off), GhProxyOverride::Off, "{off}");
|
||||
}
|
||||
assert_eq!(
|
||||
gh_proxy_override(" https://gh.example/ "),
|
||||
GhProxyOverride::Prefix("https://gh.example/".to_string())
|
||||
);
|
||||
// 未填(键不存在)也是 Builtin,不是 Off。
|
||||
assert_eq!(
|
||||
DownloadTuning::from_settings(None, None, None).gh_proxy,
|
||||
GhProxyOverride::Builtin
|
||||
);
|
||||
}
|
||||
|
||||
/// `apply_gh_proxy` 的三档真的改到档案上、并且**改到候选链上**(`expand()` 读的就是档案里那个
|
||||
/// 前缀;自定义前缀那一档的链断言在 `shared.rs`)。变异证明:`Off` 分支改成原样返回 ⇒ `off` 红。
|
||||
#[test]
|
||||
fn gh_proxy_override_reaches_the_profile_and_the_chain() {
|
||||
use crate::download::mirrors::{MirrorTable, SOURCE_GH_PROXY};
|
||||
use crate::download::types::ResourceKind;
|
||||
|
||||
let url = "https://github.com/o/r/releases/download/v1/a.jar";
|
||||
let table = MirrorTable::builtin();
|
||||
let sources = |profile: &RegionProfile| -> Vec<String> {
|
||||
table
|
||||
.expand(url, ResourceKind::Other, profile)
|
||||
.into_iter()
|
||||
.map(|candidate| candidate.source)
|
||||
.collect()
|
||||
};
|
||||
|
||||
let mirror_first = RegionProfile::mirror_first(0);
|
||||
let kept = DownloadTuning::default().apply_gh_proxy(mirror_first.clone());
|
||||
assert_eq!(kept.gh_proxy, mirror_first.gh_proxy, "Builtin 不该动档案");
|
||||
assert!(
|
||||
sources(&kept).contains(&SOURCE_GH_PROXY.to_string()),
|
||||
"出厂套前缀"
|
||||
);
|
||||
|
||||
let off = DownloadTuning::from_settings(None, None, Some("off"))
|
||||
.apply_gh_proxy(mirror_first.clone());
|
||||
assert!(
|
||||
!sources(&off).contains(&SOURCE_GH_PROXY.to_string()),
|
||||
"关了就没候选"
|
||||
);
|
||||
|
||||
let prefix = DownloadTuning::from_settings(None, None, Some("https://gh.example/"))
|
||||
.apply_gh_proxy(mirror_first);
|
||||
assert_eq!(prefix.gh_proxy.as_deref(), Some("https://gh.example/"));
|
||||
assert!(prefix.gh_proxy_enabled(), "前缀生效");
|
||||
}
|
||||
|
||||
/// 每个数据根的调优互不串味(一个根改成 2 不该改另一个根的引擎)。
|
||||
/// 变异证明:把 `wanted`/`publish` 的键改回单一进程级槽位 ⇒ 第二个根读到 2,红。
|
||||
#[test]
|
||||
fn tuning_is_per_cache_root_and_no_change_is_reported_as_such() {
|
||||
let a = PathBuf::from("/tmp/ull-tuning-a");
|
||||
let b = PathBuf::from("/tmp/ull-tuning-b");
|
||||
assert_eq!(wanted(&a), DownloadTuning::default());
|
||||
|
||||
let changed = DownloadTuning::from_settings(Some(2), None, None);
|
||||
assert!(publish(&a, changed.clone()), "真变了要报变更");
|
||||
assert_eq!(wanted(&a), changed);
|
||||
assert!(!publish(&a, changed.clone()), "同值不该报变更");
|
||||
assert_eq!(wanted(&b), DownloadTuning::default(), "别的根不受影响");
|
||||
|
||||
assert!(
|
||||
publish(&a, DownloadTuning::default()),
|
||||
"恢复默认也是一次变更"
|
||||
);
|
||||
assert_eq!(wanted(&a), DownloadTuning::default());
|
||||
}
|
||||
@@ -35,6 +35,8 @@ use super::types::{
|
||||
SOURCE_OFFICIAL,
|
||||
};
|
||||
|
||||
mod inspect;
|
||||
|
||||
/// 一次成功尝试的产物描述。
|
||||
pub(crate) struct AttemptOk {
|
||||
/// 文件总字节数。
|
||||
@@ -94,50 +96,6 @@ impl DownloadEngine {
|
||||
self
|
||||
}
|
||||
|
||||
/// 配置。
|
||||
#[must_use]
|
||||
pub fn config(&self) -> &EngineConfig {
|
||||
&self.cfg
|
||||
}
|
||||
|
||||
/// **真实并发闸门**此刻的许可数(探针,M193):读 [`Self::acquire`] 会去抢的那张
|
||||
/// `Semaphore`,**不是** `config().max_concurrency`。有下载在飞时偏小,空闲等于容量。
|
||||
#[must_use]
|
||||
pub fn concurrency_probe(&self) -> usize {
|
||||
self.sem.available_permits()
|
||||
}
|
||||
|
||||
/// HTTP 客户端(同一条连接池与超时配置):给「一锤子查询」用(如 Adoptium 版本查询),
|
||||
/// 没必要为了一个 GET 再造一个 client。
|
||||
#[must_use]
|
||||
pub fn client(&self) -> &reqwest::Client {
|
||||
&self.http
|
||||
}
|
||||
|
||||
/// 当前地区档案(设置页展示)。
|
||||
#[must_use]
|
||||
pub fn region(&self) -> &RegionProfile {
|
||||
&self.region
|
||||
}
|
||||
|
||||
/// 镜像表(`game::java` 的 Oracle / MS / Zulu 分发表在这里查)。
|
||||
#[must_use]
|
||||
pub fn mirrors(&self) -> &MirrorTable {
|
||||
&self.mirrors
|
||||
}
|
||||
|
||||
/// 健康度注册表(诊断页)。
|
||||
#[must_use]
|
||||
pub fn health(&self) -> &HealthRegistry {
|
||||
&self.health
|
||||
}
|
||||
|
||||
/// 内容寻址缓存。
|
||||
#[must_use]
|
||||
pub fn cache(&self) -> &ContentCache {
|
||||
&self.cache
|
||||
}
|
||||
|
||||
/// 候选规划:镜像展开 → 官方位置保持不变 → 其余按健康度排序。
|
||||
#[must_use]
|
||||
pub fn plan(&self, req: &DownloadRequest, now_ms: u64) -> Vec<Candidate> {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
//! 引擎的只读查询面:**从 `engine.rs` 拆出只为守 400 行硬线**(M289 加失速诊断前先纯搬移,逐字节未改)。
|
||||
//!
|
||||
//! 这里只有「读」——配置、并发闸门探针、HTTP 客户端、地区档案、镜像表、健康度、内容缓存。
|
||||
//! 编排(候选循环、退避、落盘)仍在 [`super`]。
|
||||
|
||||
use super::super::cache::ContentCache;
|
||||
use super::super::config::EngineConfig;
|
||||
use super::super::health::HealthRegistry;
|
||||
use super::super::mirrors::MirrorTable;
|
||||
use super::super::region::RegionProfile;
|
||||
use super::DownloadEngine;
|
||||
|
||||
impl DownloadEngine {
|
||||
/// 配置。
|
||||
#[must_use]
|
||||
pub fn config(&self) -> &EngineConfig {
|
||||
&self.cfg
|
||||
}
|
||||
|
||||
/// **真实并发闸门**此刻的许可数(探针,M193):读 [`Self::acquire`] 会去抢的那张
|
||||
/// `Semaphore`,**不是** `config().max_concurrency`。有下载在飞时偏小,空闲等于容量。
|
||||
#[must_use]
|
||||
pub fn concurrency_probe(&self) -> usize {
|
||||
self.sem.available_permits()
|
||||
}
|
||||
|
||||
/// HTTP 客户端(同一条连接池与超时配置):给「一锤子查询」用(如 Adoptium 版本查询),
|
||||
/// 没必要为了一个 GET 再造一个 client。
|
||||
#[must_use]
|
||||
pub fn client(&self) -> &reqwest::Client {
|
||||
&self.http
|
||||
}
|
||||
|
||||
/// 当前地区档案(设置页展示)。
|
||||
#[must_use]
|
||||
pub fn region(&self) -> &RegionProfile {
|
||||
&self.region
|
||||
}
|
||||
|
||||
/// 镜像表(`game::java` 的 Oracle / MS / Zulu 分发表在这里查)。
|
||||
#[must_use]
|
||||
pub fn mirrors(&self) -> &MirrorTable {
|
||||
&self.mirrors
|
||||
}
|
||||
|
||||
/// 健康度注册表(诊断页)。
|
||||
#[must_use]
|
||||
pub fn health(&self) -> &HealthRegistry {
|
||||
&self.health
|
||||
}
|
||||
|
||||
/// 内容寻址缓存。
|
||||
#[must_use]
|
||||
pub fn cache(&self) -> &ContentCache {
|
||||
&self.cache
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user