Skip to content

Commit e0402d2

Browse files
committed
feat(index): miss-triggered refresh — fetch once when a dep isn't local
Refine the offline-first gate per review: fully offline is too strict. Keep the common case zero-network (dependency present in the local index), but when a requested dependency is NOT in the local index, refresh once to fetch it — instead of failing offline. - Announce it: the build path now calls with quiet=false, printing 'Refreshing package index — `<pkg>` not found locally (one-time)' so a rare one-time network pause doesn't look like a silent hang. Steady-state builds (deps present) still print nothing. - Guard against thrash: if the index was refreshed <120s ago and the package is still missing, upstream genuinely lacks it — don't re-run the heavy `xlings update` per missing package in one build. src/xlings.cppm: rework ensure_official_package_index_fresh. src/pm/package_fetcher.cppm: quiet=false at the call site. docs: correct the '稳态不再联网' wording to 'present→offline, missing→refresh once'.
1 parent 3162152 commit e0402d2

3 files changed

Lines changed: 38 additions & 13 deletions

File tree

.agents/docs/2026-06-24-offline-first-index-and-mcpp-index-publish.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,15 @@ mcpp 第一次跑 / 沙盒初始化时(当前日志:`Initialize mcpp sandbox lay
114114

115115
### 4.1 实现进度(WS3)
116116

117-
- **✅ P0②(build 离线优先)**:`ensure_official_package_index_fresh`(`src/xlings.cppm`)
118-
不再因 TTL 过期就跑联网 `xlings update`;**只在本地索引项缺失(首次 / 没见过的包)时拉一次**
119-
稳态 `mcpp build` 不再联网 —— 直接消除 Termux 首跑/构建卡几分钟的根因(commit `f0f57ae`)。
117+
- **✅ P0②(build 离线优先 + 缺包触发刷新)**:`ensure_official_package_index_fresh`(`src/xlings.cppm`)
118+
不再因 TTL 过期就跑联网 `xlings update`。改为 **miss-triggered**:
119+
- **依赖在本地索引里 → 直接用,零网络**(常态 build,消除 Termux 首跑/构建卡几分钟的根因);
120+
- **依赖在本地索引里查不到 → 自动刷新一次**去拉它(`mcpp build` 路径以 `quiet=false` 调用,
121+
打印一行 `Refreshing package index — \`<pkg>\` not found locally`,让一次性网络停顿不像卡死)。
122+
- **防重**:刚刷过(<120s)且包仍缺失 → 不再重复跑 `xlings update`(上游确实没有,重拉无益),
123+
避免一个 build 里多个缺包各跑一遍全量 git 同步。
124+
commit `f0f57ae`(初版纯离线)→ 增补 miss-triggered + 防重 + 可见提示。
125+
> 即"完全不联网"过严;稳态(依赖齐全)不联网,**缺包则联网刷一次**,二者兼得。
120126
- **✅ P0③(`mcpp index status`)**:新增只读、**全程不联网**`mcpp index status`,显示
121127
xim/mcpplibs 两索引的 present/fresh/age/path;缺索引时提示显式 `mcpp index update`,否则确认本地可离线用。
122128
`src/xlings.cppm` 导出 `IndexStatus` + `{default,official}_index_status`;`src/pm/index_management.cppm`

src/pm/package_fetcher.cppm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,8 +725,13 @@ Fetcher::resolve_xpkg_path(std::string_view target,
725725
if (autoInstall) {
726726
if (parsed.indexName == "xim") {
727727
mcpp::xlings::Env xlEnv{ cfg_.xlingsBinary, cfg_.xlingsHome() };
728+
// quiet=false: this only ever prints when a dependency is missing
729+
// from the local index and we refresh once to fetch it — a rare,
730+
// intentional event worth surfacing so a one-time network pause
731+
// doesn't look like a silent hang. Steady-state builds (deps
732+
// present) return early without a word.
728733
mcpp::xlings::ensure_official_package_index_fresh(
729-
xlEnv, parsed.packageName, cfg_.searchTtlSeconds, /*quiet=*/true);
734+
xlEnv, parsed.packageName, cfg_.searchTtlSeconds, /*quiet=*/false);
730735
}
731736

732737
std::vector<std::string> targets {

src/xlings.cppm

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,19 +1248,33 @@ void ensure_official_package_index_fresh(const Env& env,
12481248
std::string_view packageName,
12491249
[[maybe_unused]] std::int64_t ttlSeconds,
12501250
bool quiet) {
1251-
// Offline-first: an existing local index entry is used as-is. We do NOT
1252-
// auto-update just because a TTL expired — that runs a network `xlings
1253-
// update` (git-syncs several index repos) that stalls for minutes on
1254-
// slow/blocked networks (the Termux first-run / build hang). Fetch ONLY when
1255-
// the entry is MISSING (first run / never-seen package), so the index is
1256-
// guaranteed to exist; routine refresh is the user's explicit
1251+
// Offline-first, miss-triggered. We do NOT auto-update just because a TTL
1252+
// expired — that runs a network `xlings update` (git-syncs several index
1253+
// repos) that stalls for minutes on slow/blocked networks (the Termux
1254+
// first-run / build hang). But fully offline is too strict: if a requested
1255+
// dependency is NOT in the local index, we DO refresh once to discover it.
1256+
//
1257+
// present locally → use as-is, zero network (the common build case).
1258+
// missing locally → refresh once to try to fetch it.
1259+
//
1260+
// Routine, deps-already-present refresh stays the user's explicit
12571261
// `mcpp index update` / `xlings update`.
12581262
auto pkg = official_package_file(env, packageName);
12591263
if (!pkg.empty() && std::filesystem::exists(pkg)) return;
1264+
1265+
// The package is missing locally. Refresh once — but guard against a build
1266+
// that resolves several genuinely-absent packages re-running the heavy
1267+
// `xlings update` per package: if the index was refreshed moments ago and
1268+
// the package is STILL missing, upstream simply lacks it; re-pulling won't
1269+
// help. (A package added upstream before this run lands in that one pull.)
1270+
constexpr std::int64_t kJustRefreshedSeconds = 120;
1271+
if (is_official_index_fresh(env, kJustRefreshedSeconds)) return;
1272+
12601273
if (!quiet)
1261-
print_status("Fetching",
1262-
std::format("index entry for {} (one-time)", packageName));
1263-
update_index(env, /*quiet=*/true);
1274+
print_status("Refreshing",
1275+
std::format("package index — `{}` not found locally (one-time)",
1276+
packageName));
1277+
update_index(env, /*quiet=*/quiet);
12641278
}
12651279

12661280
} // namespace mcpp::xlings

0 commit comments

Comments
 (0)