Files
LanMountainDesktop/.trae/specs/plonds-client-service/spec.md
2026-06-02 09:27:08 +08:00

174 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PLONDS Client Service 独立化设计
> 日期2026-06-01
> 状态:设计中
## 1. 目标
PLONDS 在应用内必须作为独立服务存在,负责分发发现、下载、校验和本地包准备。它不是现有 Update 模块的 provider也不应把 S3/GitHub/source 选择逻辑混入 `LanMountainDesktop/Services/Update/`
最终边界:
- PLONDS 服务:寻找最新版本、选择下载源、下载 manifest 和包、校验文件、准备本地 staging。
- 安装程序/安装网关:只消费 PLONDS 已准备好的本地安装输入,执行增量安装或完整安装。
- UI只展示 PLONDS 服务和安装程序返回的状态;完整包也失败后才处理错误。
## 2. 当前耦合点
当前需要拆离的耦合点:
- `LanMountainDesktop/Services/Settings/SettingsDomainServices.cs`
- 直接持有 `PlondsStaticUpdateService``PlondsReleaseUpdateService`
-`CheckForUpdatesCoreAsync` 中把 PLONDS 和 GitHub Update fallback 逻辑混在一起
- `LanMountainDesktop/Services/Update/UpdateInstallGateway.cs`
- 直接判断 `UpdatePayloadKind.DeltaPlonds`
- 直接实例化 `PlondsUpdateApplier`
- `LanMountainDesktop/Services/Update/Plonds*.cs`
- PLONDS apply/parser/payload resolver 仍位于 Update 命名空间
## 3. Source 发现规则
PLONDS 客户端内置两个初始地址:
1. S3 上的 PLONDS manifest 地址
2. GitHub Release 上的 PLONDS manifest 地址
两个地址读取的是同一种 JSON 文件,当前文件名为 `PLONDS.json`。客户端每次检查增量更新时,会并行或顺序请求所有已知 source 的 `PLONDS.json`
### 3.1 Source 扩展
`PLONDS.json` 可以声明额外 source。客户端读取到额外 source 后,应把它们加入下一轮寻找列表。
建议 manifest 扩展字段:
```json
{
"sources": [
{
"id": "rainyun-s3",
"kind": "s3",
"manifestUrl": "https://example.com/plonds/1.2.3/PLONDS.json",
"priority": 100
},
{
"id": "github",
"kind": "github",
"manifestUrl": "https://github.com/owner/repo/releases/download/v1.2.3/PLONDS.json",
"priority": 50
}
]
}
```
规则:
- `sources` 为空或缺失时,只使用内置 S3 + GitHub。
- 新 source 不覆盖内置 source除非 `id` 相同。
- source 列表需要去重,按 `id``manifestUrl` 双重去重。
- source 持久化到 PLONDS 自己的配置/缓存,不写入 Update 设置。
## 4. 版本选择规则
如果多个 source 返回的版本不一致,客户端选择 `currentVersion` 最高的 manifest。
规则:
- 版本解析使用 `Version` 语义,忽略前导 `v`
- 版本相同时,优先选择下载可用性更高的 source。
- 如果最高版本 manifest 下载包失败,可以尝试同版本的其他 source。
- 不因为低版本 source 成功而降级,除非用户显式允许。
## 5. 下载与回退规则
PLONDS 服务优先走增量包:
1. 下载所选 manifest。
2. 下载 `changed.zip`
3. 校验 `changed.zip` 与 manifest 中的 hash/checksum。
4. 解压或准备增量 staging。
5. 交给安装程序执行增量安装。
如果增量流程失败PLONDS 服务自动改用完整包:
1. 下载 `Files.zip`
2. 校验 `Files.zip`
3. 解压或准备完整包 staging。
4. 交给安装程序执行完整包安装。
如果完整包也失败PLONDS 服务返回失败结果,由 UI 展示错误和重试入口。
## 6. 发布产物布局
Publisher 上传到 S3 的版本目录:
```text
<prefix>/<version>/PLONDS.json
<prefix>/<version>/changed.zip
<prefix>/<version>/<version>-changed/**
<prefix>/<version>/Files.zip
<prefix>/<version>/<version>-Files/**
```
说明:
- `Files.zip` 是上传到 S3 时的完整包标准名。
- `<version>-Files/` 是 S3 上解压后的完整包目录。
- `<prefix>/PLONDS.json` 是 S3 的固定 latest manifest 地址,和 GitHub Release latest manifest 一起作为客户端内置初始 source。
- GitHub Release 仍可保留平台原始文件名,例如 `files-windows-x64.zip`
- `PLONDS.json` 的 downloads 字段同时包含 GitHub 与 S3 的增量包、完整包位置。
- Publisher 必须先完成版本目录内的 `changed.zip``Files.zip`、解压目录和版本 `PLONDS.json` 上传,再更新 `<prefix>/PLONDS.json` latest 指针。
- Publisher 的 S3 目录上传必须支持重跑续传;同 key 且大小一致的对象可以跳过,避免失败后从头上传完整包目录。
## 7. 建议代码结构
```text
LanMountainDesktop/Services/Plonds/
IPlondsService.cs
PlondsService.cs
Sources/
IPlondsSource.cs
PlondsHttpManifestSource.cs
PlondsSourceRegistry.cs
Download/
PlondsDownloader.cs
PlondsDownloadPlanner.cs
Verification/
PlondsVerifier.cs
Staging/
PlondsPackageStore.cs
PlondsPreparedPackage.cs
Models/
PlondsClientManifest.cs
PlondsSourceDescriptor.cs
PlondsCheckResult.cs
```
后续如果要移植,优先把这棵目录或等价项目抽成独立库。
## 8. 与安装程序的交接契约
PLONDS 服务输出本地 prepared package
```csharp
public sealed record PlondsPreparedPackage(
Version Version,
PlondsPackageMode Mode,
string ManifestPath,
string? ChangedZipPath,
string? ChangedDirectory,
string? FilesZipPath,
string? FilesDirectory);
```
安装程序只接受这个结果,不参与 source 发现、下载和校验。
## 9. 实施顺序
1. Publisher 补齐完整包 S3 上传与 manifest downloads 字段。
2. 新增 `Services/Plonds/` 客户端服务骨架和模型。
3.`PlondsStaticUpdateService` / `PlondsReleaseUpdateService` 合并迁移到独立 PLONDS source 体系。
4.`LanMountainDesktop/Services/Update/Plonds*.cs` 迁出 Update 命名空间。
5. `UpdateSettingsService` 改为调用 `IPlondsService`,不再直接组合 S3/GitHub PLONDS fallback。
6. 安装入口只接收 `PlondsPreparedPackage`
7. 添加单元测试覆盖 source 扩展、最高版本选择、增量失败转完整包、完整包失败交 UI。