文档记录

This commit is contained in:
JSD\13999
2026-05-15 15:38:40 +08:00
parent d7b09891dc
commit 019703d2a8
18 changed files with 4221 additions and 1 deletions

View File

@@ -0,0 +1,156 @@
# P0-2: GameFlow 需求详细文档
## 对齐说明
本文档以 `docs/requirements/p0-requirements-set.md` 为准。GameFlow 是全局生命周期所有者,负责创建 Feature scope、FeatureContext并编排 Feature 的进入、切换和关闭。
## 目标
提供游戏启动、Feature 切换和关闭流程的编排器,保证生命周期顺序、失败清理、取消和非法状态防护。
## 状态机
```csharp
public enum GameFlowState
{
Idle,
Starting,
Running,
Switching,
NoActiveFeature,
ShuttingDown,
Disposed
}
```
状态转换:
```text
Idle -> Starting -> Running <-> Switching
\-> NoActiveFeature
Running -> ShuttingDown -> Disposed
NoActiveFeature -> Switching -> Running
NoActiveFeature -> ShuttingDown -> Disposed
```
非法状态调用抛 `InvalidOperationException`,错误必须包含当前状态和操作名。
## 接口
```csharp
public sealed class GameFlow
{
public GameFlowState State { get; }
public Task StartupAsync<TInitialFeature>(
Container root,
CancellationToken cancellationToken)
where TInitialFeature : IFeature;
public Task SwitchToAsync<TFeature>(
CancellationToken cancellationToken)
where TFeature : IFeature;
public Task ShutdownAsync(CancellationToken cancellationToken);
}
```
## 启动流程
```text
StartupAsync:
1. State = Starting
2. Resolve IConfigProvider
3. await config.LoadAllAsync(ct)
4. Resolve ISaveService
5. 加载或创建 P0 Sample 所需 Data
6. 注册 Data 到 root Container
7. 创建 TInitialFeature
8. 创建 Feature scope
9. 创建 FeatureContext
10. await feature.LoadAsync(context)
11. await feature.EnterAsync(context)
12. State = Running
```
失败规则:
- 配置加载失败清理已创建对象State 回到 Idle抛异常。
- 存档加载失败:使用默认 Data记录警告继续启动。
- Feature Load/Enter 失败:调用 Dispose 清理State 回到 Idle抛异常。
## Feature 切换流程
```text
SwitchToAsync:
1. State = Switching
2. await current.ExitAsync(currentContext)
3. current.Dispose()
4. Dispose current FeatureContext / scope / resources
5. 创建新 Feature、scope、FeatureContext
6. await next.LoadAsync(nextContext)
7. await next.EnterAsync(nextContext)
8. State = Running
```
失败规则:
- 旧 Feature `ExitAsync` 失败:记录错误,继续 Dispose。
- 旧 Feature `Dispose` 失败:记录错误,继续创建新 Feature。
- 新 Feature `LoadAsync` 失败:清理新 FeatureState = NoActiveFeature抛异常。
- 新 Feature `EnterAsync` 失败:调用新 Feature DisposeState = NoActiveFeature抛异常。
- 切换期间再次调用 `SwitchToAsync`P0 抛 `InvalidOperationException`,不排队。
## 关闭流程
```text
ShutdownAsync:
1. State = ShuttingDown
2. best-effort 调用当前 Feature ExitAsync
3. best-effort 调用当前 Feature Dispose
4. best-effort 保存必要 Data
5. Dispose root Container
6. State = Disposed
```
规则:
- `ShutdownAsync` 一旦进入关闭流程,必须尽量执行到底。
- 保存失败记录错误,不阻塞退出。
- Feature 退出/释放失败记录错误,不阻塞退出。
- Container 释放失败记录错误,不阻塞退出。
## 暂不做
- Feature 栈。
- 并行 Feature。
- Feature 预加载。
- 可配置启动任务列表。
- 切换请求队列。
- Starting/Switching 中断式 Shutdown。
## 验收标准
| # | 标准 | 通过条件 |
|---|------|---------|
| 1 | 正常启动 | Startup 完成后 State == Running初始 Feature 已 Load + Enter |
| 2 | 启动配置失败 | State 回到 Idle异常向上传播 |
| 3 | 启动存档失败 | 使用默认 Data记录警告继续启动 |
| 4 | 正常切换 | 旧 Feature 已 Exit/Dispose新 Feature 已 Load/Enter |
| 5 | 新 Feature Load 失败 | State == NoActiveFeature已清理新 Feature |
| 6 | 新 Feature Enter 失败 | State == NoActiveFeature已 Dispose 新 Feature |
| 7 | 关闭 best-effort | 保存或释放失败时仍进入 Disposed |
| 8 | 非法状态防护 | 非法调用抛异常并包含当前状态 |
| 9 | CancellationToken 传递 | FeatureContext 中可拿到同一个取消信号 |
## 依赖关系
```text
GameFlow
├── Container
├── IFeature
├── FeatureContext
├── IConfigProvider
├── ISaveService
└── IResourceService
```