feat: publish official resources atomically

Fixes #9

Fixes #11
This commit is contained in:
2026-07-14 00:10:39 +08:00
parent 45aba2fb2b
commit 2ff99ae9e3
10 changed files with 1055 additions and 63 deletions
+17 -11
View File
@@ -173,11 +173,13 @@ sudo install -d -o bat -g bat -m 0750 \
`/var/lib/bluearchive-toolkit/official/` 会保存:
- `official-sync-snapshot.json`
- `current`:指向当前可读 release 的 symlink
- `versions/<id>/official-sync-snapshot.json`
- `versions/<id>/official-download-manifest.json`
- `versions/<id>/...` 下载得到的官方资源文件
- `.staging/<id>`:下载和校验中的临时 release
- `official-bootstrap-cache.json`
- `official-download-manifest.json`
- `.official-sync.lock`
- 下载得到的官方资源文件
不要把输出目录设为:
@@ -228,11 +230,11 @@ sudo -u bat /opt/bluearchive-toolkit/bin/bat doctor \
--state-dir /run/bluearchive-toolkit
```
`--watch` 是 Rust 内部持久检查模式,正常情况下默认每 1 小时执行一次检查,并且每天北京时间(UTC+8)`03:00``16:00``18:00` 会强制执行一次自动刷新。固定时间刷新会中断普通 interval 的 sleep,该轮注入 `force=true`;如果失败,会按失败重试周期继续重试。远端和本地一致时默认静默;有远端变化或本地文件损坏时自动下载或 repair,并输出人类可读摘要。下载、发现或校验失败时默认 60 秒后重试,可显式加 `BAT_ERROR_RETRY=60s` 或调整 service `ExecStart`。默认平台是 `Windows,Android`,无需显式传 `--platforms`;需要覆盖时用 systemd drop-in 重写 `ExecStart`。默认资源目录是 `./bat-resources`,生产 service 显式使用 `/var/lib/bluearchive-toolkit/official`
`--watch` 是 Rust 内部持久检查模式,正常情况下默认每 1 小时执行一次检查,并且每天北京时间(UTC+8)`03:00``16:00``18:00` 会强制执行一次自动刷新。固定时间刷新会中断普通 interval 的 sleep,该轮注入 `force=true`;如果失败,会按失败重试周期继续重试。远端和本地一致时默认静默;有远端变化或本地文件损坏时自动下载或 repair,并输出人类可读摘要。下载、发现或校验失败时默认 60 秒后重试,可显式加 `BAT_ERROR_RETRY=60s` 或调整 service `ExecStart`。默认平台是 `Windows,Android`,无需显式传 `--platforms`;需要覆盖时用 systemd drop-in 重写 `ExecStart`。默认资源目录是 `./bat-resources`,生产 service 显式使用 `/var/lib/bluearchive-toolkit/official`生产读取方应读取 `/var/lib/bluearchive-toolkit/official/current`;同步中的文件只会进入 `.staging/<id>`,校验完成后才发布为 `versions/<id>` 并切换 `current`
### 可选模式:CLI 自托管 `--daemon`
不使用 systemd 时,可以直接后台运行。生产中不要使用默认 `/tmp/bat-pid`,建议使用持久状态目录,这样 `bat-daemon.log` 不会随 reboot 或 tmp 清理丢失:
不使用 systemd 时,可以直接后台运行。生产中不要使用默认 `/tmp/bat-pid`,建议使用持久状态目录,这样 `bat-daemon.log``bat-events.jsonl` 不会随 reboot 或 tmp 清理丢失:
```bash
sudo -u bat /opt/bluearchive-toolkit/bin/bat \
@@ -248,7 +250,7 @@ sudo -u bat /opt/bluearchive-toolkit/bin/bat reload --state-dir /var/lib/bluearc
sudo -u bat /opt/bluearchive-toolkit/bin/bat stop --state-dir /var/lib/bluearchive-toolkit/daemon-state
```
`--daemon` 会在 `--state-dir` 下创建 `bat.sock``bat.pid``bat-status.json``bat-daemon.log` 和短生命周期的 `bat-control.lock``bat.sock` 是 Unix socket JSON-RPC 控制通道;`status``stop``logs``reload` 和默认形态的 `refresh` 会优先连接 live daemon。PID、状态和日志文件保留为快照、诊断和 socket 不可用时的兼容路径;`bat-control.lock` 串行化控制命令,并能在 stale/corrupt 时由下一次控制命令或 `clean-stable` 恢复。`reload` 默认不会重启进程,而是让 watch 循环重新自动发现并强制刷新:空闲睡眠时立即唤醒,正在同步时排队到当前轮结束后执行;需要替换启动参数或 binary 时用 `restart`
`--daemon` 会在 `--state-dir` 下创建 `bat.sock``bat.pid``bat-status.json``bat-daemon.log``bat-events.jsonl` 和短生命周期的 `bat-control.lock``bat.sock` 是 Unix socket JSON-RPC 控制通道;`status``stop``logs``reload` 和默认形态的 `refresh` 会优先连接 live daemon。PID、状态和日志文件保留为快照、诊断和 socket 不可用时的兼容路径;`bat-events.jsonl` 是带轮转的结构化 JSONL 事件日志;`bat-status.json` 会暴露最后成功时间、下次检查时间、最后错误摘要和当前下载进度;`bat-control.lock` 串行化控制命令,并能在 stale/corrupt 时由下一次控制命令或 `clean-stable` 恢复。`reload` 默认不会重启进程,而是让 watch 循环重新自动发现并强制刷新:空闲睡眠时立即唤醒,正在同步时排队到当前轮结束后执行;需要替换启动参数或 binary 时用 `restart`
不要同时运行 systemd `--watch` 和 standalone `--daemon` 指向同一个 `--output`。二者都会被资源锁和 live daemon 互斥保护,但生产运维上应保持单一 owner。
@@ -257,14 +259,18 @@ sudo -u bat /opt/bluearchive-toolkit/bin/bat stop --state-dir /var/lib/bluearchi
systemd 模式:
- 进程日志:`journalctl -u bluearchive-toolkit-official-sync.service`
- 资源状态`/var/lib/bluearchive-toolkit/official/official-sync-snapshot.json`
- 下载 manifest`/var/lib/bluearchive-toolkit/official/official-download-manifest.json`
- 当前可读 release`/var/lib/bluearchive-toolkit/official/current`
- 资源状态`/var/lib/bluearchive-toolkit/official/current/official-sync-snapshot.json`
- 下载 manifest`/var/lib/bluearchive-toolkit/official/current/official-download-manifest.json`
- 历史 release`/var/lib/bluearchive-toolkit/official/versions/<id>`
- 同步 staging`/var/lib/bluearchive-toolkit/official/.staging/<id>`
- 资源写锁:`/var/lib/bluearchive-toolkit/official/.official-sync.lock`
- 运行期目录:`/run/bluearchive-toolkit/`
standalone `--daemon` 模式:
- 进程日志:`<state-dir>/bat-daemon.log`
- 结构化事件日志:`<state-dir>/bat-events.jsonl`
- RPC socket`<state-dir>/bat.sock`
- PID 文件:`<state-dir>/bat.pid`
- daemon 状态:`<state-dir>/bat-status.json`
@@ -327,14 +333,14 @@ sudo systemctl start bluearchive-toolkit-official-sync.service
journalctl -u bluearchive-toolkit-official-sync.service -n 100 --no-pager
```
当前官方资源同步的本地状态位于 `/var/lib/bluearchive-toolkit/official`。普通 binary 回滚不需要回滚资源目录;如果要测试可能改动 manifest/schema 的版本,先备份资源状态文件
当前官方资源同步的本地状态位于 `/var/lib/bluearchive-toolkit/official`,生产读取入口是 `/var/lib/bluearchive-toolkit/official/current`。普通 binary 回滚不需要回滚资源目录;如果要测试可能改动 manifest/schema 的版本,先备份当前 release 状态文件和 bootstrap cache
```bash
sudo -u bat tar -C /var/lib/bluearchive-toolkit/official \
-czf /var/lib/bluearchive-toolkit/official-state-backup.tgz \
official-sync-snapshot.json \
official-bootstrap-cache.json \
official-download-manifest.json
current/official-sync-snapshot.json \
current/official-download-manifest.json
```
如果业务层需要热更新、热重载或发布新资源,应该由上层服务在观察到 `--json` report 或 snapshot 变化后决定。Rust 同步进程只负责拉取、校验和维护本地状态。