mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
changed.对启动器重构的尝试
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
2. Launcher 扫描 `app-*` 目录,选择最佳版本 (优先 `.current` 标记,然后按版本号降序)
|
||||
3. 首次启动显示 OOBE 引导 (`OobeWindow`)
|
||||
4. 显示 Splash 启动动画 (`SplashWindow`)
|
||||
5. 检查并应用待处理的更新 (`UpdateEngineService.ApplyPendingUpdate`)
|
||||
5. 检查并应用待处理的更新 (`IUpdateEngine.ApplyPendingUpdateAsync` / `UpdateEngineFacade`)
|
||||
6. 启动主程序 `app-{version}/LanMountainDesktop.exe`(待处理插件安装/升级由 Host 在 `PluginRuntimeService.ApplyPendingPluginOperations()` 中应用,而非 Launcher 启动流程)
|
||||
7. 清理标记为 `.destroy` 的旧版本
|
||||
|
||||
@@ -97,8 +97,8 @@
|
||||
| 服务 | 职责 |
|
||||
|------|------|
|
||||
| `DeploymentLocator` | 扫描和定位 `app-*` 版本目录,选择最佳版本 |
|
||||
| `UpdateEngineService` | 下载、验证、应用增量更新,支持原子化更新和回滚 |
|
||||
| `LauncherFlowCoordinator` | 协调 OOBE → Splash → 更新 → 启动主程序的完整流程 |
|
||||
| `IUpdateEngine` / `UpdateEngineFacade` | 更新门面;pending 检测、签名、Legacy/PLONDS apply、回滚、清理委托给 `Update/` 策略类 |
|
||||
| `LauncherOrchestrator` / `LaunchPipeline` | 协调 OOBE → Splash → 更新 → 启动主程序的完整流程 |
|
||||
| `OobeStateService` | 管理首次运行状态 |
|
||||
| `PluginInstallerService` | CLI 维护:`plugin install` 直接安装 `.laapp` |
|
||||
| `PluginUpgradeQueueService` | CLI 维护:`plugin update` 应用待处理队列(正常市场安装/升级由 Host 处理) |
|
||||
|
||||
@@ -64,9 +64,9 @@ dotnet test LanMountainDesktop.slnx -c Debug
|
||||
|
||||
### 调试建议
|
||||
|
||||
- **Launcher 启动问题优先看 `LanMountainDesktop.Launcher/Program.cs` 和 `Services/LauncherFlowCoordinator.cs`**
|
||||
- **版本管理问题优先看 `LanMountainDesktop.Launcher/Services/DeploymentLocator.cs`**
|
||||
- **更新系统问题优先看 `LanMountainDesktop.Launcher/Services/UpdateEngineService.cs` 和 `UpdateCheckService.cs`**
|
||||
- **Launcher 启动问题优先看 `LanMountainDesktop.Launcher/Program.cs`、`Shell/LauncherOrchestrator.cs` 和 `Startup/LaunchPipeline.cs`**
|
||||
- **版本管理问题优先看 `LanMountainDesktop.Launcher/Deployment/DeploymentLocator.cs`**
|
||||
- **更新系统问题优先看 `LanMountainDesktop.Launcher/Update/UpdateEngineFacade.cs`、`Update/LegacyUpdateApplier.cs`、`Update/PlondsUpdateApplier.cs` 和 `UpdateCheckService.cs`**
|
||||
- 启动问题优先看 `LanMountainDesktop/Program.cs` 和 `LanMountainDesktop/App.axaml.cs`
|
||||
- 设置窗口和设置页问题优先看 `LanMountainDesktop/Views/`、`ViewModels/` 与相关 `Services/`
|
||||
- 插件加载与安装问题优先看 `LanMountainDesktop/plugins/`
|
||||
|
||||
@@ -142,7 +142,7 @@ Task<UpdateCheckResult> CheckForUpdateAsync(
|
||||
- `Preview` - 检查所有版本 (包括 `prerelease=true`)
|
||||
|
||||
### IUpdateEngine / UpdateEngineFacade
|
||||
**职责**: 下载、验证、应用更新(实现位于 `Update/UpdateEngineFacade.cs`,契约 `Update/IUpdateEngine.cs`)
|
||||
**职责**: `UpdateEngineFacade` 是 `IUpdateEngine` 薄门面;pending 检测、签名、Legacy/PLONDS apply、快照、checkpoint、回滚和清理分别位于 `Update/` 策略/基础设施类。
|
||||
|
||||
**关键方法**:
|
||||
```csharp
|
||||
@@ -325,69 +325,38 @@ static async Task<int> Main(string[] args)
|
||||
}
|
||||
```
|
||||
|
||||
**App.axaml.cs**:
|
||||
**App.axaml.cs / Shell 入口**:
|
||||
```csharp
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
var appRoot = Commands.ResolveAppRoot(context);
|
||||
var deploymentLocator = new DeploymentLocator(appRoot);
|
||||
var updateCheckService = new UpdateCheckService("owner", "repo");
|
||||
|
||||
var coordinator = new LauncherFlowCoordinator(
|
||||
context,
|
||||
deploymentLocator,
|
||||
new OobeStateService(appRoot),
|
||||
new UpdateEngineService(deploymentLocator),
|
||||
updateCheckService,
|
||||
new PluginInstallerService());
|
||||
|
||||
_ = RunCoordinatorAsync(desktop, coordinator);
|
||||
var splashWindow = LaunchEntryHandler.CreateSplashWindow();
|
||||
splashWindow.Show();
|
||||
_ = LauncherCompositionRoot.RunOrchestratorWithSplashAsync(desktop, context, splashWindow);
|
||||
}
|
||||
```
|
||||
|
||||
**LauncherFlowCoordinator.RunAsync()**:
|
||||
**LaunchPipeline**:
|
||||
```csharp
|
||||
public async Task<LauncherResult> RunAsync()
|
||||
internal sealed class LaunchPipeline
|
||||
{
|
||||
// 1. 清理旧版本
|
||||
_deploymentLocator.CleanupDestroyedDeployments();
|
||||
|
||||
// 2. OOBE
|
||||
if (_oobeStateService.IsFirstRun())
|
||||
public async Task<LauncherResult> ExecuteAsync(LaunchContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
foreach (var step in _oobeSteps)
|
||||
await step.RunAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
// 3. Splash
|
||||
var splashWindow = await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
var window = new SplashWindow();
|
||||
window.Show();
|
||||
return window;
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
// 4. 应用更新
|
||||
var updateResult = await _updateEngine.ApplyPendingUpdateAsync();
|
||||
if (!updateResult.Success)
|
||||
Logger.Warn("Update apply failed, will try to launch existing version.");
|
||||
foreach (var phase in _phases)
|
||||
{
|
||||
var result = await phase.ExecuteAsync(context, cancellationToken);
|
||||
if (result.Status == LaunchPhaseStatus.Completed)
|
||||
{
|
||||
return result.Result!;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 启动主程序(插件 pending 由 Host 应用,不在 Launcher 启动步骤处理)
|
||||
var hostResult = await LaunchHostWithIpcAsync();
|
||||
if (!hostResult.Success)
|
||||
return hostResult;
|
||||
|
||||
return new LauncherResult { Success = true };
|
||||
}
|
||||
finally
|
||||
{
|
||||
await Dispatcher.UIThread.InvokeAsync(() => splashWindow.Close());
|
||||
return LaunchResultBuilder.BuildFailure("launch", "pipeline_incomplete", "Launch pipeline finished without producing a result.");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`LauncherFlowCoordinator` 已删除。GUI 顶层生命周期由 `LauncherGuiCoordinator` 处理,启动阶段由 `LaunchPipeline` 和各 `ILaunchPhase` 承载;更新 apply 通过 `IUpdateEngine` 门面进入 `Update/` 策略类。
|
||||
|
||||
## 命令行接口
|
||||
|
||||
### launch - 启动应用
|
||||
@@ -505,7 +474,7 @@ public class MyOobeStep : IOobeStep
|
||||
}
|
||||
```
|
||||
|
||||
2. 在 `LauncherFlowCoordinator` 中注册:
|
||||
2. 在 `Shell/LauncherOrchestrator.cs` 的 OOBE step 组装处注册,或通过后续 `ILaunchPhase`/OOBE 装配点接入:
|
||||
```csharp
|
||||
_oobeSteps = [
|
||||
new WelcomeOobeStep(_oobeStateService),
|
||||
|
||||
433
docs/Launcher 单项目内部解耦改造计划(执行版).md
Normal file
433
docs/Launcher 单项目内部解耦改造计划(执行版).md
Normal file
@@ -0,0 +1,433 @@
|
||||
---
|
||||
name: Launcher 单项目解耦
|
||||
overview: 在保持单一 LanMountainDesktop.Launcher 项目、单一 exe、零部署风险的前提下,按职责域增量重构:目录分层、RunAsync→Pipeline+Phase、UpdateEngine→策略类、App→纯 Avalonia+LauncherOrchestrator;执行过程中由 Agent 自主 Git 提交,每域可编译可测。
|
||||
todos:
|
||||
- id: phase-a-diagnostics
|
||||
content: Phase A:Startup 诊断 + HostStartupMonitor 独立类 + AOT 启动检测竞态修复 + 测试
|
||||
status: completed
|
||||
- id: phase-b-directory
|
||||
content: Phase B1:职责域目录迁移(Deployment/Update/Startup/Oobe/Plugins/Infrastructure),零逻辑变更,提交
|
||||
status: completed
|
||||
- id: phase-b-pipeline
|
||||
content: Phase B2:RunAsync→LaunchPipeline+ILaunchPhase,引入 LauncherOrchestrator,删除 LauncherFlowCoordinator,提交
|
||||
status: completed
|
||||
- id: phase-b-app-slim
|
||||
content: Phase B3:App.axaml.cs 精简为纯 Avalonia 初始化 + 委托 LauncherOrchestrator,提交
|
||||
status: completed
|
||||
- id: phase-c-di
|
||||
content: Phase C:LauncherServiceRegistration + 轻量 MS DI,统一 CLI/GUI 装配,提交
|
||||
status: completed
|
||||
- id: phase-d-update-split
|
||||
content: Phase D:UpdateEngineFacade→门面+策略类(Verifier/Activator/Rollback 等),提交
|
||||
status: completed
|
||||
- id: phase-e-guardrails
|
||||
content: Phase E:LauncherArchitectureTests + 文档 + AOT 回归,提交
|
||||
status: completed
|
||||
isProject: false
|
||||
---
|
||||
|
||||
# Launcher 单项目内部解耦改造计划(执行版)
|
||||
|
||||
## 0. 硬性约束
|
||||
|
||||
|
||||
| 约束 | 说明 |
|
||||
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **单项目** | 仅 `[LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj](LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj)`,不新建 Launcher.* 独立程序集 |
|
||||
| **单 exe** | 仍只发布 `LanMountainDesktop.Launcher.exe`(AOT 单文件) |
|
||||
| **零部署风险** | 不改变安装包目录结构、不引入新进程、不改变 Public IPC / Coordinator IPC 拓扑与契约 |
|
||||
| **增量重构** | 一个职责域一域推进,每步 `dotnet build` + 相关 `dotnet test` 通过后再进下一步 |
|
||||
| **单进程性能** | 模块间仅 in-process 接口调用,不为解耦新增 IPC |
|
||||
| **未来可拆** | 各域暴露 `I`* 接口,将来若需多进程可直接复用契约 |
|
||||
| **Git 自主提交** | Agent 在每个职责域完成且验证通过后 **自动 commit**,无需用户手动提交(见 §8) |
|
||||
|
||||
|
||||
外部共享库 `[LanMountainDesktop.PluginPackaging](LanMountainDesktop.PluginPackaging/)` 保留(Host + Launcher CLI 共用),不属于 Launcher 拆分。
|
||||
|
||||
---
|
||||
|
||||
## 1. 验收标准(必须全部满足)
|
||||
|
||||
### 1.1 零部署风险
|
||||
|
||||
- Inno Setup / CI 产物仍只有:`LanMountainDesktop.Launcher.exe` + `app-{version}/` + `.launcher/`
|
||||
- Host 调用 Launcher 的 CLI 参数、`launch-source`、`apply-update` 路径不变
|
||||
- Public IPC routes(`lanmountain.launcher.startup-progress`、`loading-state`)与 Coordinator pipe 不变
|
||||
- VeloPack / 更新 apply 状态机(`.current/.partial/.destroy`)行为不变
|
||||
|
||||
### 1.2 增量可验证
|
||||
|
||||
- 每个 Phase 结束:编译绿 + 该域新增/既有测试绿
|
||||
- 允许「纯移动文件」的 PR 单独提交,行为 diff 为零
|
||||
|
||||
### 1.3 测试友好
|
||||
|
||||
- `Startup/`、`Update/`、`Deployment/` 内类型 **无 Avalonia 依赖**,可独立单元测试
|
||||
- 每个 `ILaunchPhase`、每个 Update 策略类各有对应测试类
|
||||
- 保留并扩展现有 `[LauncherStartupTimeoutPolicyTests](LanMountainDesktop.Tests/LauncherStartupTimeoutPolicyTests.cs)`、`[LauncherMultiInstancePolicyTests](LanMountainDesktop.Tests/LauncherMultiInstancePolicyTests.cs)`
|
||||
|
||||
### 1.4 启动性能
|
||||
|
||||
- Pipeline 阶段为同步/异步方法调用链,不引入额外进程或网络
|
||||
- DI 容器仅在进程入口构建一次;Stage/Phase 实例可复用 Singleton
|
||||
|
||||
### 1.5 代码结构目标
|
||||
|
||||
|
||||
| 对象 | 当前(实测) | 目标 |
|
||||
| ----------------------------------- | -------------------------------------------- | --------------------------------------------------- |
|
||||
| `LauncherFlowCoordinator` 全 partial | ~1880 行(859+568+279+…) | **删除**;逻辑迁入 Pipeline + Phases |
|
||||
| `RunAsync()` 等价逻辑 | 跨 partial ~800+ 行 while/阶段混杂 | **≤80 行** 编排入口,细节在各 Phase |
|
||||
| `UpdateEngineFacade` | ~1849 行 | 门面 **≤200 行** + Update 内部策略/基础设施类各 **≤300 行** |
|
||||
| `App.axaml.cs` | ~258 行(已部分瘦身) | **≤120 行**:纯 Avalonia + 一行委托 `LauncherOrchestrator` |
|
||||
| `LauncherOrchestrator` | 不存在(逻辑在 Coordinator + CompositionRoot 546 行) | **≤250 行**:GUI 入口编排 |
|
||||
| `LauncherCompositionRoot` | ~546 行 | **≤150 行**:仅 DI 构建 + 入口分发 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 2. 目标架构
|
||||
|
||||
### 2.1 核心类型关系
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Program --> EntryRouter
|
||||
App --> LauncherOrchestrator
|
||||
EntryRouter --> LauncherOrchestrator
|
||||
LauncherOrchestrator --> LaunchPipeline
|
||||
LaunchPipeline --> Phase1[CleanupPhase]
|
||||
LaunchPipeline --> Phase2[OobeGatePhase]
|
||||
LaunchPipeline --> Phase3[ApplyUpdatePhase]
|
||||
LaunchPipeline --> Phase4[LaunchHostPhase]
|
||||
LaunchPipeline --> Phase5[MonitorStartupPhase]
|
||||
Phase3 --> IUpdateEngine
|
||||
Phase4 --> IDeploymentLocator
|
||||
Phase5 --> IHostStartupMonitor
|
||||
LauncherCompositionRoot --> ServiceProvider
|
||||
ServiceProvider --> LaunchPipeline
|
||||
```
|
||||
|
||||
|
||||
|
||||
**命名约定:**
|
||||
|
||||
- `**LauncherOrchestrator`**:GUI 生命周期内的唯一编排入口(取代 `LauncherFlowCoordinator` 对外角色)
|
||||
- `**LaunchPipeline`**:按序执行 `ILaunchPhase` 列表
|
||||
- `**ILaunchPhase**`:原 `ILaunchPipelineStage`;每个 Phase 对应原 `RunAsync` 中一个职责段
|
||||
|
||||
### 2.2 职责域目录(单项目内)
|
||||
|
||||
```
|
||||
LanMountainDesktop.Launcher/
|
||||
├── Program.cs # CLI / GUI 路由
|
||||
├── App.axaml.cs # 纯 Avalonia(≤120 行)
|
||||
├── Shell/
|
||||
│ ├── LauncherOrchestrator.cs # GUI 编排入口
|
||||
│ ├── LauncherCompositionRoot.cs # DI + Entry 分发
|
||||
│ ├── LaunchPipeline.cs
|
||||
│ ├── Phases/ # ILaunchPhase 实现
|
||||
│ │ ├── CleanupDeploymentsPhase.cs
|
||||
│ │ ├── OobeGatePhase.cs
|
||||
│ │ ├── ApplyPendingUpdatePhase.cs
|
||||
│ │ ├── LaunchHostPhase.cs
|
||||
│ │ └── MonitorStartupPhase.cs
|
||||
│ └── EntryHandlers/ # apply-update / air-app-broker / attach
|
||||
├── Deployment/
|
||||
├── Update/
|
||||
│ ├── IUpdateEngine.cs
|
||||
│ ├── UpdateEngineFacade.cs # IUpdateEngine 薄门面
|
||||
│ ├── PendingUpdateDetector.cs
|
||||
│ ├── UpdateSignatureVerifier.cs
|
||||
│ ├── LegacyUpdateApplier.cs
|
||||
│ ├── PlondsUpdateApplier.cs
|
||||
│ ├── DeploymentActivator.cs
|
||||
│ ├── UpdateSnapshotStore.cs
|
||||
│ ├── InstallCheckpointStore.cs
|
||||
│ ├── RollbackStrategy.cs
|
||||
│ └── IncomingArtifactsCleaner.cs
|
||||
├── Startup/
|
||||
├── Oobe/
|
||||
├── Ipc/
|
||||
├── AirApp/
|
||||
├── Plugins/
|
||||
├── Infrastructure/
|
||||
├── Models/
|
||||
└── Views/
|
||||
```
|
||||
|
||||
### 2.3 模块依赖规则
|
||||
|
||||
- `Deployment/`、`Update/`、`Startup/`:**禁止** `using Avalonia`
|
||||
- `Views/`:**禁止** 引用具体 `UpdateEngineFacade` / `DeploymentLocator`(仅接口或 Orchestrator)
|
||||
- 跨域:*仅通过 `I` 接口**;Orchestrator/Pipeline 负责装配
|
||||
|
||||
### 2.4 与 Host 边界(不变)
|
||||
|
||||
|
||||
| 能力 | Owner |
|
||||
| -------------------------- | ------------------------------ |
|
||||
| OOBE / Splash / 多实例 / 启动检测 | Launcher `Startup/` + `Shell/` |
|
||||
| 更新 apply / rollback | Launcher `Update/` |
|
||||
| 插件市场 / pending | Host + PluginPackaging |
|
||||
| 更新 download | Host → spawn Launcher apply |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 3. 三大核心拆分(用户指定)
|
||||
|
||||
### 3.1 拆分 `LauncherFlowCoordinator`:`RunAsync` → Pipeline + Phase
|
||||
|
||||
**现状:** 逻辑分散在 4 个 partial,等效一个 1800+ 行 God Class;`RunAsync` 内含清理、OOBE、更新、启动、IPC 监听、超时 while-loop、多实例分支。
|
||||
|
||||
**目标 API(单项目 `Shell/` 内):**
|
||||
|
||||
```csharp
|
||||
internal interface ILaunchPhase
|
||||
{
|
||||
string PhaseId { get; }
|
||||
/// <returns>null = 继续下一阶段;非 null = 管道终止并返回结果</returns>
|
||||
Task<LauncherResult?> ExecuteAsync(LaunchContext context, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
internal sealed class LaunchPipeline
|
||||
{
|
||||
public LaunchPipeline(IEnumerable<ILaunchPhase> phases) { ... }
|
||||
public Task<LauncherResult> RunAsync(LaunchContext context, CancellationToken ct);
|
||||
}
|
||||
```
|
||||
|
||||
**Phase 映射(与原 RunAsync 步骤一一对应):**
|
||||
|
||||
|
||||
| Phase | 原 RunAsync 段 | 产出 |
|
||||
| ------------------------- | --------------------------------------- | ----------------------------- |
|
||||
| `CleanupDeploymentsPhase` | `CleanupOldDeployments` | 无 UI |
|
||||
| `ExistingHostProbePhase` | 多实例 / Public IPC 探测 | 可短路成功 |
|
||||
| `ApplyPendingUpdatePhase` | `_updateEngine.ApplyPendingUpdateAsync` | 失败仍继续 |
|
||||
| `OobeGatePhase` | migration + OOBE steps | UI via `ILauncherUiPresenter` |
|
||||
| `LaunchHostPhase` | `LaunchHostWithIpcAsync` | Process + plan |
|
||||
| `MonitorStartupPhase` | while-loop + IPC + timeout | 调用 `IHostStartupMonitor` |
|
||||
|
||||
|
||||
`**LauncherOrchestrator` 职责:**
|
||||
|
||||
- 接收 `SplashWindow`、构建 `LaunchContext`(含 reporter、attempt registry、coordinator server)
|
||||
- 调用 `LaunchPipeline.RunAsync`
|
||||
- 管理 Splash/Error 窗口生命周期(委托 `ILauncherUiPresenter`)
|
||||
- **不含** 更新/部署/IPC 细节
|
||||
|
||||
**删除清单:** `LauncherFlowCoordinator.cs` 及全部 partial 文件。
|
||||
|
||||
---
|
||||
|
||||
### 3.2 拆分 `UpdateEngineFacade` → 门面 + 策略类
|
||||
|
||||
**现状:** 原 `UpdateEngineFacade` 为 1800+ 行单文件,混合检测、验签、解压、激活、快照、回滚、清理。
|
||||
|
||||
**目标结构:**
|
||||
|
||||
```
|
||||
Update/
|
||||
├── IUpdateEngine.cs # 对外契约(未来多进程可原样抽出)
|
||||
├── UpdateEngineFacade.cs # 门面,编排策略,≤200 行
|
||||
├── PendingUpdateDetector.cs # CheckPendingUpdate
|
||||
├── UpdateSignatureVerifier.cs # manifest + RSA 签名 / hash
|
||||
├── LegacyUpdateApplier.cs # Legacy zip apply
|
||||
├── PlondsUpdateApplier.cs # PLONDS manifest apply
|
||||
├── DeploymentActivator.cs # .current / .partial / .destroy
|
||||
├── UpdateSnapshotStore.cs # snapshots 读写
|
||||
├── InstallCheckpointStore.cs # resume checkpoint
|
||||
├── RollbackStrategy.cs # rollback CLI/GUI
|
||||
└── IncomingArtifactsCleaner.cs # CleanupIncomingArtifacts
|
||||
```
|
||||
|
||||
**门面方法映射:**
|
||||
|
||||
|
||||
| `IUpdateEngine` 公开方法 | 委托策略 |
|
||||
| ---------------------------- | ------------------------------------------------------ |
|
||||
| `CheckPendingUpdate()` | `PendingUpdateDetector` |
|
||||
| `ApplyPendingUpdateAsync()` | Detector → Verifier → Legacy/PLONDS Applier → Activator → Snapshot/Checkpoint |
|
||||
| `RollbackLatest()` | `RollbackStrategy` |
|
||||
| `CleanupIncomingArtifacts()` | `IncomingArtifactsCleaner` |
|
||||
| `DownloadAsync()`(若有) | 保持或拆 `UpdateDownloader` |
|
||||
|
||||
|
||||
**测试:** 每个 Strategy 独立 mock `IDeploymentLocator` / 文件系统,不启 Avalonia。
|
||||
|
||||
---
|
||||
|
||||
### 3.3 精简 `App.axaml.cs` → 纯 Avalonia + `LauncherOrchestrator`
|
||||
|
||||
**现状:** ~258 行,仍含 apply-update、air-app-broker、preview、coordinator attach 等分支。
|
||||
|
||||
**目标结构:**
|
||||
|
||||
```csharp
|
||||
// App.axaml.cs 目标形态(概念)
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
var context = LauncherRuntimeContext.Current;
|
||||
var mode = LauncherEntryModeResolver.Resolve(context);
|
||||
_ = LauncherOrchestrator.RunAsync(desktop, context, mode);
|
||||
}
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
```
|
||||
|
||||
**从 App 迁出的逻辑 → `Shell/EntryHandlers/`:**
|
||||
|
||||
|
||||
| 现 App 分支 | 新 Handler |
|
||||
| ----------------- | -------------------------------------- |
|
||||
| `launch` + splash | `GuiLaunchEntryHandler` → Orchestrator |
|
||||
| `apply-update` | `ApplyUpdateEntryHandler` |
|
||||
| `air-app-broker` | `AirAppBrokerEntryHandler` |
|
||||
| debug preview | `PreviewEntryHandler` |
|
||||
|
||||
|
||||
**验收:** `App.axaml.cs` ≤120 行;不含 `new UpdateEngineFacade` / `new DeploymentLocator` / while-loop。
|
||||
|
||||
---
|
||||
|
||||
## 4. 分阶段执行顺序与 Git 提交点
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[Phase A Startup] --> B1[Phase B1 目录迁移]
|
||||
B1 --> B2[Phase B2 Pipeline+Orchestrator]
|
||||
B2 --> B3[Phase B3 App 精简]
|
||||
B3 --> C[Phase C DI]
|
||||
B1 --> D[Phase D Update 策略拆分]
|
||||
C --> E[Phase E 守卫+文档+AOT回归]
|
||||
D --> E
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Phase A:Startup 子系统 + AOT 生产 bug(优先)
|
||||
|
||||
- 抽出 `Startup/HostStartupMonitor.cs`(从 partial 独立)
|
||||
- 修复 IPC 连接退避、成功判定统一走 `StartupSuccessTracker`
|
||||
- Host 侧 `DesktopVisible` 上报对齐(仅日志/时序,不改 IPC 契约)
|
||||
- 测试 + `**git commit**`: `fix(launcher): extract HostStartupMonitor and harden startup detection`
|
||||
|
||||
### Phase B1:目录迁移(零逻辑变更)
|
||||
|
||||
- 物理移动文件到 `Deployment/`、`Update/`、`Startup/` 等,更新 namespace
|
||||
- `dotnet build` + test
|
||||
- `**git commit**`: `refactor(launcher): reorganize into responsibility folders`
|
||||
|
||||
### Phase B2:Pipeline + Phase + LauncherOrchestrator
|
||||
|
||||
- 实现 `ILaunchPhase`、`LaunchPipeline`、`LauncherOrchestrator`
|
||||
- 逐 Phase 从 Coordinator 迁移逻辑(可先并行运行对照测试)
|
||||
- 删除 `LauncherFlowCoordinator*`
|
||||
- `**git commit**`: `refactor(launcher): replace LauncherFlowCoordinator with LaunchPipeline`
|
||||
|
||||
### Phase B3:App.axaml.cs 精简
|
||||
|
||||
- EntryHandlers 提取;App 仅 Avalonia + Orchestrator 委托
|
||||
- `**git commit**`: `refactor(launcher): slim App.axaml.cs to Avalonia shell only`
|
||||
|
||||
### Phase C:轻量 DI
|
||||
|
||||
- `LauncherServiceRegistration.cs` + `Microsoft.Extensions.DependencyInjection`
|
||||
- Program / CliHost / CompositionRoot 统一 `ServiceProvider`
|
||||
- `**git commit**`: `refactor(launcher): add composition-root DI wiring`
|
||||
|
||||
### Phase D:UpdateEngine 策略拆分(可与 B2 并行,依赖 B1)
|
||||
|
||||
- 已完成:`UpdateEngineFacade` 收敛为 119 行 `IUpdateEngine` 门面
|
||||
- 已完成:提取 pending 检测、签名、Legacy/PLONDS apply、激活、快照、checkpoint、回滚、incoming 清理等 Update 内部类
|
||||
- 已完成:补 `UpdateStrategyTests` 覆盖关键策略行为
|
||||
- `**git commit**`: `refactor(launcher): split UpdateEngine into strategy classes`
|
||||
|
||||
### Phase E:守卫 + 文档 + AOT 回归
|
||||
|
||||
- 已完成:`LauncherArchitectureTests` 守住无 Avalonia 依赖、`IUpdateEngine` 依赖边界、门面/CompositionRoot 行数阈值
|
||||
- 已完成:更新 `docs/LAUNCHER.md`、`docs/ARCHITECTURE.md`、`docs/DEVELOPMENT.md`、`docs/UPDATE_SYSTEM.md`
|
||||
- 已验证:Debug build、Launcher/Update/Architecture 过滤测试、全量测试;AOT publish 本地 smoke 通过(保留现有 AOT/trim warnings)
|
||||
- `**git commit**`: `docs(launcher): document module boundaries and add architecture tests`
|
||||
|
||||
---
|
||||
|
||||
## 5. Phase / Service 测试矩阵
|
||||
|
||||
|
||||
| 组件 | 测试文件 | 覆盖点 |
|
||||
| ----------------------- | ---------------------------- | --------------------------------- |
|
||||
| `StartupSuccessTracker` | `StartupSuccessTrackerTests` | Foreground/Tray/Background policy |
|
||||
| `HostStartupMonitor` | `HostStartupMonitorTests` | 超时、IPC 延迟、ShellStatus 轮询 |
|
||||
| `LaunchPipeline` | `LaunchPipelineTests` | Phase 短路、失败传播 |
|
||||
| 各 `ILaunchPhase` | `*PhaseTests` | 单阶段 mock |
|
||||
| `PendingUpdateDetector` | `PendingUpdateDetectorTests` | 无 pending / corrupt |
|
||||
| `DeploymentActivator` | `DeploymentActivatorTests` | 标记文件状态机 |
|
||||
| `RollbackStrategy` | `RollbackStrategyTests` | 快照回退 |
|
||||
| 命名空间规则 | `LauncherArchitectureTests` | 无 Avalonia 泄漏 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 6. 明确不做
|
||||
|
||||
- 不新建 csproj(Launcher.Deployment 等)
|
||||
- 不新建 exe / Windows Service
|
||||
- 不改变 Public IPC / Coordinator IPC 协议
|
||||
- 不把插件市场安装迁回 Launcher
|
||||
- 不为模块间通信引入新 IPC(仅保留现有 Host↔Launcher 契约)
|
||||
|
||||
---
|
||||
|
||||
## 7. 风险与缓解
|
||||
|
||||
|
||||
| 风险 | 缓解 |
|
||||
| --------------- | ------------------------------------------------------------------ |
|
||||
| 大规模移动 merge 冲突 | B1 独立 commit,零逻辑变更 |
|
||||
| Pipeline 迁移行为回归 | 先写 Phase 级测试再迁代码;保留 `LMD_LAUNCHER_LEGACY_COORDINATOR=1` 开关一个版本(可选) |
|
||||
| AOT + DI | 显式注册,禁止反射扫描;`PublishAot` CI 步骤验证 |
|
||||
| Update 拆分遗漏路径 | CLI `update *` 与 GUI apply-update 同一 `IUpdateEngine` 门面 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 8. Git 工作流(Agent 自主提交)
|
||||
|
||||
**原则:** 每个 Phase 验证通过后立即提交;不累积巨型 uncommitted diff。
|
||||
|
||||
**Commit 前检查(每个 commit 必做):**
|
||||
|
||||
```bash
|
||||
dotnet build LanMountainDesktop.slnx -c Debug
|
||||
dotnet test LanMountainDesktop.slnx -c Debug --filter "FullyQualifiedName~Launcher"
|
||||
```
|
||||
|
||||
**Commit message 风格(与仓库一致):**
|
||||
|
||||
```
|
||||
refactor(launcher): replace LauncherFlowCoordinator with LaunchPipeline
|
||||
|
||||
Pipeline + Phase pattern; LauncherOrchestrator becomes GUI entry.
|
||||
No deployment or IPC contract changes.
|
||||
```
|
||||
|
||||
**禁止:** `git push --force`、修改 git config、跳过 hooks(除非 hook 失败需修复后新 commit)。
|
||||
|
||||
**建议分支:** `refactor/launcher-internal-modularization`(单 long-lived 分支,按 Phase 连续 commit;或每 Phase 一个 PR 由用户决定 merge 时机)。
|
||||
|
||||
---
|
||||
|
||||
## 9. 整体完成定义(Definition of Done)
|
||||
|
||||
- 无 `LauncherFlowCoordinator` 源文件
|
||||
- `App.axaml.cs` ≤120 行,仅 Avalonia + Orchestrator 委托
|
||||
- `UpdateEngineFacade` 巨型文件已替换为薄门面 + Update 内部策略/基础设施类
|
||||
- 职责域目录就位,架构测试通过
|
||||
- 全量 Launcher 相关测试 + AOT publish smoke 通过
|
||||
- 安装包结构与 IPC 拓扑与重构前一致
|
||||
- 每个 Phase 有对应 Git commit,工作区 clean
|
||||
@@ -36,7 +36,7 @@ UpdateCheckService.CheckForUpdateAsync()
|
||||
↓
|
||||
有新版本? ──No→ 继续启动
|
||||
↓ Yes
|
||||
UpdateEngineService.DownloadAsync()
|
||||
IUpdateEngine.DownloadAsync() / UpdateEngineFacade
|
||||
├─ 下载 files-{version}.json
|
||||
├─ 下载 files-{version}.json.sig
|
||||
└─ 下载 delta-{old}-to-{new}.zip (或完整包)
|
||||
@@ -45,17 +45,13 @@ UpdateEngineService.DownloadAsync()
|
||||
↓
|
||||
下次启动时
|
||||
↓
|
||||
UpdateEngineService.ApplyPendingUpdate()
|
||||
├─ 验证签名
|
||||
├─ 创建 app-{new}/ 目录
|
||||
├─ 标记 .partial
|
||||
├─ 解压增量包
|
||||
├─ 从旧版本复用未变更文件
|
||||
├─ 验证所有文件 SHA256
|
||||
├─ 删除 .partial
|
||||
├─ 添加 .current 到新版本
|
||||
├─ 标记旧版本 .destroy
|
||||
└─ 保存更新快照
|
||||
IUpdateEngine.ApplyPendingUpdateAsync() / UpdateEngineFacade
|
||||
├─ PendingUpdateDetector 识别 Legacy/PLONDS pending 更新
|
||||
├─ UpdateSignatureVerifier 验证签名和哈希
|
||||
├─ LegacyUpdateApplier 或 PlondsUpdateApplier 应用文件
|
||||
├─ DeploymentActivator 切换 .current/.partial/.destroy
|
||||
├─ UpdateSnapshotStore / InstallCheckpointStore 记录快照和断点
|
||||
└─ IncomingArtifactsCleaner 清理 incoming 缓存
|
||||
↓
|
||||
启动新版本
|
||||
↓
|
||||
@@ -448,4 +444,3 @@ private static void EnsurePathWithinRoot(string targetPath, string rootPath)
|
||||
- Release pipeline now produces VeloPack native assets (
|
||||
eleases.win.json, *.nupkg, RELEASES).
|
||||
- Launcher remains the installer and rollback authority; only package generation moved to VeloPack.
|
||||
- Legacy iles.json + update.zip generation remains available only as a disabled fallback path in CI.
|
||||
|
||||
88
docs/auto_commit_md/20260528_1ee6e68.md
Normal file
88
docs/auto_commit_md/20260528_1ee6e68.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Git 提交分析报告
|
||||
|
||||
## 基本信息
|
||||
- **哈希**: 1ee6e68f33f0a1bbeccf7cef8f3767e65d6916c9
|
||||
- **短哈希**: 1ee6e68
|
||||
- **作者**: lincube <lincube3@hotmail.com>
|
||||
- **时间**: 2026-05-28 10:28:31 +0800
|
||||
- **合入作者**: Cursor <cursoragent@cursor.com>
|
||||
|
||||
## 提交信息摘要
|
||||
refactor(launcher): converge plugin pending to Host via PluginPackaging
|
||||
|
||||
## 变更统计
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| 变更文件数 | 32 |
|
||||
| 新增行数 | 881 |
|
||||
| 删除行数 | 1917 |
|
||||
| 净变化 | -1036 |
|
||||
|
||||
## 详细变更分析
|
||||
|
||||
### 架构变更概述
|
||||
此提交进行了重要的架构调整:将插件待处理(pending)功能从 Launcher 移到了 Host(主程序),并引入了新的 PluginPackaging 项目。
|
||||
|
||||
### 新增项目
|
||||
1. **LanMountainDesktop.PluginPackaging** - 新的插件打包项目
|
||||
- `PendingPluginUpgradeStore.cs` - 待处理插件升级存储
|
||||
- `PluginPackageInstallOptions.cs` - 插件包安装选项
|
||||
- `PluginPackageInstallResult.cs` - 插件包安装结果
|
||||
- `PluginPackageInstaller.cs` - 插件包安装器
|
||||
- `PluginPackageManifest.cs` - 插件包清单
|
||||
- `PluginPackageManifestReader.cs` - 插件包清单读取器
|
||||
- `PluginPackagingConstants.cs` - 插件打包常量
|
||||
|
||||
### 删除项目
|
||||
1. **LanMountainDesktop.PluginUpgradeHelper** - 已删除的插件升级辅助项目
|
||||
- `Program.cs` - 主程序(372行)
|
||||
|
||||
### 主要删除的文件
|
||||
1. `FlexibleHostLocator.cs` - 灵活主机定位器(634行)
|
||||
2. `UpdateCheckService.cs` - 更新检查服务(161行)
|
||||
3. `LauncherClient.cs` - Launcher 客户端(210行)
|
||||
4. `CliLauncherUpdateBridge.cs` - CLI Launcher 更新桥接(48行)
|
||||
5. `IpcLauncherUpdateBridge.cs` - IPC Launcher 更新桥接(171行)
|
||||
|
||||
### 主要变更的文件
|
||||
1. `PendingPluginUpgradeService.cs` - 大幅简化
|
||||
2. `PluginMarketInstallService.cs` - 大幅简化,移除了通过 Launcher 安装的逻辑
|
||||
3. `PluginRuntimeService.cs` - 新增 `ApplyPendingPluginOperations()` 方法
|
||||
4. 多个文档文件更新 - 反映架构变更
|
||||
|
||||
### 架构变化要点
|
||||
|
||||
#### 1. 职责转移
|
||||
- **之前**:Launcher 负责插件待处理安装/升级
|
||||
- **现在**:Host(主程序)负责在启动时应用待处理插件操作
|
||||
|
||||
#### 2. 新的流程
|
||||
1. 插件市场下载包到用户的待处理队列
|
||||
2. 下次 Host 启动时,在插件发现前应用待处理操作
|
||||
3. Launcher 保留 CLI 命令作为维护兼容性入口
|
||||
|
||||
#### 3. 新增功能
|
||||
- `PluginRuntimeService.ApplyPendingPluginOperations()` - 应用待处理插件操作
|
||||
- `PendingPluginUpgradeService.AddPendingInstallOrUpgrade()` - 添加待处理安装或升级
|
||||
- 新增 `RestartRequired` 状态到 `AirAppMarketInstallState`
|
||||
|
||||
## 代码审查要点
|
||||
|
||||
### 优势
|
||||
1. **架构更清晰**:Launcher 专注于版本管理和更新,Host 专注于插件运行时
|
||||
2. **减少权限需求**:插件安装不需要通过 Launcher,减少了权限提升的场景
|
||||
3. **简化代码**:删除了大量桥接代码和复杂的协调逻辑
|
||||
4. **更好的用户体验**:插件安装在 Host 启动时完成,用户体验更流畅
|
||||
|
||||
### 潜在风险
|
||||
1. **功能回归风险**:删除了大量代码,需要确保所有功能都已正确迁移
|
||||
2. **兼容性**:CLI 命令作为兼容性入口,需要确保仍然正常工作
|
||||
3. **升级路径**:现有用户的待处理插件队列需要正确迁移
|
||||
4. **错误处理**:Host 启动时的插件安装失败需要妥善处理
|
||||
|
||||
### 建议
|
||||
1. 完整测试插件市场安装/升级流程
|
||||
2. 测试 CLI 插件命令的兼容性
|
||||
3. 测试待处理插件操作在 Host 启动时的应用
|
||||
4. 验证升级路径,确保现有用户平滑过渡
|
||||
5. 检查错误处理和日志记录是否完善
|
||||
83
docs/auto_commit_md/20260528_1ef47c7.md
Normal file
83
docs/auto_commit_md/20260528_1ef47c7.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Git 提交分析报告
|
||||
|
||||
## 基本信息
|
||||
- **哈希**: 1ef47c780bea380088d2615e8f4ec7d478ca5aa5
|
||||
- **短哈希**: 1ef47c7
|
||||
- **作者**: lincube <lincube3@hotmail.com>
|
||||
- **时间**: 2026-05-28 11:13:14 +0800
|
||||
- **合入作者**: Cursor <cursoragent@cursor.com>
|
||||
|
||||
## 提交信息摘要
|
||||
refactor(launcher): add DI, IUpdateEngine facade, and architecture tests
|
||||
|
||||
## 变更统计
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| 变更文件数 | 31 |
|
||||
| 新增行数 | 168 |
|
||||
| 删除行数 | 1512 |
|
||||
| 净变化 | -1344 |
|
||||
|
||||
## 详细变更分析
|
||||
|
||||
### 新增文件
|
||||
1. `LanMountainDesktop.Launcher/Update/IUpdateEngine.cs` - 新增更新引擎接口
|
||||
2. `LanMountainDesktop.Tests/LauncherArchitectureTests.cs` - 新增架构测试文件
|
||||
|
||||
### 删除文件
|
||||
1. `LanMountainDesktop.Launcher/Services/LauncherFlowCoordinator.cs`
|
||||
2. `LanMountainDesktop.Launcher/Services/LauncherFlowCoordinator.HostStartupMonitor.cs`
|
||||
3. `LanMountainDesktop.Launcher/Services/LauncherFlowCoordinator.LaunchOrchestrator.cs`
|
||||
4. `LanMountainDesktop.Launcher/Services/LauncherFlowCoordinator.UiPresenter.cs`
|
||||
|
||||
### 重命名文件
|
||||
1. `LanMountainDesktop.Launcher/Update/UpdateEngineService.cs` → `LanMountainDesktop.Launcher/Update/UpdateEngineFacade.cs`
|
||||
|
||||
### 主要变更点
|
||||
|
||||
#### 1. 依赖注入重构
|
||||
- 新增 `LanMountainDesktop.Launcher/Shell/LauncherServiceRegistration.cs` - DI 服务注册
|
||||
- 修改 `LanMountainDesktop.Launcher/Shell/LauncherCompositionRoot.cs` - 组合根
|
||||
- 更新 `LanMountainDesktop.Launcher/Program.cs` - 入口点调整
|
||||
|
||||
#### 2. 更新引擎重构
|
||||
- 新增 `IUpdateEngine` 接口,定义更新引擎契约
|
||||
- `UpdateEngineService` 重命名为 `UpdateEngineFacade` 并实现接口
|
||||
- 将更新相关逻辑从巨大的协调器中解耦
|
||||
|
||||
#### 3. 协调器移除
|
||||
- 删除了 `LauncherFlowCoordinator` 及其分部类(共约 1436 行代码)
|
||||
- 功能已由 `LauncherOrchestrator` + `LaunchPipeline` 替代
|
||||
|
||||
#### 4. 架构测试
|
||||
- 新增 `LauncherArchitectureTests` 测试:
|
||||
- 验证 Deployment/Update/Startup/Infrastructure 命名空间不依赖 Avalonia
|
||||
- 确认 `LauncherFlowCoordinator` 已不存在
|
||||
|
||||
#### 5. 命名空间调整
|
||||
- 多个视图文件的 `using` 语句从 `LanMountainDesktop.Launcher.Services` 改为 `LanMountainDesktop.Launcher.Infrastructure`
|
||||
|
||||
#### 6. 文档更新
|
||||
- 更新 `docs/LAUNCHER.md`,反映新的架构设计
|
||||
- 移除对 `LauncherFlowCoordinator` 的描述
|
||||
- 添加对 `LauncherOrchestrator` / `LaunchPipeline` 的说明
|
||||
- 文档化 `IUpdateEngine` / `UpdateEngineFacade`
|
||||
|
||||
## 代码审查要点
|
||||
|
||||
### 优势
|
||||
1. **架构清晰**:通过 DI 和接口解耦,代码结构更清晰
|
||||
2. **责任分离**:将巨型协调器拆分为多个职责单一的组件
|
||||
3. **可测试性**:新增架构测试,确保关键架构约束得到执行
|
||||
4. **文档更新**:同步更新了架构文档
|
||||
5. **代码简化**:净减少 1344 行代码,去除了冗余
|
||||
|
||||
### 潜在风险
|
||||
1. **大规模删除**:删除了大量代码,需要确保没有遗漏功能
|
||||
2. **依赖注入引入**:新引入 DI 框架,需要验证服务注册是否完整
|
||||
3. **接口变更**:`UpdateEngineService` 重命名并改为接口实现,需确保所有引用都已更新
|
||||
|
||||
### 建议
|
||||
1. 运行完整的测试套件,特别是启动流程和更新相关测试
|
||||
2. 进行端到端测试,验证启动流程是否正常工作
|
||||
3. 检查插件相关功能是否仍然正常(提到了插件 pending 处理)
|
||||
45
docs/auto_commit_md/20260528_545dee8.md
Normal file
45
docs/auto_commit_md/20260528_545dee8.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Git 提交分析报告
|
||||
|
||||
## 基本信息
|
||||
- **哈希**: 545dee85a79942a18b18a81a86a53bb700161f9d
|
||||
- **短哈希**: 545dee8
|
||||
- **作者**: lincube <lincube3@hotmail.com>
|
||||
- **时间**: 2026-05-28 10:28:16 +0800
|
||||
- **合入作者**: Cursor <cursoragent@cursor.com>
|
||||
|
||||
## 提交信息摘要
|
||||
fix(launcher): wire HostStartupMonitor into launch flow
|
||||
|
||||
## 变更统计
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| 变更文件数 | 1 |
|
||||
| 新增行数 | 1 |
|
||||
| 删除行数 | 1 |
|
||||
| 净变化 | 0 |
|
||||
|
||||
## 详细变更分析
|
||||
|
||||
### 变更的文件
|
||||
`LanMountainDesktop.Launcher/Startup/HostStartupMonitor.cs`
|
||||
|
||||
### 具体变更
|
||||
修改了 `HostStartupMonitor` 中的 `Request` 记录的 `ComposeLaunchDetails` 函数签名:
|
||||
- **之前**:`Func<bool, bool, bool, Dictionary<string, string>>`
|
||||
- **之后**:`Func<bool, bool, Dictionary<string, string>>`
|
||||
|
||||
移除了第三个布尔参数。
|
||||
|
||||
## 代码审查要点
|
||||
|
||||
### 优势
|
||||
1. **简化接口**:减少了不必要的参数
|
||||
2. **保持兼容性**:这是一个小的调整,不会造成大的影响
|
||||
|
||||
### 潜在风险
|
||||
1. **调用点需要同步更新**:需要确保所有调用 `HostStartupMonitor` 的地方都已同步更新
|
||||
2. **参数用途不明确**:不清楚移除的参数原本的用途
|
||||
|
||||
### 建议
|
||||
1. 检查所有调用点,确保已同步更新
|
||||
2. 运行相关测试,确保功能正常
|
||||
98
docs/auto_commit_md/20260528_a26b6fa.md
Normal file
98
docs/auto_commit_md/20260528_a26b6fa.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# Git 提交分析报告
|
||||
|
||||
## 基本信息
|
||||
- **哈希**: a26b6faace509f2ff8806e95fe5891ce4b325fc4
|
||||
- **短哈希**: a26b6fa
|
||||
- **作者**: lincube <lincube3@hotmail.com>
|
||||
- **时间**: 2026-05-28 11:03:49 +0800
|
||||
- **合入作者**: Cursor <cursoragent@cursor.com>
|
||||
|
||||
## 提交信息摘要
|
||||
refactor(launcher): replace LauncherFlowCoordinator with LaunchPipeline and slim App shell
|
||||
|
||||
## 变更统计
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| 变更文件数 | 19 |
|
||||
| 新增行数 | 2517 |
|
||||
| 删除行数 | 788 |
|
||||
| 净变化 | +1729 |
|
||||
|
||||
## 详细变更分析
|
||||
|
||||
### 新增文件
|
||||
1. `LanMountainDesktop.Launcher/Shell/EntryHandlers/LaunchEntryHandlers.cs` - 启动入口处理器
|
||||
2. `LanMountainDesktop.Launcher/Shell/EntryHandlers/PreviewEntryHandler.cs` - 预览入口处理器
|
||||
3. `LanMountainDesktop.Launcher/Shell/LauncherCompositionRoot.cs` - 组合根
|
||||
4. `LanMountainDesktop.Launcher/Shell/LauncherOrchestrator.cs` - 启动协调器
|
||||
5. `LanMountainDesktop.Launcher/Startup/ExistingHostProbe.cs` - 现有主机探测
|
||||
6. `LanMountainDesktop.Launcher/Startup/HostLaunchModels.cs` - 主机启动模型
|
||||
7. `LanMountainDesktop.Launcher/Startup/HostLaunchService.cs` - 主机启动服务
|
||||
8. `LanMountainDesktop.Launcher/Startup/LaunchAttemptDetails.cs` - 启动尝试详情
|
||||
9. `LanMountainDesktop.Launcher/Startup/LaunchPipeline.cs` - 启动管道
|
||||
10. `LanMountainDesktop.Launcher/Startup/LaunchUiPresenter.cs` - UI 展示器
|
||||
11. `LanMountainDesktop.Launcher/Startup/Phases/ApplyPendingUpdatePhase.cs` - 应用待更新阶段
|
||||
12. `LanMountainDesktop.Launcher/Startup/Phases/CleanupDeploymentsPhase.cs` - 清理部署阶段
|
||||
13. `LanMountainDesktop.Launcher/Startup/Phases/ExistingHostProbePhase.cs` - 现有主机探测阶段
|
||||
14. `LanMountainDesktop.Launcher/Startup/Phases/LaunchHostPhase.cs` - 启动主机阶段
|
||||
15. `LanMountainDesktop.Launcher/Startup/Phases/MonitorStartupPhase.cs` - 监控启动阶段
|
||||
16. `LanMountainDesktop.Launcher/Startup/Phases/OobeGatePhase.cs` - OOBE 关卡阶段
|
||||
|
||||
### 主要变更文件
|
||||
1. `LanMountainDesktop.Launcher/App.axaml.cs` - 大幅精简,移除大量逻辑
|
||||
|
||||
### 主要变更点
|
||||
|
||||
#### 1. 架构重构
|
||||
- **移除巨型协调器**:将 `LauncherFlowCoordinator` 的功能拆分到多个职责单一的类中
|
||||
- **引入管道模式**:新增 `LaunchPipeline` 来管理启动流程
|
||||
- **阶段化设计**:将启动流程拆分为多个独立的阶段(Phase)
|
||||
|
||||
#### 2. 启动阶段设计
|
||||
新增以下启动阶段:
|
||||
- `CleanupDeploymentsPhase` - 清理部署
|
||||
- `ExistingHostProbePhase` - 现有主机探测
|
||||
- `ApplyPendingUpdatePhase` - 应用待更新
|
||||
- `OobeGatePhase` - OOBE 关卡
|
||||
- `LaunchHostPhase` - 启动主机
|
||||
- `MonitorStartupPhase` - 监控启动
|
||||
|
||||
#### 3. 核心组件
|
||||
- **LauncherOrchestrator** - 负责整体协调
|
||||
- **LauncherCompositionRoot** - 组合根,负责对象组装
|
||||
- **HostLaunchService** - 主机启动服务
|
||||
- **ExistingHostProbe** - 现有主机探测逻辑
|
||||
- **LaunchUiPresenter** - UI 展示逻辑
|
||||
|
||||
#### 4. 入口处理
|
||||
- 新增 `LaunchEntryHandlers` 和 `PreviewEntryHandler`
|
||||
- 将入口处理逻辑从 `App` 类中移出
|
||||
|
||||
#### 5. App 类精简
|
||||
- `App.axaml.cs` 从 815 行大幅减少
|
||||
- 逻辑被分散到各个专门的类中
|
||||
|
||||
#### 6. 测试更新
|
||||
- `LauncherAirAppLifecycleServiceTests` 更新以使用新的入口处理器
|
||||
- `LauncherGlobalUsings.cs` 添加新的命名空间引用
|
||||
|
||||
## 代码审查要点
|
||||
|
||||
### 优势
|
||||
1. **职责分离**:每个类职责更加单一清晰
|
||||
2. **可扩展性**:通过阶段模式,方便添加新的启动阶段
|
||||
3. **可测试性**:各个组件可以独立测试
|
||||
4. **代码组织**:文件结构更清晰,便于维护
|
||||
5. **增量变化**:虽然新增了很多代码,但这是为了更好的架构
|
||||
|
||||
### 潜在风险
|
||||
1. **复杂度增加**:组件数量增多,理解整个流程需要查看更多文件
|
||||
2. **阶段顺序依赖**:阶段之间有依赖关系,需要确保顺序正确
|
||||
3. **状态管理**:`LaunchContext` 需要在多个阶段之间传递状态,需确保状态一致性
|
||||
4. **回归风险**:大规模重构可能引入隐藏的 bug
|
||||
|
||||
### 建议
|
||||
1. 为每个阶段编写单元测试
|
||||
2. 编写集成测试验证完整启动流程
|
||||
3. 考虑添加流程图文档,帮助理解各阶段关系
|
||||
4. 进行充分的端到端测试,确保各种启动场景正常工作
|
||||
109
docs/auto_commit_md/20260528_b219f10.md
Normal file
109
docs/auto_commit_md/20260528_b219f10.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Git 提交分析报告
|
||||
|
||||
## 基本信息
|
||||
- **哈希**: b219f109ec1c69c21d57be7ac3e03dcd6f981877
|
||||
- **短哈希**: b219f10
|
||||
- **作者**: lincube <lincube3@hotmail.com>
|
||||
- **时间**: 2026-05-28 10:43:30 +0800
|
||||
- **合入作者**: Cursor <cursoragent@cursor.com>
|
||||
|
||||
## 提交信息摘要
|
||||
refactor(launcher): reorganize into responsibility folders
|
||||
|
||||
## 变更统计
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| 变更文件数 | 57 |
|
||||
| 新增行数 | 92 |
|
||||
| 删除行数 | 197 |
|
||||
| 净变化 | -105 |
|
||||
|
||||
## 详细变更分析
|
||||
|
||||
### 主要目录重组
|
||||
此提交主要是将文件从单一的 `Services` 文件夹重新组织到按职责划分的文件夹中:
|
||||
|
||||
#### 1. AirApp 相关
|
||||
- 从 `Services/AirApp/` 移动到 `AirApp/`
|
||||
- 涉及文件:
|
||||
- `AirAppHostLocator.cs`
|
||||
- `AirAppInstanceKey.cs`
|
||||
- `IAirAppProcessStarter.cs`
|
||||
- `LauncherAirAppLifecycleIpcHost.cs`
|
||||
- `LauncherAirAppLifecycleService.cs`
|
||||
|
||||
#### 2. Deployment 相关
|
||||
- 从 `Services/` 移动到 `Deployment/`
|
||||
- 涉及文件:
|
||||
- `DeploymentLocator.cs`
|
||||
- `HostDiscoveryOptions.cs`
|
||||
- `HostLaunchPlan.cs`
|
||||
- `HostResolutionResult.cs`
|
||||
- `LegacyVersionDetector.cs`
|
||||
|
||||
#### 3. Infrastructure 相关
|
||||
- 从 `Services/` 移动到 `Infrastructure/`
|
||||
- 涉及文件:
|
||||
- `Commands.cs`
|
||||
- `DataLocationResolver.cs`
|
||||
- `DeferredSplashStageReporter.cs`
|
||||
- `DotNetRuntimeProbe.cs`
|
||||
- `ISplashStageReporter.cs`
|
||||
- `LanguagePreferenceService.cs`
|
||||
- `LauncherBackgroundService.cs`
|
||||
- `LauncherDebugSettingsStore.cs`
|
||||
- `LauncherExecutionContext.cs`
|
||||
- `Logger.cs`
|
||||
- `ThemeService.cs`
|
||||
|
||||
#### 4. Oobe 相关
|
||||
- 从 `Services/` 移动到 `Oobe/`
|
||||
- 涉及文件:
|
||||
- `DataLocationOobeStep.cs`
|
||||
- `HostAppSettingsOobeMerger.cs`
|
||||
- `IOobeStep.cs`
|
||||
- `LauncherWindowsStartupService.cs`
|
||||
- `OobeStateService.cs`
|
||||
- `PrivacyAgreementService.cs`
|
||||
- `WelcomeOobeStep.cs`
|
||||
|
||||
#### 5. Startup 相关
|
||||
- 从 `Services/` 移动到 `Startup/`
|
||||
- 涉及文件:
|
||||
- `StartupAttemptRegistry.cs`
|
||||
- `StartupDiagnostics.cs`
|
||||
- `StartupSuccessTracker.cs`
|
||||
|
||||
#### 6. Update 相关
|
||||
- 从 `Services/` 移动到 `Update/`
|
||||
- 涉及文件:
|
||||
- `IUpdateProgressReporter.cs`
|
||||
- `NullUpdateProgressReporter.cs`
|
||||
- `UpdateCheckService.cs`
|
||||
- `UpdateEngineService.cs`
|
||||
|
||||
### 其他变更
|
||||
1. 新增 `GlobalUsings.cs` - 添加全局 using 语句
|
||||
2. 新增 `LauncherGlobalUsings.cs`(测试项目)- 测试项目的全局 using
|
||||
3. `OobeWindow.axaml.cs` - 更新命名空间引用
|
||||
4. 多个测试文件更新 - 更新命名空间引用
|
||||
|
||||
## 代码审查要点
|
||||
|
||||
### 优势
|
||||
1. **更好的组织结构**:按职责划分文件夹,代码组织更清晰
|
||||
2. **易于导航**:开发者可以更快找到相关功能的文件
|
||||
3. **模块化**:每个文件夹代表一个功能模块
|
||||
4. **可维护性提升**:相关文件放在一起,便于维护
|
||||
|
||||
### 潜在风险
|
||||
1. **合并冲突风险**:大量文件移动可能导致合并冲突
|
||||
2. **引用更新不完整**:需要确保所有 using 语句和引用都已更新
|
||||
3. **文档需要同步**:相关文档可能需要更新以反映新的文件结构
|
||||
4. **Git 历史**:文件移动可能会影响 Git 历史追踪
|
||||
|
||||
### 建议
|
||||
1. 运行完整的编译检查,确保没有遗漏的引用
|
||||
2. 运行测试套件,确保所有测试通过
|
||||
3. 检查相关文档是否需要更新
|
||||
4. 考虑为新的文件夹结构添加 README 说明
|
||||
103
docs/auto_commit_md/20260528_ebe35d6.md
Normal file
103
docs/auto_commit_md/20260528_ebe35d6.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Git 提交分析报告
|
||||
|
||||
## 基本信息
|
||||
- **哈希**: ebe35d6f91b844dcdf3729d0d894875804749e9a
|
||||
- **短哈希**: ebe35d6
|
||||
- **作者**: lincube <lincube3@hotmail.com>
|
||||
- **时间**: 2026-05-28 10:27:33 +0800
|
||||
- **合入作者**: Cursor <cursoragent@cursor.com>
|
||||
|
||||
## 提交信息摘要
|
||||
fix(launcher): extract startup subsystem and harden IPC detection
|
||||
|
||||
## 变更统计
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| 变更文件数 | 14 |
|
||||
| 新增行数 | 1990 |
|
||||
| 删除行数 | 1535 |
|
||||
| 净变化 | +455 |
|
||||
|
||||
## 详细变更分析
|
||||
|
||||
### 概述
|
||||
此提交将启动子系统从庞大的 `LauncherFlowCoordinator` 中提取出来,形成独立的、职责更清晰的模块,并加强了 IPC 检测机制。
|
||||
|
||||
### 新增文件
|
||||
|
||||
#### 1. 启动子系统核心组件
|
||||
- `HostActivationPolicy.cs` - 主机激活策略
|
||||
- `HostStartupMonitor.cs` - 主机启动监控器
|
||||
- `PublicIpcConnection.cs` - 公共 IPC 连接
|
||||
- `StartupDiagnostics.cs` - 启动诊断
|
||||
- `StartupSuccessTracker.cs` - 启动成功跟踪器
|
||||
- `StartupTimeoutPolicy.cs` - 启动超时策略
|
||||
|
||||
#### 2. 分部类文件
|
||||
- `LauncherFlowCoordinator.HostStartupMonitor.cs` - 主机启动监控器分部类
|
||||
- `LauncherFlowCoordinator.LaunchOrchestrator.cs` - 启动协调器分部类
|
||||
- `LauncherFlowCoordinator.UiPresenter.cs` - UI 展示器分部类
|
||||
|
||||
#### 3. 测试文件
|
||||
- `HostActivationPolicyTests.cs` - 主机激活策略测试
|
||||
- `StartupSuccessTrackerTests.cs` - 启动成功跟踪器测试
|
||||
|
||||
### 主要变更的文件
|
||||
- `LauncherFlowCoordinator.cs` - 大幅简化(1612行 → 更少)
|
||||
- `LauncherMultiInstancePolicyTests.cs` - 更新命名空间引用
|
||||
- `LauncherStartupTimeoutPolicyTests.cs` - 更新测试以引用新文件
|
||||
|
||||
### 核心功能改进
|
||||
|
||||
#### 1. 提取启动子系统
|
||||
- 将启动相关逻辑从 `LauncherFlowCoordinator` 中分离
|
||||
- 形成独立的、可测试的组件
|
||||
- 每个组件职责单一清晰
|
||||
|
||||
#### 2. 主机激活策略 (`HostActivationPolicy`)
|
||||
- `ShouldProbeExistingHostBeforeLaunch()` - 决定是否在启动前探测现有主机
|
||||
- `IsExistingHostReadyForLauncherDecision()` - 检查现有主机是否准备好
|
||||
- `IsRecoverableActivationFailure()` - 判断激活失败是否可恢复
|
||||
- 退出码分类方法
|
||||
|
||||
#### 3. 启动成功跟踪器 (`StartupSuccessTracker`)
|
||||
- 支持多种启动策略(前台、重启后台、重启托盘)
|
||||
- 根据不同阶段判断启动成功
|
||||
- 提供恢复成功状态构建
|
||||
|
||||
#### 4. 启动超时策略 (`StartupTimeoutPolicy`)
|
||||
- 软超时:30秒
|
||||
- 硬超时:120秒
|
||||
- IPC 连接超时配置
|
||||
- 重试间隔配置
|
||||
|
||||
#### 5. 启动诊断 (`StartupDiagnostics`)
|
||||
- 可通过环境变量 `LMD_LAUNCHER_STARTUP_DIAG=1` 启用
|
||||
- 记录启动事件到 JSONL 文件
|
||||
- 追踪 Shell 状态变化
|
||||
|
||||
#### 6. 加强 IPC 检测 (`PublicIpcConnection`)
|
||||
- 带退避的连接尝试
|
||||
- 更好的错误处理
|
||||
- 超时控制
|
||||
|
||||
## 代码审查要点
|
||||
|
||||
### 优势
|
||||
1. **更好的模块化**:代码组织更清晰,每个组件职责单一
|
||||
2. **可测试性提升**:提取出的组件都有对应的测试
|
||||
3. **诊断能力增强**:新增启动诊断功能,便于问题排查
|
||||
4. **IPC 检测更健壮**:带退避的重试机制,超时配置更精细
|
||||
5. **代码可读性**:庞大的协调器被拆解,更易理解和维护
|
||||
|
||||
### 潜在风险
|
||||
1. **回归风险**:大规模重构可能引入隐藏的 bug
|
||||
2. **组件协调**:需要确保新组件之间的交互正确
|
||||
3. **测试覆盖**:需要确保所有路径都有充分的测试
|
||||
|
||||
### 建议
|
||||
1. 完整测试启动流程,包括各种边缘情况
|
||||
2. 测试多实例场景
|
||||
3. 测试重启场景(托盘、后台等)
|
||||
4. 启用启动诊断,验证诊断功能正常
|
||||
5. 测试超时场景
|
||||
286
docs/launcher_architecture_analysis.md
Normal file
286
docs/launcher_architecture_analysis.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# Launcher 架构拆分评估报告
|
||||
|
||||
## 1. 现状分析
|
||||
|
||||
### 1.1 Launcher 当前职责清单
|
||||
|
||||
根据代码审查,[LanMountainDesktop.Launcher](file:///d:/github/LanMountainDesktop/LanMountainDesktop.Launcher) 当前承担 **6 个主要职责域**:
|
||||
|
||||
| 职责域 | 核心文件 | 代码量 | 复杂度 |
|
||||
|--------|---------|--------|--------|
|
||||
| **OOBE 首次体验** | `OobeStateService`, `OobeWindow`, `WelcomeOobeStep`, `DataLocationOobeStep`, `PrivacyAgreementService` | ~28 KB | 中 |
|
||||
| **Splash / 启动协调** | `LauncherFlowCoordinator`, `SplashWindow`, `LoadingDetailsWindow`, `StartupAttemptRegistry` | ~120 KB | **极高** |
|
||||
| **更新引擎** | `UpdateEngineService`, `UpdateCheckService` | ~77 KB | **极高** |
|
||||
| **插件管理** | `PluginInstallerService`, `PluginUpgradeQueueService` | ~13 KB | 低 |
|
||||
| **部署/版本管理** | `DeploymentLocator`, `FlexibleHostLocator`, `DotNetRuntimeProbe`, `LegacyVersionDetector` | ~70 KB | 高 |
|
||||
| **Air APP 生命周期** | `AirApp/*`, `LauncherBackgroundService` | ~21 KB | 中 |
|
||||
|
||||
**总计:~673 KB 源代码,95 个 .cs/.axaml 文件**
|
||||
|
||||
### 1.2 关键耦合热点
|
||||
|
||||
#### 热点 1:[LauncherFlowCoordinator.cs](file:///d:/github/LanMountainDesktop/LanMountainDesktop.Launcher/Services/LauncherFlowCoordinator.cs) — **90 KB / 2034 行**
|
||||
|
||||
这是整个 Launcher 最大的单文件,负责:
|
||||
- OOBE → Splash → Update → Plugin → Host Launch 的完整编排
|
||||
- 多实例检测与协调 (IPC coordinator)
|
||||
- 主程序启动、进程监控、超时处理
|
||||
- 激活恢复 (activation recovery)
|
||||
- 所有 UI 窗口的生命周期管理
|
||||
|
||||
> [!WARNING]
|
||||
> 这个文件是当前最大的架构债务。它同时了解所有职责域,是修改任何启动行为都必须触碰的瓶颈文件。
|
||||
|
||||
#### 热点 2:[UpdateEngineService.cs](file:///d:/github/LanMountainDesktop/LanMountainDesktop.Launcher/Services/UpdateEngineService.cs) — **72 KB / 1850 行**
|
||||
|
||||
包含两套完整的更新应用流程(Legacy 和 PLONDS),内嵌:
|
||||
- 签名验证
|
||||
- 增量文件应用
|
||||
- SHA-256/SHA-512 校验
|
||||
- 回滚机制
|
||||
- 快照管理
|
||||
- 安装检查点与断点续传
|
||||
|
||||
#### 热点 3:[App.axaml.cs](file:///d:/github/LanMountainDesktop/LanMountainDesktop.Launcher/App.axaml.cs) — **34 KB / 850 行**
|
||||
|
||||
App 入口承担了过多的运行时编排逻辑,包括:
|
||||
- Coordinator IPC 服务器的创建和管理
|
||||
- Air APP IPC broker 模式
|
||||
- 主程序进程存活监控
|
||||
- 失败恢复 UI 流程
|
||||
|
||||
### 1.3 职责域间的依赖关系
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A["App.axaml.cs<br/>(入口编排)"] --> B["LauncherFlowCoordinator<br/>(流程协调)"]
|
||||
A --> C["Air APP Broker"]
|
||||
A --> D["Coordinator IPC"]
|
||||
B --> E["OobeStateService"]
|
||||
B --> F["UpdateEngineService"]
|
||||
B --> G["PluginInstallerService"]
|
||||
B --> H["DeploymentLocator"]
|
||||
B --> I["StartupAttemptRegistry"]
|
||||
B --> D
|
||||
F --> H
|
||||
G --> J["PluginUpgradeQueueService"]
|
||||
C --> K["LauncherAirAppLifecycleService"]
|
||||
|
||||
style A fill:#ff6b6b,color:#fff
|
||||
style B fill:#ff6b6b,color:#fff
|
||||
style F fill:#ff9f43,color:#fff
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 红色节点是耦合最严重的热点。`LauncherFlowCoordinator` 直接依赖几乎所有其他服务。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案评估
|
||||
|
||||
### Option A:多项目拆分
|
||||
|
||||
将 Launcher 拆分成独立的 .NET 项目/可执行文件:
|
||||
|
||||
| 拆分后的项目 | 职责 |
|
||||
|-------------|------|
|
||||
| `LanMountainDesktop.Launcher` | 精简入口,仅做 OOBE + Splash + 编排调度 |
|
||||
| `LanMountainDesktop.UpdateService` | 更新检查、下载、应用、回滚 |
|
||||
| `LanMountainDesktop.PluginService` | 插件安装、升级队列 |
|
||||
| `LanMountainDesktop.DeploymentManager` | 版本目录管理、主机发现 |
|
||||
|
||||
#### 优点
|
||||
- 最大化隔离:每个服务可独立部署、独立更新
|
||||
- 更新引擎可以在 Launcher 自身不运行时被调用(例如计划任务)
|
||||
- 故障隔离:插件安装崩溃不影响更新流程
|
||||
|
||||
#### 缺点
|
||||
|
||||
> [!CAUTION]
|
||||
> **这些缺点在当前阶段是致命的。**
|
||||
|
||||
- **进程间通信成本巨大**:当前 `LauncherFlowCoordinator` 的 2034 行编排逻辑严重依赖同进程内的同步/异步调用和共享状态(`TaskCompletionSource`、进程对象引用、UI Dispatcher 调度)。拆成多进程意味着每个交互点都需要 IPC 管道 + 序列化 + 超时处理 + 错误恢复。
|
||||
- **启动延迟增加**:当前 Launcher 启动到 Host 启动的路径已经很长(OOBE → 更新 → 插件 → 主机发现 → Host 进程启动 → IPC 握手)。多进程会在每个阶段增加进程启动开销。
|
||||
- **安装包膨胀**:每个独立可执行文件都需要自己的运行时依赖,即使共享 Avalonia SDK。
|
||||
- **复杂的部署协调**:Launcher 自身不可被拆分更新——它就是更新的入口。如果 `UpdateService` 是独立进程,谁来启动它?又需要一个 meta-launcher。
|
||||
- **当前代码并未准备好**:`LauncherFlowCoordinator.RunAsync()` 是一个巨大的异步方法,内部有十几个局部变量和闭包在多个 await 之间共享状态。这些状态不可能简单地序列化为 IPC 消息。
|
||||
|
||||
#### 改造工程量估算
|
||||
- **IPC 层**:需新增 ~8-10 个 IPC 契约、每个有请求/响应/通知消息
|
||||
- **进程管理**:需要为每个子服务编写进程启动、健康检查、重启逻辑
|
||||
- **状态同步**:`StartupAttemptRegistry` 的锁文件机制需要扩展为跨进程锁
|
||||
- **估计 3-5 人周**,且引入大量新的故障模式
|
||||
|
||||
---
|
||||
|
||||
### Option B:单项目内部解耦(推荐)
|
||||
|
||||
保持单一 Launcher 可执行文件,通过以下手段实现内部解耦:
|
||||
|
||||
#### 阶段 1:职责分层(重构目录结构)
|
||||
|
||||
```
|
||||
LanMountainDesktop.Launcher/
|
||||
├── Program.cs # 入口(保持精简)
|
||||
├── App.axaml.cs # Avalonia 应用(精简到 <200 行)
|
||||
├── Core/ # 核心编排层
|
||||
│ ├── LauncherOrchestrator.cs # 从 App.axaml.cs 提取的运行时编排
|
||||
│ ├── StartupPipeline.cs # 从 FlowCoordinator 提取的阶段管道
|
||||
│ └── StartupPhase.cs # 每个阶段的抽象接口
|
||||
├── Deployment/ # 版本管理域
|
||||
│ ├── DeploymentLocator.cs
|
||||
│ ├── FlexibleHostLocator.cs
|
||||
│ ├── HostLaunchPlan.cs
|
||||
│ ├── DotNetRuntimeProbe.cs
|
||||
│ └── LegacyVersionDetector.cs
|
||||
├── Update/ # 更新引擎域
|
||||
│ ├── UpdateEngineService.cs # 重构后 <400 行
|
||||
│ ├── LegacyUpdateApplier.cs # 从 UpdateEngine 提取
|
||||
│ ├── PlondsUpdateApplier.cs # 从 UpdateEngine 提取
|
||||
│ ├── SignatureVerifier.cs # 从 UpdateEngine 提取
|
||||
│ ├── UpdateCheckService.cs
|
||||
│ └── UpdateSnapshotManager.cs # 从 UpdateEngine 提取
|
||||
├── Plugin/ # 插件管理域
|
||||
│ ├── PluginInstallerService.cs
|
||||
│ └── PluginUpgradeQueueService.cs
|
||||
├── Oobe/ # OOBE 域
|
||||
│ ├── OobeStateService.cs
|
||||
│ ├── IOobeStep.cs
|
||||
│ ├── WelcomeOobeStep.cs
|
||||
│ ├── DataLocationOobeStep.cs
|
||||
│ └── PrivacyAgreementService.cs
|
||||
├── AirApp/ # Air APP 域(已部分独立)
|
||||
│ └── ...
|
||||
├── Coordination/ # 多实例协调域
|
||||
│ ├── StartupAttemptRegistry.cs
|
||||
│ ├── LauncherCoordinatorIpcServer.cs
|
||||
│ └── LauncherCoordinatorIpcClient.cs
|
||||
├── Views/ # UI 层
|
||||
│ └── ...
|
||||
├── ViewModels/ # ViewModel 层
|
||||
│ └── ...
|
||||
└── Models/ # 数据模型
|
||||
└── ...
|
||||
```
|
||||
|
||||
#### 阶段 2:拆分 LauncherFlowCoordinator
|
||||
|
||||
将 2034 行的 `RunAsync()` 重构为 Pipeline + Phase 模式:
|
||||
|
||||
```csharp
|
||||
// 启动管道定义(伪代码)
|
||||
public class StartupPipeline
|
||||
{
|
||||
private readonly IReadOnlyList<IStartupPhase> _phases;
|
||||
|
||||
public async Task<LauncherResult> ExecuteAsync(StartupContext context)
|
||||
{
|
||||
foreach (var phase in _phases)
|
||||
{
|
||||
var result = await phase.ExecuteAsync(context);
|
||||
if (!result.Continue) return result.LauncherResult;
|
||||
}
|
||||
return LauncherResult.Success();
|
||||
}
|
||||
}
|
||||
|
||||
// 各阶段独立实现
|
||||
public class CleanupPhase : IStartupPhase { ... }
|
||||
public class OobePhase : IStartupPhase { ... }
|
||||
public class UpdatePhase : IStartupPhase { ... }
|
||||
public class PluginUpgradePhase : IStartupPhase { ... }
|
||||
public class HostLaunchPhase : IStartupPhase { ... }
|
||||
public class StartupMonitorPhase : IStartupPhase { ... }
|
||||
```
|
||||
|
||||
#### 阶段 3:拆分 UpdateEngineService
|
||||
|
||||
将 1850 行的更新引擎拆分为独立的策略类:
|
||||
|
||||
```csharp
|
||||
// 更新引擎成为协调者,不再包含实现
|
||||
public class UpdateEngineService
|
||||
{
|
||||
private readonly IUpdateApplier _legacyApplier;
|
||||
private readonly IUpdateApplier _plondsApplier;
|
||||
private readonly ISignatureVerifier _signatureVerifier;
|
||||
private readonly IUpdateSnapshotManager _snapshotManager;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
#### 阶段 4:精简 App.axaml.cs
|
||||
|
||||
将 850 行的 App 入口精简为纯粹的 Avalonia 应用初始化 + 委托给 `LauncherOrchestrator`:
|
||||
|
||||
```csharp
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
var orchestrator = new LauncherOrchestrator(desktop, LauncherRuntimeContext.Current);
|
||||
_ = orchestrator.RunAsync();
|
||||
}
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
```
|
||||
|
||||
#### 优点
|
||||
- **零部署风险**:不改变安装包结构、不引入新进程、不改变 IPC 拓扑
|
||||
- **增量重构**:可以一个职责域一个域地逐步重构,每次重构都可编译验证
|
||||
- **测试友好**:拆分后的各 Phase 和 Service 可以独立单元测试
|
||||
- **保持启动性能**:单进程内的函数调用无 IPC 开销
|
||||
- **为未来多进程做准备**:如果将来真的需要拆分进程,接口已经清晰
|
||||
|
||||
#### 缺点
|
||||
- 仍然是单进程:更新引擎崩溃会影响 Launcher 进程
|
||||
- 需要自律维持架构边界(没有编译级隔离)
|
||||
|
||||
#### 改造工程量估算
|
||||
- 阶段 1(目录重组):~0.5 人天
|
||||
- 阶段 2(FlowCoordinator 拆分):~2-3 人天
|
||||
- 阶段 3(UpdateEngine 拆分):~1-2 人天
|
||||
- 阶段 4(App.axaml.cs 精简):~0.5-1 人天
|
||||
- **总计 ~4-7 人天**,且风险可控
|
||||
|
||||
---
|
||||
|
||||
## 3. 决策矩阵
|
||||
|
||||
| 维度 | Option A (多项目拆分) | Option B (内部解耦) |
|
||||
|------|---------------------|-------------------|
|
||||
| **改造风险** | 🔴 高:引入新 IPC、新故障模式 | 🟢 低:纯重构,行为不变 |
|
||||
| **改造工期** | 🔴 3-5 人周 | 🟢 4-7 人天 |
|
||||
| **启动性能** | 🔴 多进程启动开销 | 🟢 零额外开销 |
|
||||
| **故障隔离** | 🟢 进程级隔离 | 🟡 需靠代码纪律 |
|
||||
| **独立更新** | 🟢 各服务可独立版本 | 🔴 单一二进制 |
|
||||
| **可测试性** | 🟢 天然隔离 | 🟢 接口拆分后等效 |
|
||||
| **安装包大小** | 🔴 膨胀(多 EXE) | 🟢 不变 |
|
||||
| **部署复杂度** | 🔴 谁更新 Launcher? | 🟢 VeloPack 现有流程 |
|
||||
| **团队人力需求** | 🔴 需长期维护多套 IPC | 🟢 维护成本低 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 推荐方案
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **推荐 Option B:单项目内部解耦**,原因如下:
|
||||
|
||||
1. **当前阶段的核心瓶颈不是项目边界,而是文件级别的职责混乱**。`LauncherFlowCoordinator` 一个文件 2034 行,`UpdateEngineService` 一个文件 1850 行,`App.axaml.cs` 一个文件 850 行——这才是真正影响可维护性的问题。
|
||||
|
||||
2. **Launcher 的核心约束决定了它必须是单一入口**。根据 [ARCHITECTURE.md](file:///d:/github/LanMountainDesktop/docs/ARCHITECTURE.md) 的定义,Launcher 是 "应用的唯一入口",负责版本选择、原子化更新和安全启动。这个约束使得多进程拆分的价值大打折扣。
|
||||
|
||||
3. **已经存在良好的外部进程隔离**。Host 主程序 (`LanMountainDesktop.exe`)、Air APP Host (`LanMountainDesktop.AirAppHost`) 都是独立进程。Launcher 只需要作为协调者存在,它不需要自己也拆成多个进程。
|
||||
|
||||
4. **改造投入产出比**。Option A 需要 3-5 人周且引入新风险,Option B 需要 4-7 人天且零风险,效果(可维护性、可测试性)几乎等效。
|
||||
|
||||
---
|
||||
|
||||
## 5. Open Questions
|
||||
|
||||
1. **是否考虑将 Launcher 的 CLI 模式(`update check`、`update apply`、`plugin install`)独立成一个无 UI 的命令行工具?** 这是一个比全面拆分轻量得多的拆分点,可以让 CI/CD 和脚本调用不依赖 Avalonia 运行时。
|
||||
|
||||
2. **`UpdateEngineService` 是否打算支持 Launcher 自身的自更新?** 如果是,可能需要一个极简的 "bootstrap updater" 组件,这是唯一可能需要独立进程的场景。
|
||||
|
||||
3. **内部解耦后,是否要引入 `Microsoft.Extensions.DependencyInjection`?** 当前所有服务都是手动 `new` 的,引入 DI 容器可以自然地约束依赖方向,但也会增加 Launcher 启动路径的复杂度。
|
||||
|
||||
Reference in New Issue
Block a user