feat: add official resource sync pipeline

Add the production-facing official update service and bat-official-sync watch CLI for unattended resource synchronization.

Support launcher-resource discovery without installing the launcher, remote marker snapshots, local manifest audit and repair, official seed hash validation, bootstrap caching, richer Addressables coverage, SQLite resource persistence, and FFI JSON helpers.
This commit is contained in:
2026-07-05 23:49:56 +08:00
parent 99e66a48d7
commit 789402c887
35 changed files with 6262 additions and 177 deletions
+3 -2
View File
@@ -8,8 +8,9 @@ BlueArchive Toolkit 采用 **Monorepo + 多语言混合** 架构,旨在构建
当前已经可用的官方资源入口包括:
- `infrastructure/examples/official_launcher_bootstrap.rs`
- `infrastructure/examples/official_pull_plan.rs`
- `infrastructure/examples/official_pull_plan.rs`:Linux 生产资源拉取路径,显式读取官方 `server-info` 输入。
- `infrastructure/examples/official_update_check.rs`:Linux 自动更新检查入口,保存 snapshot 并按需拉取。
- `infrastructure/examples/official_launcher_bootstrap.rs`:显式开发/审计辅助路径,用于核查官方 launcher metadata,不是生产运行依赖。
- `docs/guides/official-resource-test-pull.md`
已接受的架构决策:
@@ -35,7 +35,7 @@ BlueArchiveToolkit 的最终目标覆盖资源同步、CAS、AssetBundle 解析
3. **Go 应用层**
- 负责 CLI、资源同步、下载器、API Server、任务调度、配置、日志、Provider 编排。
- 通过 FFI、进程边界或稳定 SDK 调用 Rust 引擎能力。
- 通过稳定 SDK、进程边界,必要时再通过 FFI 调用 Rust 引擎能力。
- 不重复实现 AssetBundle 解析、Patch 算法或 CAS 对象存储核心逻辑。
4. **Web 层**
@@ -48,8 +48,8 @@ BlueArchiveToolkit 的最终目标覆盖资源同步、CAS、AssetBundle 解析
1. Rust 引擎 API 必须保持业务无关,不出现 CLI 命令、HTTP 状态码、Web 页面状态。
2. Go 应用层不得复制 Rust 引擎中的 Hash、Patch、AssetBundle 核心算法。
3. FFI 边界必须避免暴露大量细粒度内部结构,优先暴露批量和事务语义。
4. 所有跨语言错误必须能映射到统一错误码和可读诊断信息。
3. 跨边界优先级应是进程边界或稳定 SDK,其次才是 FFI;若使用 FFI,必须只暴露粗粒度批量和事务语义。
4. 所有跨边界错误必须能映射到统一错误码和可读诊断信息。
---
@@ -45,6 +45,6 @@ CAS V1 对外领域接口继续使用 `bat_core::repositories::cas_repository::C
## 后果
1. 后续 Go CLI/API 只能通过领域仓储接口稳定 FFI 调用 CAS,不直接依赖对象目录结构。
1. 后续 Go CLI/API 只能通过领域仓储接口稳定 SDK 或进程边界调用 CAS,不直接依赖对象目录结构FFI 仅作为可选实现方式
2. CAS V1 后续可以替换元数据后端,但不能改变领域接口语义。
3. 如果以后需要 dry-run GC、批量引用更新或流式存储,应作为新接口扩展,不破坏当前 trait。
+68 -5
View File
@@ -11,6 +11,8 @@
- `bluearchive.cafe`
- 任何镜像层、转写层、二次代理层
- 人工拼接出来的样例 URL
- Linux 生产环境安装或执行官方启动器
- 把已安装客户端目录或官方启动器安装目录当作生产输入
当前默认平台集合是:
@@ -29,9 +31,23 @@
| 下载层 | 校验官方 URL,调用下载器,落盘并记录字节数 | 得到本地资源副本 |
| 导入层 | 将 bundle 写入 CAS 和 ResourceRepository | 得到可查询的资源索引 |
| 同步层 | 比较当前快照和历史快照 | 决定下载、校验、发布 |
| 更新层 | 保存上次官方 snapshot,定期执行 discovery + diff + pull | 形成自动更新闭环 |
## 3. 工作原理
### 3.0 Linux 生产约束
生产环境目标是 Linux 后端任务,不是 Windows 桌面客户端环境。
因此生产同步入口必须满足:
1. 不要求安装官方启动器。
2. 不要求启动官方启动器进程。
3. 不要求把生产环境当作客户端安装目录。
4. 可以显式执行 official metadata discovery 自动发现 `server-info` URL、`connection-group``app-version`
5. 也可以通过配置、调度状态或已审计 metadata snapshot 显式提供这些值。
6. `--auto-discover` 只允许通过官方 HTTP metadata 和临时目录解析 `GameMainConfig`launcher metadata 未变时必须复用缓存,metadata 变化时才重新下载必要官方 game zip。
### 3.1 发现官方资源根
入口是 `YostarJpServerInfo`
@@ -105,9 +121,16 @@
1. 检查 URL 是否属于官方 host。
2. 把 URL 映射到本地输出路径。
3. 通过系统 `curl` 下载
4. 记录文件大小和最终路径
5. 非官方 URL 直接拒绝
3. 读取输出目录下的 `official-download-manifest.json`
4. 已存在目标文件只有在本地清单中的相对路径、size、BLAKE3 都匹配时才跳过
5. 缺少清单、清单不匹配或文件损坏时重新下载
6. `TableCatalog.bytes``BundlePackingInfo.bytes``MediaCatalog.bytes` 总是刷新并用官方 `.hash` 强校验;该 `.hash``xxHash32(seed=0)` 的十进制文本。
7. `catalog_*.hash` 当前只作为 Addressables catalog 变更标记,不作为 zip/JSON 内容校验算法;Unity Addressables/SBP builder 对 JSON/bin catalog 使用 `HashingMethods.Calculate` 生成 `Hash128` 文本,运行时用它判断 remote catalog cache 是否过期,它不能套用 seed catalog 的 `xxHash32` 规则。
8. 存在 `.part` 临时文件时通过 `curl --continue-at -` 尝试断点续传。
9. 新下载写入 `.part`,成功后原子 rename 到最终路径。
10. 成功下载后更新本地下载清单。
11. 记录最终文件大小、本次传输字节数、官方 hash 校验数和执行状态。
12. 非官方 URL 直接拒绝。
路径映射时会做分段清理,避免把不安全路径写进输出目录。
@@ -152,13 +175,46 @@
- `infrastructure/src/official_sync.rs`
### 3.7 自动更新闭环
`OfficialUpdateService` 是当前 Rust 侧的自动更新核心,正式命令入口是 `bat-official-sync`
流程是:
1. 显式执行 `--auto-discover` 或读取已审计 `server-info` 输入。
2. `--auto-discover` 先抓官方 launcher metadatametadata 未变时复用 `official-bootstrap-cache.json` 中的 `GameMainConfig` 摘要,metadata 变化时临时下载官方 game zip 并重新解析。
3. 生成当前 v2 snapshot,记录 `app_version``connection_group``bundle_version``addressables_root`、endpoint URL、seed `.hash` 内容、`catalog_*.hash` marker、launcher metadata 摘要和 `GameMainConfig` 摘要。
4. 读取上一次成功同步写出的 snapshot。
5. 使用 `OfficialSyncPlan` 和扩展 snapshot diff 判断是否需要下载;URL 未变但 `.hash` / marker 内容变化也会触发更新。
6. 远端无变化时执行本地 download manifest audit,检查路径、size 和 BLAKE3。
7. 远端变化或本地 audit 发现 repair_needed 时生成 pull plan,下载并校验官方 URL。
8. 下载成功后写回新的 snapshot。
该入口不安装、不执行官方启动器,也不读取生产外的本地客户端目录。Rust 正式 binary 支持 `--watch` 常驻模式,默认每 1 小时执行一次检查;远端和本地一致时静默等待下次检查,不一致时自动下载或 repair。单次运行仍保留为核心幂等路径,systemd service、容器或 Go 进程可以只负责守护该常驻进程;cron/systemd timer 调单次模式只是可选集成方式。项目是否热更新、热重载或重启进程,由上层业务集成决定。
对应实现主要在:
- `infrastructure/src/official_update.rs`
- `infrastructure/src/bin/bat_official_sync.rs`
- `infrastructure/examples/official_update_check.rs`(历史/开发入口)
## 4. 官方 bootstrap 与用户流程
当前已经提供的官方用户流程是:
当前已经提供的官方用户流程分两类。
Linux 生产路径:
1. 显式执行 `--auto-discover`,或提供已审计的官方 metadata snapshot。
2. `official_pull_plan` 依据官方 `server-info`、catalog 和 verified platforms 生成全量拉取计划。
3. `bat-official-sync` 对比上次 snapshot 和远端 `.hash` marker;远端无变化时 audit 本地清单,有变化或本地损坏时下载、校验并落盘官方资源。
开发/审计辅助路径:
1. `official_launcher_bootstrap` 获取官方 launcher 信息。
2. `official_game_main_config` 从官方 ZIP 解出并解密 `GameMainConfig`
3. `official_pull_plan` 依据官方 `server-info`、catalog 和 verified platforms 生成全量拉取计划
3. 手动确认最新 PC metadata、`server-info` URL 和默认 connection group
自动发现路径和开发/审计辅助路径都只使用官方 HTTP 和临时目录,不安装或启动官方 launcher。
这些入口都只接受官方域名,不走 `bluearchive.cafe` 镜像链。
@@ -171,6 +227,12 @@
- verified inventory 会产出完整内容 URL 集
- pull plan 会同时包含 discovery URLs 和 content URLs
- 全量样本下是 `2` 个 discovery URL + `5` 个内容 URL = `7` 个 URL
- `OfficialUpdateService` 能持久化 v2 snapshot,并在远端 marker 内容变化时触发下载决策
- `bat-official-sync` 输出稳定 JSON report,支持 `--watch --interval 1h` 常驻运行,非 dry-run 使用 `.official-sync.lock` 防止并发写状态目录
- `OfficialUpdateService` 能读写 `official-bootstrap-cache.json`,并支持默认开启的 `audit_local` / `repair` CLI 行为
- 下载层能在本地文件 size/BLAKE3/path 或 manifest 不匹配时重新下载
- 官方 seed `.hash` mismatch 会导致下载失败,而不是降级为本地 BLAKE3 猜测
- 非官方 URL 会在 fetch/download 入口被拒绝
相关验证主要来自:
@@ -178,6 +240,7 @@
- `cargo test -p bat-infrastructure`
- `cargo test -p bat-adapters --examples`
- `cargo test -p bat-infrastructure --examples`
- `cargo test -p bat-infrastructure --bin bat-official-sync -- --nocapture`
- `cargo clippy -p bat-adapters -- -D warnings`
- `cargo clippy -p bat-infrastructure -- -D warnings`
+125 -23
View File
@@ -13,26 +13,23 @@
- `macOS`
- `bluearchive.cafe` 或其他镜像域名
- 任何本地客户端目录
- 任何已安装的官方启动器或 Windows 客户端
## 1. 当前流程
运行时链路只走官方日服:
Linux 生产运行时链路只走官方日服 HTTP 资源,不安装、不启动、不依赖官方启动器二进制
1. 请求官方 launcher API
2. 官方 launcher manifest 链路得到最新游戏包 ZIP
3. 解包 `resources.assets`
4. 解密 `GameMainConfig`
5. `GameMainConfig` 自动读取 `server-info` URL 和默认 `connection-group`
6. 请求官方 `server-info`
7. 生成 Windows + Android 的官方资源 discovery 端点。
8. 拉取 seed catalog,生成完整官方 pull plan。
9. dry-run 只输出 URL;非 dry-run 下载全部官方 URL。
1. 显式执行 `--auto-discover`,通过官方 HTTP metadata 自动发现 `app-version``server-info` URL 和默认 `connection-group`
2. 请求官方 `server-info`
3. 生成 Windows + Android 的官方资源 discovery 端点
4. 拉取 seed catalog,生成完整官方 pull plan
5. dry-run 只输出 URL;非 dry-run 下载全部官方 URL
`--server-info-file``--server-info-path` 都不是硬依赖
`--auto-discover` 会下载官方 metadata 所需的临时包并解析 `GameMainConfig`,但不会安装官方启动器,也不会执行官方启动器进程。`--launcher-bootstrap` 只是旧命名兼容别名,新流程不要再推荐使用
## 2. 先做 launcher bootstrap
## 2. 可选 metadata 审计
先确认 launcher API 和官方 ZIP 链路正常
如需单独审计官方 metadata API 和官方 ZIP 链路,可以手动运行
```bash
cargo run -p bat-infrastructure --example official_launcher_bootstrap -- \
@@ -54,17 +51,17 @@ cargo run -p bat-infrastructure --example official_launcher_bootstrap -- \
## 3. 先做 dry-run
推荐默认流程是不提供本地 `server-info` 文件,也不提供本地客户端目录
推荐开发和生产自动化的默认流程是显式打开 `--auto-discover`
```bash
cargo run -p bat-infrastructure --example official_pull_plan -- \
--launcher-bootstrap \
--auto-discover \
--platforms Windows,Android \
--output /tmp/ba-official-pull \
--dry-run
```
如果你已经有官方 `server-info` 文件,也可以显式传入
如果你要复现某次已审计的 metadata snapshot,也可以显式传入官方 `server-info` 文件
```bash
cargo run -p bat-infrastructure --example official_pull_plan -- \
@@ -76,6 +73,18 @@ cargo run -p bat-infrastructure --example official_pull_plan -- \
--dry-run
```
如果你已经把官方 `server-info` JSON 存成只读本地文件,也可以使用:
```bash
cargo run -p bat-infrastructure --example official_pull_plan -- \
--server-info-path /path/to/server-info.json \
--connection-group Prod-Audit \
--app-version 1.70.0 \
--platforms Windows,Android \
--output /tmp/ba-official-pull \
--dry-run
```
检查输出时,重点看:
- `platforms=[Windows, Android]`
@@ -89,7 +98,7 @@ cargo run -p bat-infrastructure --example official_pull_plan -- \
```bash
cargo run -p bat-infrastructure --example official_pull_plan -- \
--launcher-bootstrap \
--auto-discover \
--platforms Windows,Android \
--output /tmp/ba-official-pull
```
@@ -98,28 +107,121 @@ cargo run -p bat-infrastructure --example official_pull_plan -- \
- 只接受官方 URL
- 下载完整官方资源集合
- 下载成功后在输出目录维护 `official-download-manifest.json`
- 已存在目标文件只有在本地下载清单中的 size 和 BLAKE3 校验通过时才会跳过
- `TableCatalog.bytes``BundlePackingInfo.bytes``MediaCatalog.bytes` 会用官方 `.hash` 做强校验;该 `.hash``xxHash32(seed=0)` 的十进制文本
- `catalog_*.hash` 是 Unity Addressables/SBP 写出的 catalog 变更标记,来源是 `HashingMethods.Calculate(json/bin catalog)` 生成的 `Hash128` 文本;它不是 seed catalog 的 `xxHash32` 规则,目前不作为 zip/JSON 内容强校验
- 存在 `.part` 临时文件时会尝试断点续传
- 新下载先写 `.part`,成功后再替换为最终文件
- 把结果写入 `--output`
## 5. 例外输入
## 5. 自动更新检查
如果必须使用本地 `server-info`,只接受
正式自动更新入口是 `bat-official-sync`。它会保存上一次成功同步的 snapshot,下次运行时先自动发现当前官方 metadata,再和 snapshot 对比
- 每轮都会先拉取轻量官方 metadata 和 `.hash` marker。
- URL 没变但 `.hash` / marker 内容变更时,也会判定为需要更新。
- 远端无变化时,默认执行本地 `official-download-manifest.json` audit。
- 本地文件缺失、路径不一致、size 不一致或 BLAKE3 不一致时,默认进入 repair 并重下必要文件。
- 远端和本地都一致:单次模式输出 `update_status=up_to_date`,watch 模式默认静默并等待下次检查。
- 有远端变化或本地 repair:生成 pull plan,下载完整官方资源,成功后更新 snapshot。
- `--dry-run`:只报告本次是否会下载,不写 snapshot;如果 cache miss,也不会写入新的 bootstrap cache。
- `--dry-run --plan`:除更新判断外,还会解析 seed catalog 并打印完整下载 URL。
- 真实更新会输出 `downloaded_count``resumed_count``skipped_count``transferred_bytes``official_seed_hash_verified_count`
- 校验报告分层输出 `official_seed_hash_verified_count``local_manifest_verified_count``addressables_marker_checked_count``unverified_marker_count`
- 下载阶段复用同一套本地清单和 `.part` 续传逻辑;没有清单或校验不匹配的文件会重新下载。
状态文件默认位于 `--output` 下:
- `official-sync-snapshot.json`:上一次成功同步的 v2 snapshot,包含 app version、connection group、bundle version、addressables root、endpoint URL、官方 seed `.hash` 内容、Addressables `catalog_*.hash` marker、launcher metadata 摘要和 `GameMainConfig` 摘要。
- `official-bootstrap-cache.json``--auto-discover``GameMainConfig` 解析缓存。launcher metadata 未变时复用缓存;metadata 变化时才通过官方 HTTP 下载必要 game zip 到临时目录解析。
- `official-download-manifest.json`:本地下载强校验清单,记录 URL、相对路径、size 和 BLAKE3。
先 dry-run
```bash
cargo run -p bat-infrastructure --bin bat-official-sync -- \
--auto-discover \
--platforms Windows,Android \
--output /tmp/ba-official-update \
--snapshot /tmp/ba-official-update/official-sync-snapshot.json \
--dry-run
```
如果需要在 dry-run 阶段审阅完整下载 URL,加 `--plan`
```bash
cargo run -p bat-infrastructure --bin bat-official-sync -- \
--auto-discover \
--platforms Windows,Android \
--output /tmp/ba-official-update \
--snapshot /tmp/ba-official-update/official-sync-snapshot.json \
--dry-run \
--plan
```
确认后执行真实更新:
```bash
cargo run -p bat-infrastructure --bin bat-official-sync -- \
--auto-discover \
--platforms Windows,Android \
--output /tmp/ba-official-update \
--snapshot /tmp/ba-official-update/official-sync-snapshot.json
```
Rust 常驻更新模式默认每 1 小时执行一次检查,符合则静默,不符合则自动拉取/repair 并输出 JSON report
```bash
cargo run -p bat-infrastructure --bin bat-official-sync -- \
--auto-discover \
--platforms Windows,Android \
--output /tmp/ba-official-update \
--snapshot /tmp/ba-official-update/official-sync-snapshot.json \
--watch
```
如需调整间隔:
```bash
cargo run -p bat-infrastructure --bin bat-official-sync -- \
--auto-discover \
--platforms Windows,Android \
--output /tmp/ba-official-update \
--watch \
--interval 30m
```
命令成功时 stdout 输出稳定 JSON report;错误时 stderr 输出 JSON error。普通错误 exit `1`,状态目录锁冲突 exit `75`
生产可以直接运行 `--watch`,也可以用 systemd service、容器或 Go 进程守护它。cron/systemd timer 仍可调用单次模式,但不再是 Rust 自动更新的唯一方式。项目是否热更新、热重载或重启进程,由上层业务集成决定。生产目录应使用独立输出目录,不要指向现有客户端或人工维护的资源目录。非 dry-run 每轮会创建 `--output/.official-sync.lock`,防止并发写同一状态目录。
需要只做探测时可以加 `--dry-run`。需要关闭本地 audit 或 repair 时可以显式使用 `--no-audit-local``--no-repair`,但生产同步默认应保持开启。
## 6. 例外输入
可接受的 `server-info` 输入是:
- `--auto-discover`
- `--server-info-url <官方 URL>`
- `--server-info-file <官方文件名>`
- `--server-info-path <本地官方 JSON>`
但这两项不再是主流程依赖
如果没有显式 `server-info` 输入,必须手动加 `--auto-discover` 才会走官方 metadata / `GameMainConfig` 辅助发现链路。不要在 Linux 生产任务里依赖已安装启动器或本地客户端目录
## 6. 代码入口
## 7. 代码入口
当前可用的用户入口:
- `infrastructure/examples/official_launcher_bootstrap.rs`
- `infrastructure/examples/official_pull_plan.rs`
- `infrastructure/src/bin/bat_official_sync.rs`
- `infrastructure/examples/official_update_check.rs`(历史/开发入口;生产优先使用 `bat-official-sync`
- `adapters/examples/yostar_jp_client_bootstrap.rs`
- `adapters/examples/yostar_jp_discovery.rs`
- `adapters/examples/yostar_jp_inventory.rs`
## 7. 验证
## 8. 验证
推荐验证命令:
@@ -128,5 +230,5 @@ cargo test -p bat-adapters
cargo test -p bat-infrastructure
cargo test -p bat-infrastructure --example official_launcher_bootstrap -- --nocapture
cargo test -p bat-infrastructure --example official_pull_plan -- --nocapture
cargo test -p bat-infrastructure --bin bat-official-sync -- --nocapture
```
+3 -1
View File
@@ -16,7 +16,9 @@
已确认可用的内容:
- `bat-cas-engine` 的 CAS V1 已完成。
- `bat-adapters` 的官方日服 URL 规则官方 launcher bootstrap、官方 GameMainConfig bootstrap、官方 pull plan 已可用。
- `bat-adapters` 的官方日服 URL 规则官方 pull plan / update check 已可用。
- Linux 生产资源拉取路径已明确为显式 `--auto-discover` 或已审计 metadata snapshot,不安装、不执行官方启动器。
- 官方 launcher bootstrap、官方 GameMainConfig bootstrap 保留为底层显式开发/审计辅助路径。
- `bat-infrastructure` 的官方 bootstrap / pull integration 测试已通过。
- 官方资源链路已经明确只接受官方 host,不依赖 `bluearchive.cafe` 镜像。