mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 07:24:55 +08:00
439 lines
26 KiB
Markdown
439 lines
26 KiB
Markdown
# BlueArchiveToolkit 用户指南
|
||
|
||
本指南面向 `bat` 官方资源同步二进制的使用者,覆盖:命令、选项、退出码、运行时行为,以及统一错误码参考。
|
||
|
||
- 权威运行/部署说明另见 `docs/guides/official-resource-test-pull.md` 和 `docs/guides/deployment.md`。
|
||
- 本文档中的命令、选项以 `bat --help` 为准;错误码以 `core/src/error_code.rs` 的码表为准。
|
||
|
||
---
|
||
|
||
## 1. 概览
|
||
|
||
`bat` 是 Linux 上官方日服(Yostar JP)资源同步的正式入口。它可以:
|
||
|
||
- `--auto-discover` 从官方 HTTP metadata 解析 `GameMainConfig`,自动获得 app-version、连接组和 server-info,不安装、不启动官方启动器;已发布 release 会保存 `official-launcher-bootstrap.json`。
|
||
- 生成官方全量 pull plan、执行真实下载,维护 release 内的下载 manifest,并做 size + BLAKE3 复用校验、官方 seed `.hash`(标准 xxHash32(seed=0))强校验、ZIP 结构校验。
|
||
- 断点续传、失败分类重试、下载 quarantine、本地 manifest audit/repair。
|
||
- 原子发布:先写 `.staging/<id>`,校验通过后发布 `versions/<id>` 并原子切换 `current` symlink。
|
||
- 常驻运行(`--watch`)或后台化(`--daemon`),通过 `bat.sock` Unix socket JSON-RPC 控制。
|
||
|
||
### 运行形态
|
||
|
||
```bash
|
||
# 一次性 dry-run(不写状态)
|
||
bat --auto-discover --dry-run
|
||
|
||
# 前台常驻
|
||
bat --auto-discover --watch --output /var/lib/bluearchive-toolkit/official
|
||
|
||
# 后台守护
|
||
bat --auto-discover --daemon --output /var/lib/bluearchive-toolkit/official
|
||
```
|
||
|
||
带凭据的代理**推荐用环境变量**(凭据不进命令行/argv/状态文件):
|
||
|
||
```bash
|
||
HTTPS_PROXY=http://user:pass@127.0.0.1:7890 bat --auto-discover --daemon
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 命令
|
||
|
||
无子命令时执行一次性同步(或配合 `--watch`/`--daemon`)。子命令如下:
|
||
|
||
| 命令 | 说明 |
|
||
|---|---|
|
||
| `refresh` | 执行一次更新检查;若有 live daemon,则通过 RPC 请求其刷新 |
|
||
| `verify` | 校验远端计划、本地 manifest 和官方 seed hash(dry-run + 审计当前 release) |
|
||
| `repair` | 重新下载本地校验失败的资源 |
|
||
| `status` | 显示 daemon 状态 |
|
||
| `stop` | 停止 daemon |
|
||
| `restart` | 重启 daemon;未显式传参时复用保存的参数 |
|
||
| `reload` | 请求 daemon 重新自动发现并强制刷新 |
|
||
| `logs` | 显示 daemon 日志尾部(配合 `--tail`) |
|
||
| `doctor` | 运行时诊断(输出目录、状态目录、curl/unzip、代理、PID、socket、锁) |
|
||
| `clean-stable` | 清理 `.part`/`.tmp`/失效锁、PID、socket(daemon 运行中会拒绝执行) |
|
||
|
||
`status`/`stop`/`logs`/`reload` 和默认形态的 `refresh` 优先走 `bat.sock` JSON-RPC;socket 不可用时 `status`/`stop` 回退到 PID/状态文件兼容路径。
|
||
|
||
### bat-api 资源 bootstrap / 分发服务
|
||
|
||
`bat-api` 是 Go 侧正式服务入口,用于给客户端、补丁器或上层工具提供启动前资源入口和 CDN 形态只读分发。它不负责自动发现、下载、校验或发布资源;这些长期状态由 Rust `bat` / daemon 持有。
|
||
|
||
生产拓扑上,`bat-api` 基本应与 Rust `bat` 运行在同一台服务器、同一容器或同一共享文件系统环境。当前可读资源目录不在 `bat-api` 配置里写死,而是由 `bat.sock` RPC 的 `catalog.status` / `resource.manifest` 返回 `resource_root`。
|
||
|
||
推荐运行关系:
|
||
|
||
```bash
|
||
# 先让 Rust bat 生产并维护 release
|
||
bat --auto-discover --daemon \
|
||
--output /var/lib/bluearchive-toolkit/official \
|
||
--state-dir /var/lib/bluearchive-toolkit/daemon-state
|
||
|
||
# 再启动 bat-api 读取同一个 daemon socket
|
||
bat-api \
|
||
--listen :18080 \
|
||
--public-base-url http://127.0.0.1:18080 \
|
||
--socket /var/lib/bluearchive-toolkit/daemon-state/bat.sock \
|
||
--refresh-interval 1m
|
||
```
|
||
|
||
测试、fixture 或应急只读诊断场景可用 `--resource-root <DIR>` 直接指向已发布 release 根;生产默认应通过 `--socket` / `BAT_API_SOCKET` 从 `bat.sock` 发现当前版本。`bat.sock` 不应暴露到公网;对外发布时只暴露 `bat-api` HTTP,并把 `--public-base-url` 设为客户端实际访问的 HTTPS 根。
|
||
|
||
开发环境不能本地全量运行 `bat` 时,用 fixture 验证 Go 服务面即可:
|
||
|
||
```bash
|
||
BAT_API_SKIP_ENV_FILE=1 go run ./cmd/bat-api \
|
||
--listen 127.0.0.1:18080 \
|
||
--public-base-url http://127.0.0.1:18080 \
|
||
--resource-root internal/api/testdata/release \
|
||
--refresh-interval 0
|
||
```
|
||
|
||
常用接口:
|
||
|
||
| 接口 | 说明 |
|
||
|---|---|
|
||
| `GET /healthz` | 服务存活、RPC 可用性、release ready 状态和最近一次 RPC refresh 诊断 |
|
||
| `GET/HEAD /readyz` | release 就绪检查;当前无可分发 release 时返回 `503` |
|
||
| `GET /v1/bootstrap` | 启动前资源入口:`bat` RPC 健康、release 摘要、server-info URL、client-patch base、改写后的 Addressables root |
|
||
| `GET /v1/launcher/bootstrap` | 启动器资源引导聚合视图:release、launcher metadata、GameMainConfig 摘要和资源 URL |
|
||
| `GET /api/launcher/game/config` | launcher 资源 metadata 兼容 envelope;字段来自 Rust `bat` 已发布 snapshot/RPC |
|
||
| `GET /api/launcher/game/config/json` | launcher 形状的资源引导 JSON URL;不会返回完整 PC package update manifest |
|
||
| `GET /api/launcher/advanced/game/download/cdn` | launcher 形状的 CDN 配置;返回当前 `--public-base-url`,用于资源引导 |
|
||
| `GET /api-launcher-jp.yo-star.com/api/launcher/...` | 与上面 `/api/launcher/...` 等价,便于反代或 hosts 映射保持官方 host 形状 |
|
||
| `GET /v1/release` | 当前 release 摘要 |
|
||
| `GET /v1/resources?offset=0&limit=100` | 当前 manifest 索引分页 |
|
||
| `GET /v1/server-info` | 调试用 server-info JSON,只改 `AddressablesCatalogUrlRoot` |
|
||
| `GET /yostar-serverinfo.bluearchiveyostar.com/server-info.json` | 官方 host/path 形态的 server-info |
|
||
| `GET/HEAD /prod-clientpatch.bluearchiveyostar.com/...` | 官方 CDN path 形态资源字节 |
|
||
| `GET /openapi.yaml` | bat-api OpenAPI 文档 |
|
||
| `GET /admin/` | 管理控制入口与允许操作列表 |
|
||
| `POST /admin/control/{action}` | 经白名单转发 Rust `bat` 控制请求;见下文 |
|
||
|
||
launcher 兼容端点只服务启动前资源发现。它们复用 Rust `bat` snapshot 中的 `launcher_metadata` 和 `game_main_config_bootstrap`,显式标记 `scope=resource_bootstrap_only` / `package_update_manifest=false`。`bat-api` 不下载 launcher 包,不生成官方 PC package update manifest,也不仿造登录、账号、网关、鉴权或游戏业务协议。
|
||
|
||
生产面对玩家分发时,应启用 HTTP token 鉴权、限流和访问日志:
|
||
|
||
- `BAT_API_AUTH_TOKEN`:启用 `Authorization: Bearer <token>`、`X-BAT-Token` 或 query fallback 鉴权;token 推荐由 secret manager 或进程环境提供,不建议写入提交文件。`/admin/control/*` 需要此 token。
|
||
- `BAT_API_AUTH_QUERY_PARAM`:query fallback 参数名,默认 `bat_token`;兼容不能写 header 的客户端,访问日志不会记录 query。
|
||
- `BAT_API_AUTH_EXEMPT_PATHS`:逗号分隔的免鉴权 path 或 slash-prefix,例如 `/healthz,/readyz`。
|
||
- `BAT_API_RATE_LIMIT_RPS` / `BAT_API_RATE_LIMIT_BURST`:按客户端 IP 的进程内 token bucket 限流;边缘反代/CDN 仍应配置独立限流。
|
||
- `BAT_API_TRUST_PROXY_HEADERS`:只有反代已经清洗并覆盖 `X-Forwarded-For` / `X-Real-IP` 时才设为 `true`。
|
||
- `BAT_API_ACCESS_LOG`:结构化访问日志,记录 method/path/status/bytes/duration/client_ip/request_id/user_agent,不记录 query string。
|
||
- `BAT_API_MAX_RESOURCE_LIMIT`:`/v1/resources` 最大分页上限,默认 `1000`。
|
||
|
||
`POST /admin/control/{action}` 只转发固定白名单内的 Rust RPC,不是任意 RPC proxy:
|
||
|
||
| action | Rust RPC | 参数 | 返回 |
|
||
|---|---|---|---|
|
||
| `reload` | `daemon.reload` | 无 | `202` accepted |
|
||
| `refresh` | `daemon.refresh` | 可选 `{ "force": true }` | `202` accepted |
|
||
| `restart` | `daemon.restart` | 无 | `202` accepted |
|
||
| `sync` | `resource.sync` | 可选 `{ "force": true }` | `202` + task |
|
||
| `verify` | `resource.verify` | 无 | `202` + task |
|
||
| `repair` | `resource.repair` | 无 | `202` + task |
|
||
| `catalog-refresh` | `catalog.refresh` | 可选 `{ "force": true }` | `202` + task |
|
||
|
||
`stop`、`clean-stable`、patch 和 UnityFS 写入命令不会经 HTTP 暴露。
|
||
|
||
所有动态 JSON(bootstrap、health、ready、release、resources、launcher 兼容、server-info、OpenAPI、admin 和错误响应)显式返回 `Cache-Control: no-store`。资源字节 CDN path 仍返回长期 immutable cache header。
|
||
|
||
CDN path 只服务 manifest 索引内且磁盘存在、size 匹配的文件。响应支持 `GET`、`HEAD`、`Range`、条件请求、ETag、Last-Modified、Accept-Ranges 和长期缓存头;ETag 优先使用 manifest 中的 BLAKE3。`.hash` 以 `text/plain` 返回,其它未知扩展默认为 `application/octet-stream`。
|
||
|
||
`bat-api` 只改写资源相关入口:server-info 中的 `AddressablesCatalogUrlRoot` 会指向 `--public-base-url` 下的 `prod-clientpatch...` path;`ApiUrl`、`GatewayUrl`、登录、账号、网关和游戏业务协议不会被仿造或改写。
|
||
|
||
示例:
|
||
|
||
```bash
|
||
curl -fsS http://127.0.0.1:18080/v1/bootstrap
|
||
curl -fsS http://127.0.0.1:18080/v1/launcher/bootstrap
|
||
curl -fsS http://127.0.0.1:18080/api-launcher-jp.yo-star.com/api/launcher/game/config
|
||
curl -fsS http://127.0.0.1:18080/openapi.yaml
|
||
|
||
curl -fsS \
|
||
http://127.0.0.1:18080/prod-clientpatch.bluearchiveyostar.com/<root_token>/TableBundles/TableCatalog.hash
|
||
|
||
curl -i -H 'Range: bytes=0-1023' \
|
||
http://127.0.0.1:18080/prod-clientpatch.bluearchiveyostar.com/<root_token>/TableBundles/TableCatalog.bytes
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 选项
|
||
|
||
### 发现(Discovery)
|
||
|
||
| 选项 | 说明 |
|
||
|---|---|
|
||
| `--auto-discover` | 自动发现 app-version、server-info、连接组 |
|
||
| `--server-info-url <URL>` | 使用官方 server-info URL |
|
||
| `--server-info-file <NAME>` | 使用官方 server-info 文件名 |
|
||
| `--server-info-path <PATH>` | 使用本地 server-info JSON 文件 |
|
||
| `--app-version <VERSION>` | 覆盖 app 版本 |
|
||
| `--connection-group <NAME>` | 覆盖连接组 |
|
||
| `--launcher-version <VERSION>` | 启动器 metadata API 版本(默认 `1.7.2`) |
|
||
|
||
### 同步(Sync)
|
||
|
||
| 选项 | 说明 |
|
||
|---|---|
|
||
| `--platforms <LIST>` | 平台,如 `Windows,Android`(默认 `Windows,Android`) |
|
||
| `--output <DIR>` | 资源发布根目录(默认 `./bat-resources`) |
|
||
| `--snapshot <PATH>` | 覆盖 snapshot 路径(默认 `<output>/current/official-sync-snapshot.json`) |
|
||
| `--curl <PATH>` | curl 可执行文件(默认 `curl`) |
|
||
| `--proxy <URL\|auto\|none>` | curl 代理覆盖(默认 `auto`,从环境变量检测)。scheme 支持 http/https/socks4/socks4a/socks5/socks5h |
|
||
| `--no-proxy` | 强制直连 |
|
||
| `--unzip <PATH>` | unzip 可执行文件(默认 `unzip`) |
|
||
| `--dry-run` | 不写同步状态 |
|
||
| `--plan` | dry-run 时输出计划中的 URL |
|
||
| `--force` | 强制下载/刷新 |
|
||
| `--audit-local` / `--no-audit-local` | 启用/关闭本地 manifest 审计 |
|
||
| `--repair` / `--no-repair` | 启用/关闭自动修复 |
|
||
|
||
### 守护(Daemon)
|
||
|
||
| 选项 | 说明 |
|
||
|---|---|
|
||
| `--watch` | 前台常驻循环 |
|
||
| `--daemon` | 启动脱离终端的后台 watch 进程 |
|
||
| `--state-dir <DIR>` | 后台状态目录(默认 `/tmp/bat-pid`) |
|
||
| `--interval <DURATION>` | 正常检查周期(默认 `1h`) |
|
||
| `--error-retry <DURATION>` | 失败后重试周期(默认 `60s`) |
|
||
| `--quiet-up-to-date` / `--no-quiet-up-to-date` | 静默/总是打印 up-to-date 报告 |
|
||
| `--tail <N>` | `logs` 命令返回的日志行数(默认 `200`) |
|
||
|
||
### 输出(Output)
|
||
|
||
| 选项 | 说明 |
|
||
|---|---|
|
||
| `--human` | 人类可读输出(默认) |
|
||
| `--json` | 面向脚本的稳定 JSON 输出 |
|
||
| `--progress` / `--no-progress` | 启用/关闭 stderr 进度日志 |
|
||
| `--banner` / `--no-banner` | 启用/关闭启动横幅 |
|
||
| `-h`, `--help` | 显示帮助 |
|
||
|
||
### 默认值与运行时行为
|
||
|
||
- 平台:`Windows,Android`。
|
||
- 资源输出:`./bat-resources`(`current` → `versions/<id>`、`.staging/<id>`;自动发现 release 下包含 `official-launcher-bootstrap.json`,维护期 pending 证据位于发布根 `official-launcher-bootstrap.pending.json`)。
|
||
- 后台状态目录:`/tmp/bat-pid`(`bat.sock`、`bat.pid`、`bat-status.json`、`bat-daemon.log`、`bat-events.jsonl`、任务历史 `bat-tasks.json`、短生命周期 `bat-control.lock`;代理凭据在 `bat-proxy.secret`,`0600`)。
|
||
- 强制刷新:每天北京时间(UTC+8)`03:00`、`16:00`、`18:00` 各一次。
|
||
- 状态类文件默认 `0600` 权限,读写不跟随 symlink。
|
||
|
||
### 配置文件(`.env`,无参启动)
|
||
|
||
`bat` 首次启动时会在**二进制所在目录**释放一个 `.env` 配置模板(`0600` 权限,已存在则不动)。之后每次启动自动加载该文件,把其中的键作为进程环境变量(不覆盖已存在的环境变量),因此编辑 `.env` 后直接运行 `bat`(无参数)即可按配置启动。
|
||
|
||
- 优先级:**命令行参数 > 进程环境变量 > `.env` > 内置默认值**。
|
||
- 语法:每行 `KEY=VALUE`;`#` 开头为注释;值两侧成对引号会剥除;空值视为未设置。
|
||
- 支持的键:`BAT_OUTPUT`、`BAT_STATE_DIR`、`BAT_AUTO_DISCOVER`、`BAT_WATCH`、`BAT_DAEMON`、`BAT_PROXY`、`BAT_NO_PROXY`、`BAT_INTERVAL_SECONDS`、`BAT_ERROR_RETRY_SECONDS`、`BAT_APP_VERSION`、`BAT_CONNECTION_GROUP`、`BAT_LAUNCHER_VERSION`、`BAT_PLATFORMS`、`BAT_CURL`、`BAT_UNZIP`、`BAT_JSON`、`BAT_QUIET_UP_TO_DATE`;也可以直接写 `HTTPS_PROXY` 等通用环境变量(走现有代理自动检测)。布尔值支持 `1/0/true/false/yes/no/on/off`。
|
||
- `BAT_WATCH` / `BAT_DAEMON` 只对无子命令的 `bat` 生效(两者同时为 `1` 时 daemon 优先);命令行显式传入 `--watch` / `--daemon` / `--dry-run` 时 `.env` 的模式开关让位。`status` / `verify` 等子命令不受它们影响。
|
||
- `BAT_REDIS_URL` / `BAT_REDIS_PASSWORD` 为**预留键**:Redis 任务后端尚未接入,当前任务历史持久化在 `<state-dir>/bat-tasks.json`。
|
||
- 设 `BAT_SKIP_ENV_FILE=1` 可让 `bat` 完全跳过 `.env` 的生成与加载。
|
||
|
||
---
|
||
|
||
## 4. 退出码
|
||
|
||
| 退出码 | 含义 |
|
||
|---|---|
|
||
| `0` | 成功;`verify`/`doctor` 检查通过 |
|
||
| `1` | 普通错误 |
|
||
| `75` | 资源目录锁冲突(有 live daemon 正在管理同一目录,或 `.official-sync.lock` 被占用) |
|
||
|
||
`verify` 或 `doctor` 发现问题也返回非 0。`--json` 模式下错误以 JSON 写到 stderr。
|
||
|
||
---
|
||
|
||
## 5. 错误码参考
|
||
|
||
`bat` 使用一套稳定的数字错误码,作为 CLI、daemon RPC 和结构化日志的公共错误契约。
|
||
|
||
- **格式**:`BAT-ERR-<域 3 位><序号 3 位>`,共 6 位,例如 `BAT-ERR-300012`。
|
||
- **域**:错误码首位按百位分大类。
|
||
- **承载结构**(RPC envelope 的 `error` 字段、`--json` 输出、`bat-events.jsonl` 一致):
|
||
|
||
```json
|
||
"error": {
|
||
"code": "BAT-ERR-310001",
|
||
"kind": "proxy_failure",
|
||
"domain": "network",
|
||
"location": "official-sync.download.pull_one",
|
||
"message": "代理返回 407 认证失败",
|
||
"retryable": false
|
||
}
|
||
```
|
||
|
||
`location` 是稳定的「组件·操作」标签(跟随语义、不随行号漂移)。`retryable` 是该类错误的默认可重试性。
|
||
|
||
> 说明:错误码模型(`core/src/error_code.rs`)已建立并作为公共契约;下载、launcher/metadata、server-info/marker、配置校验、任务/RPC 等主要链路已接入该码表。剩余未实现命名空间和后续引擎能力继续按本表扩展。
|
||
|
||
### 域一览
|
||
|
||
| 域 | 区间 | 含义 |
|
||
|---|---|---|
|
||
| input | `1xxxxx` | 输入/配置:CLI 参数、配置校验、代理配置 |
|
||
| path_security | `2xxxxx` | 路径/安全边界:危险目录、路径逃逸、symlink、权限 |
|
||
| network | `3xxxxx` | 网络/下载:HTTP/网络错误、代理故障、重试耗尽、quarantine |
|
||
| integrity | `4xxxxx` | 校验/完整性:BLAKE3、官方 seed hash、size、ZIP 结构 |
|
||
| publish_storage | `5xxxxx` | 发布/版本状态/存储:staging、原子发布、version-state、锁、CAS |
|
||
| parse | `6xxxxx` | 解析/适配:manifest、UnityFS、GameMainConfig |
|
||
| task_rpc | `7xxxxx` | 任务/RPC:未知方法、参数非法、未实现、任务不存在 |
|
||
| internal | `9xxxxx` | 内部/未知:兜底 |
|
||
|
||
### 码表
|
||
|
||
| 码 | kind | 可重试 | 含义 |
|
||
|---|---|:---:|---|
|
||
| `BAT-ERR-100001` | missing_app_version | 否 | 缺少应用版本(未传 `--app-version` 且未启用 `--auto-discover`) |
|
||
| `BAT-ERR-100002` | missing_connection_group | 否 | 缺少连接组 |
|
||
| `BAT-ERR-100003` | missing_server_info_source | 否 | 缺少服务器信息来源 |
|
||
| `BAT-ERR-100004` | invalid_proxy_scheme | 否 | 代理 URL scheme 不受支持 |
|
||
| `BAT-ERR-100010` | invalid_argument | 否 | 命令行参数无效 |
|
||
| `BAT-ERR-200001` | dangerous_output_root | 否 | 输出目录被判定为危险路径 |
|
||
| `BAT-ERR-200002` | path_escape | 否 | 路径逃逸出允许根目录 |
|
||
| `BAT-ERR-200003` | symlink_rejected | 否 | 目标不允许是 symlink 或路径组件含 symlink |
|
||
| `BAT-ERR-200004` | file_permission | 否 | 文件权限或模式错误 |
|
||
| `BAT-ERR-300001` | http_forbidden | 否 | HTTP 403 |
|
||
| `BAT-ERR-300002` | http_not_found | 否 | HTTP 404 |
|
||
| `BAT-ERR-300003` | http_client_error | 否 | HTTP 其它 4xx |
|
||
| `BAT-ERR-300004` | http_too_many_requests | 是 | HTTP 429 / 请求过多 |
|
||
| `BAT-ERR-300005` | http_server_error | 是 | HTTP 5xx |
|
||
| `BAT-ERR-300010` | network_dns | 是 | DNS 解析失败 |
|
||
| `BAT-ERR-300011` | network_connect | 是 | 连接失败 |
|
||
| `BAT-ERR-300012` | network_timeout | 是 | 超时 |
|
||
| `BAT-ERR-300013` | network_tls | 是 | TLS 失败 |
|
||
| `BAT-ERR-300014` | network_interrupted | 是 | 传输中断 |
|
||
| `BAT-ERR-300015` | network_other | 是 | 其它网络错误 |
|
||
| `BAT-ERR-300020` | retry_exhausted | 否 | 下载重试次数耗尽 |
|
||
| `BAT-ERR-300021` | quarantined | 否 | URL 因反复失败进入 quarantine |
|
||
| `BAT-ERR-300030` | non_official_url | 否 | URL 不是官方 host(被拒绝) |
|
||
| `BAT-ERR-300031` | launcher_api_rejected | 否 | 官方启动器 API 返回非 200 业务码(版本/鉴权被拒等) |
|
||
| `BAT-ERR-310001` | proxy_failure | 否 | 代理自身故障(认证/解析/连接代理失败) |
|
||
| `BAT-ERR-400001` | blake3_mismatch | 否 | 本地 BLAKE3 与 manifest 不符 |
|
||
| `BAT-ERR-400002` | official_hash_mismatch | 否 | 官方 seed `.hash`(xxHash32)校验不符 |
|
||
| `BAT-ERR-400003` | size_mismatch | 否 | 文件大小与 manifest 不符 |
|
||
| `BAT-ERR-400004` | zip_structure_invalid | 否 | ZIP 结构无效 |
|
||
| `BAT-ERR-500001` | resource_locked | 否 | 资源目录锁冲突(对应退出码 75) |
|
||
| `BAT-ERR-500002` | staging_prepare_failed | 否 | staging 准备失败 |
|
||
| `BAT-ERR-500003` | publish_failed | 否 | 原子发布失败 |
|
||
| `BAT-ERR-500004` | version_state_write_failed | 是 | 版本状态写入失败 |
|
||
| `BAT-ERR-500010` | cas_hash_mismatch | 否 | CAS 对象 Hash 不匹配 |
|
||
| `BAT-ERR-500011` | cas_object_not_found | 否 | CAS 对象不存在 |
|
||
| `BAT-ERR-500012` | cas_reference_underflow | 否 | CAS 引用计数下溢 |
|
||
| `BAT-ERR-500013` | cas_database | 否 | CAS 元数据库错误 |
|
||
| `BAT-ERR-600001` | manifest_parse_failed | 否 | Manifest / Addressables catalog 解析失败 |
|
||
| `BAT-ERR-600002` | unityfs_parse_failed | 否 | UnityFS 解析失败 |
|
||
| `BAT-ERR-600003` | game_main_config_failed | 否 | GameMainConfig 解密/解析失败 |
|
||
| `BAT-ERR-600004` | launcher_response_invalid | 否 | 官方启动器链内容无效(API 响应、远端 manifest 或包内容无法解析/缺少必需内容) |
|
||
| `BAT-ERR-700001` | rpc_unknown_method | 否 | 未知 RPC 方法 |
|
||
| `BAT-ERR-700002` | rpc_invalid_params | 否 | RPC 参数无效 |
|
||
| `BAT-ERR-700003` | rpc_not_implemented | 否 | 方法/命名空间尚未实现 |
|
||
| `BAT-ERR-700004` | task_not_found | 否 | 任务不存在 |
|
||
| `BAT-ERR-700005` | task_interrupted | 否 | 任务因 daemon 停止/重启而中断 |
|
||
| `BAT-ERR-900001` | internal | 否 | 未归类的内部错误 |
|
||
|
||
新增错误码在 `core/src/error_code.rs` 的码表登记后,同步更新本表。
|
||
|
||
---
|
||
|
||
## 6. Daemon RPC 接口
|
||
|
||
稳定 contract 以 `docs/reference/rpc-backend-api.md` 为准,本节保留常用说明和命令行示例。
|
||
|
||
`bat --daemon` 在后台状态目录下创建 `bat.sock`(Unix socket),提供**换行分隔的 JSON-RPC 2.0** 控制面。CLI 的 `status`/`stop`/`logs`/`reload`/`refresh`/`repair` 优先走它;Go 服务层也应通过这个进程边界调用,而非 FFI 或执行 `bat` binary 后再解析 stdout。
|
||
|
||
### 传输与 envelope
|
||
|
||
- 请求:一行 JSON-RPC 2.0,`{"jsonrpc":"2.0","id":<n>,"method":"<ns>.<action>","params":{…}}`。
|
||
- 响应:JSON-RPC 2.0,应用层负载统一装入 `result` 的 envelope:
|
||
|
||
```json
|
||
{"jsonrpc":"2.0","id":1,"result":{
|
||
"ok": true,
|
||
"status": "ok",
|
||
"data": { … },
|
||
"request_id": "req-<pid>-<seq>"
|
||
}}
|
||
```
|
||
|
||
- `ok`:应用层成功与否。失败时 `ok=false`、`status="error"`、`error` 为 §5 的 `ApiError` 结构(含 `BAT-ERR` 码)。
|
||
- `status`:`ok` | `accepted`(长任务已入队) | `error`。
|
||
- `request_id`:进程内唯一请求 ID。
|
||
- 请求解析失败(畸形 JSON)走 JSON-RPC 顶层 `error`(如 `-32700`),不进 envelope。
|
||
|
||
### 方法命名空间
|
||
|
||
方法采用 `<namespace>.<action>`。`bat.*` 为兼容别名(解析为 `daemon.*`)。
|
||
|
||
| 方法 | 状态 | 说明 |
|
||
|---|---|---|
|
||
| `daemon.status` | ✅ | 后台状态快照 |
|
||
| `daemon.logs` | ✅ | 日志尾部(`params.tail`,默认 200) |
|
||
| `daemon.stop` | ✅ | 请求停止(`accepted`) |
|
||
| `daemon.reload` | ✅ | 请求重新发现并强制刷新(`accepted`) |
|
||
| `daemon.refresh` | ✅ | 请求刷新检查(`params.force`,`accepted`) |
|
||
| `daemon.restart` | ✅ | 启动 Rust lifecycle controller,并在响应后停止当前 daemon(`accepted`) |
|
||
| `daemon.doctor` | ✅ | 返回运行时诊断报告(只读,不清理、不重启) |
|
||
| `resource.state` | ✅ | 资源发布根 + 版本状态 + 上次同步结果 |
|
||
| `resource.sync` | ✅ | 触发同步任务(`params.force`),返回 `task_id` |
|
||
| `resource.verify` | ✅ | 触发校验任务(dry-run + audit),返回 `task_id` |
|
||
| `resource.repair` | ✅ | 触发本地 manifest 审计 + 修复任务,返回 `task_id`;不继承 `force` |
|
||
| `resource.manifest` / `resource.list` | ✅ | 当前版本下载 manifest 分页查询(`params.offset` 默认 0、`params.limit` 默认 100/上限 1000) |
|
||
| `catalog.status` | ✅ | 当前已发布版本的 catalog 概览(app/bundle 版本、addressables 根、端点与 marker 计数、launcher 元数据) |
|
||
| `catalog.versions` | ✅ | 版本历史:current / in_progress / previous / failed |
|
||
| `catalog.diff` | ✅ | 当前 snapshot 相对上一个可用版本的差异(base_delta + extended_delta + 变更端点 URL) |
|
||
| `catalog.refresh` | ✅ | 触发 catalog 更新检查任务(dry-run 计划,不下载;`params.force`),返回 `task_id` |
|
||
| `task.status` | ✅ | 查询任务(`params.task_id`) |
|
||
| `task.list` | ✅ | 列出全部任务(最新在前) |
|
||
| `task.cancel` | ✅ | 请求取消任务(`params.task_id`);协作式,在同步检查点生效 |
|
||
| `task.logs` | ✅ | 返回任务的进度日志(`params.task_id`,有界) |
|
||
| `daemon.clean-stable` / 发布级 `patch.*` / 未开放 `unityfs.*` / `task.create` | ⏳ | 已规划,返回 `BAT-ERR-700003`(not implemented);clean-stable 仍由 CLI 侧按进程生命周期显式执行,task.create 暂不开放通用任务入口 |
|
||
| 未知方法 | — | `BAT-ERR-700001`(unknown method) |
|
||
|
||
只读查询(`daemon.doctor` / `resource.state` / `resource.manifest` / `resource.list` / `catalog.status` / `catalog.versions` / `catalog.diff`)在尚无已发布版本或对应文件不存在时返回 `ok: true` 且 `data.available: false`(正常状态而非错误,便于调用方直接分支)。
|
||
|
||
### 任务模型
|
||
|
||
`resource.sync` / `resource.verify` / `resource.repair` / `catalog.refresh` 是**异步任务**:入队即返回 `{ "task_id": "task-<pid>-<seq>", "kind": "resource.sync" }`(`status: "accepted"`),实际执行由后台任务 worker 串行完成,通过 `task.status` / `task.list` 轮询。任务记录:
|
||
|
||
```json
|
||
{ "id": "task-1234-1", "kind": "resource.sync",
|
||
"status": "queued|running|succeeded|failed",
|
||
"stage": "download", "message": "…",
|
||
"created_at": …, "updated_at": …, "started_at": …, "finished_at": …,
|
||
"error": { … }, "result": { … } }
|
||
```
|
||
|
||
- `task.cancel` 请求取消:置任务的取消标志,worker 在下一个同步检查点中止,任务转为 `cancelled`(协作式,不硬杀正在执行的 curl)。
|
||
- 与后台 watch 循环的定时同步通过进程内锁互斥(任务等待而非失败)。
|
||
- 任务历史**持久化**在 `<state-dir>/bat-tasks.json`(版本化、`0600` 原子写):生命周期转换(入队/开始/结束)时落盘,进行中任务的 `stage`/`message`/日志以内存实时值为准、随下一次转换写入。daemon 重启后历史任务经 `task.status` / `task.list` / `task.logs` 仍可查;重启时仍处于 `queued`/`running` 的任务标记为 `failed`(错误码 `BAT-ERR-700005` task_interrupted)。文件损坏时改名 `bat-tasks.json.corrupt` 留证并从空历史开始。历史保留最近 64 条(运行中任务不裁剪)。
|
||
|
||
### 示例
|
||
|
||
```bash
|
||
# 触发同步任务并取回 task_id(socat 演示)
|
||
printf '{"jsonrpc":"2.0","id":1,"method":"resource.sync","params":{"force":true}}\n' \
|
||
| socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock
|
||
|
||
# 轮询任务
|
||
printf '{"jsonrpc":"2.0","id":2,"method":"task.status","params":{"task_id":"task-1234-1"}}\n' \
|
||
| socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock
|
||
|
||
# 查询当前 catalog 概览与版本历史
|
||
printf '{"jsonrpc":"2.0","id":3,"method":"catalog.status"}\n' \
|
||
| socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock
|
||
printf '{"jsonrpc":"2.0","id":4,"method":"catalog.versions"}\n' \
|
||
| socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock
|
||
|
||
# 分页读取当前版本的下载 manifest
|
||
printf '{"jsonrpc":"2.0","id":5,"method":"resource.manifest","params":{"offset":0,"limit":50}}\n' \
|
||
| socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock
|
||
|
||
# 触发本地资源审计+修复任务
|
||
printf '{"jsonrpc":"2.0","id":6,"method":"resource.repair"}\n' \
|
||
| socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock
|
||
```
|