mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-06 16:16:44 +08:00
fix(core): 收口 PR267 事件契约遗留问题
- 修复 AsyncLogAppender 接口刷新路径重复触发完成事件,并补充单次通知回归测试 - 补充 Architecture、CoroutineExceptionEventArgs 与阶段协调器的事件契约注释 - 更新 PhaseChanged 迁移文档与 analyzer-warning-reduction recovery 记录
This commit is contained in:
parent
8831cb42a8
commit
685897f2de
@ -377,7 +377,7 @@ public class CoroutineSchedulerTests
|
||||
var handle = _scheduler.Run(CreateExceptionCoroutine());
|
||||
|
||||
_scheduler.Update();
|
||||
var observation = await exceptionSource.Task;
|
||||
var observation = await exceptionSource.Task.WaitAsync(TimeSpan.FromSeconds(3));
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
|
||||
@ -103,6 +103,23 @@ public class AsyncLogAppenderTests
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ILogAppender_Flush_Should_Raise_OnFlushCompleted_Only_Once()
|
||||
{
|
||||
var innerAppender = new TestAppender();
|
||||
using var asyncAppender = new AsyncLogAppender(innerAppender, bufferSize: 10);
|
||||
ILogAppender logAppender = asyncAppender;
|
||||
var observedResults = new List<bool>();
|
||||
|
||||
asyncAppender.Append(new LogEntry(DateTime.UtcNow, LogLevel.Info, "TestLogger", "Interface flush check", null, null));
|
||||
asyncAppender.OnFlushCompleted += (_, eventArgs) => observedResults.Add(eventArgs.Success);
|
||||
|
||||
logAppender.Flush();
|
||||
|
||||
Assert.That(observedResults, Has.Count.EqualTo(1));
|
||||
Assert.That(observedResults, Has.All.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Dispose_ShouldProcessRemainingEntries()
|
||||
{
|
||||
|
||||
@ -99,8 +99,16 @@ public abstract class Architecture : IArchitecture
|
||||
public virtual Action<IServiceCollection>? Configurator => null;
|
||||
|
||||
/// <summary>
|
||||
/// 阶段变更事件(用于测试和扩展)
|
||||
/// 在架构生命周期阶段发生变化时触发。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// 订阅者应通过 <see cref="ArchitecturePhaseChangedEventArgs.Phase" /> 读取当前阶段,而不是依赖内部生命周期对象。
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// 事件委托中的 <c>sender</c> 始终为当前 <see cref="Architecture" /> 实例,便于测试与外部扩展保持稳定的发布者契约。
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public event EventHandler<ArchitecturePhaseChangedEventArgs>? PhaseChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -39,8 +39,8 @@ internal sealed class ArchitecturePhaseCoordinator(
|
||||
|
||||
/// <summary>
|
||||
/// 进入指定阶段并广播给所有阶段消费者。
|
||||
/// 顺序保持为“更新阶段值 → 生命周期钩子 → 容器中的阶段监听器 → 外部事件”,
|
||||
/// 以兼容既有调用约定。
|
||||
/// 顺序保持为“更新阶段值 → 生命周期钩子 → 容器中的阶段监听器”,
|
||||
/// 以保证框架扩展与运行时组件看到一致的阶段视图。
|
||||
/// </summary>
|
||||
/// <param name="next">目标阶段。</param>
|
||||
public void EnterPhase(ArchitecturePhase next)
|
||||
|
||||
@ -11,6 +11,7 @@ public sealed class CoroutineExceptionEventArgs : EventArgs
|
||||
/// </summary>
|
||||
/// <param name="handle">发生异常的协程句柄。</param>
|
||||
/// <param name="exception">协程执行过程中抛出的异常。</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="exception" /> 为 <see langword="null" />。</exception>
|
||||
public CoroutineExceptionEventArgs(CoroutineHandle handle, Exception exception)
|
||||
{
|
||||
Handle = handle;
|
||||
|
||||
@ -117,8 +117,7 @@ public sealed class AsyncLogAppender : ILogAppender
|
||||
/// </summary>
|
||||
void ILogAppender.Flush()
|
||||
{
|
||||
var success = Flush();
|
||||
OnFlushCompleted?.Invoke(this, new AsyncLogFlushCompletedEventArgs(success));
|
||||
Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -7,11 +7,13 @@
|
||||
|
||||
## 当前恢复点
|
||||
|
||||
- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-013`
|
||||
- 当前阶段:`Phase 13`
|
||||
- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-014`
|
||||
- 当前阶段:`Phase 14`
|
||||
- 当前焦点:
|
||||
- 当前 `MA0046` 主批次已在 `Architecture`、`AsyncLogAppender` 与 `CoroutineScheduler` 上收口完成
|
||||
- 下一轮优先从 `MA0016` 或 `MA0002` 中选择低风险批次继续推进;`MA0015` 与 `MA0077` 继续作为尾项顺手吸收
|
||||
- 当前分支 PR #267 的 latest CodeRabbit unresolved threads、outside-diff comment 与 nitpick comment 已完成本地复核
|
||||
- 本轮优先收口仍然成立的 follow-up:`AsyncLogAppender` 接口路径重复触发 `OnFlushCompleted`、事件/XML 契约缺口、
|
||||
`PhaseChanged` 迁移文档说明与 `ai-plan` 基线表述歧义
|
||||
- 下一轮默认恢复到 `MA0016` 或 `MA0002` 低风险批次;`MA0015` 与 `MA0077` 继续作为尾项顺手吸收
|
||||
- `GFramework.Godot` 的 `Timing.cs` 已同步适配新事件签名,但当前 worktree 的 Godot restore 资产仍受 Windows fallback package folder 干扰,独立 build 需在修复资产后补跑
|
||||
- 后续继续按 warning 类型和数量批处理,而不是回退到按单文件切片推进
|
||||
- 当某一轮主类型数量不足时,允许顺手合并其他低冲突 warning 类型,`MA0015` 与 `MA0077`
|
||||
@ -28,6 +30,8 @@
|
||||
- 已增强 `gframework-pr-review` 脚本与 skill 文档,降低超长 JSON 直出导致的 review 信号漏看风险
|
||||
- 已完成 `GFramework.Core` 当前 `MA0046` 批次:将阶段、协程与异步日志事件统一迁移到 `EventHandler<TEventArgs>` 形状,
|
||||
并同步更新 `GFramework.Godot` 订阅点、定向测试与 `docs/zh-CN` 示例
|
||||
- 已完成当前 PR #267 review follow-up:修复 `AsyncLogAppender` 的 `ILogAppender.Flush()` 双重完成通知,并补齐
|
||||
`PhaseChanged` / `CoroutineExceptionEventArgs` XML 文档、`PhaseChanged` 迁移说明和 `ai-plan` 基线注释
|
||||
- 当前 `GFramework.Core` `net8.0` warnings-only 基线已降到 `9` 条;剩余 warning 集中在
|
||||
`MA0016` 集合抽象接口、`MA0002` comparer 重载,以及 `MA0015` / `MA0077` 两个低数量尾项
|
||||
|
||||
@ -56,6 +60,8 @@
|
||||
让“先落盘、再定向抽取”成为默认可操作路径
|
||||
- `RP-013` 已完成 `GFramework.Core` 当前 `MA0046` 批次,并以新的事件参数类型替换阶段、协程和异步日志事件的
|
||||
非标准签名;`GFramework.Core` `net8.0` warnings-only 基线由 `15` 降至 `9`
|
||||
- `RP-014` 使用 `gframework-pr-review` 复核当前分支 PR #267 的 latest head review threads、outside-diff comment 与
|
||||
nitpick comment 后,确认 8 条高信号项中仍成立的是 1 个行为 bug 与 7 个文档/测试/跟踪缺口,并按最小改动收口
|
||||
- 当前工作树分支 `fix/analyzer-warning-reduction-batch` 已在 `ai-plan/public/README.md` 建立 topic 映射
|
||||
|
||||
## 当前风险
|
||||
@ -130,11 +136,19 @@
|
||||
- 结果:`0 Warning(s)`,`0 Error(s)`
|
||||
- `RP-013` 的定向验证结果:
|
||||
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -nologo -clp:"Summary;WarningsOnly"`
|
||||
- 结果:`9 Warning(s)`,`0 Error(s)`;当前 `GFramework.Core` `net8.0` warnings-only 输出中已不再出现 `MA0046`
|
||||
- 结果:`9 Warning(s)`,`0 Error(s)`;相对 `RP-009` / `RP-011` 的 warnings-only 基线 `15 Warning(s)` 已降到 `9 Warning(s)`,
|
||||
当前 `GFramework.Core` `net8.0` 输出中已不再出现 `MA0046`
|
||||
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~ArchitectureLifecycleBehaviorTests|FullyQualifiedName~CoroutineSchedulerTests|FullyQualifiedName~AsyncLogAppenderTests" -m:1 -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:`50 Passed`,`0 Failed`
|
||||
- `dotnet build GFramework.Godot/GFramework.Godot.csproj -c Release --no-restore -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:失败;当前 worktree 的 Godot restore 资产仍引用 Windows fallback package folder,尚未完成独立项目编译验证
|
||||
- `RP-014` 的定向验证结果:
|
||||
- `dotnet restore GFramework.Core.Tests/GFramework.Core.Tests.csproj -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:通过;host Windows `dotnet` 首次验证前补齐了缺失的 `Meziantou.Analyzer 3.0.48` 包
|
||||
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:`9 Warning(s)`,`0 Error(s)`;`AsyncLogAppender` 行为修复与 XML / 文档补充未引入新的 `GFramework.Core` `net8.0` 构建错误
|
||||
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-restore --filter "FullyQualifiedName~CoroutineSchedulerTests.Scheduler_Should_Raise_OnCoroutineException_With_EventArgs|FullyQualifiedName~AsyncLogAppenderTests.Flush_Should_Raise_OnFlushCompleted_With_Sender_And_Result|FullyQualifiedName~AsyncLogAppenderTests.ILogAppender_Flush_Should_Raise_OnFlushCompleted_Only_Once|FullyQualifiedName~ArchitectureLifecycleBehaviorTests.InitializeAsync_Should_Raise_PhaseChanged_With_Sender_And_EventArgs" -m:1 -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:`4 Passed`,`0 Failed`
|
||||
- active 跟踪文件只保留当前恢复点、活跃事实、风险与下一步,不再重复保存已完成阶段的长篇历史
|
||||
|
||||
## 下一步
|
||||
|
||||
@ -1,5 +1,37 @@
|
||||
# Analyzer Warning Reduction 追踪
|
||||
|
||||
## 2026-04-21 — RP-014
|
||||
|
||||
### 阶段:PR #267 review follow-up 收口(RP-014)
|
||||
|
||||
- 使用 `gframework-pr-review` 抓取当前分支 PR #267 的 latest head review threads、outside-diff comment、nitpick comment、
|
||||
MegaLinter 摘要与测试报告,并确认本轮除了 6 条 open thread 之外,还存在 1 条 outside-diff 与 1 条 nitpick 需要一并复核
|
||||
- 本地复核后确认仍成立的项:
|
||||
- `AsyncLogAppender` 的显式接口实现 `ILogAppender.Flush()` 会在调用 `Flush()` 后再次手动触发 `OnFlushCompleted`,
|
||||
导致接口路径重复通知
|
||||
- `Architecture.PhaseChanged`、`CoroutineExceptionEventArgs` 与 `ArchitecturePhaseCoordinator.EnterPhase` 的 XML/注释契约仍未完全同步
|
||||
- `CoroutineSchedulerTests` 的异常事件测试缺少测试级超时
|
||||
- `docs/zh-CN/core/architecture.md` 与 `docs/zh-CN/core/lifecycle.md` 仍缺少明确的 `PhaseChanged` 迁移说明
|
||||
- `ai-plan` active tracking 中 `RP-013` 的 `9 Warning(s)` 需要明确是相对 `RP-009` / `RP-011` 的 warnings-only 基线收敛
|
||||
- 实施最小修复:
|
||||
- 删除 `ILogAppender.Flush()` 中重复的完成事件触发,只保留 `Flush(TimeSpan?)` 内的单一通知源
|
||||
- 为接口调用路径补充单次完成通知回归测试,并为协程异常事件测试增加 `WaitAsync(TimeSpan.FromSeconds(3))`
|
||||
- 补齐 `Architecture.PhaseChanged`、`CoroutineExceptionEventArgs` 与 `ArchitecturePhaseCoordinator.EnterPhase` 的契约文档
|
||||
- 在 `docs/zh-CN/core/architecture.md` 与 `docs/zh-CN/core/lifecycle.md` 中加入 `phase => ...` 迁移到 `(_, args) => ...` 的说明
|
||||
- 更新 `ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md` 的恢复点、基线描述与验证结果
|
||||
- 验证结果:
|
||||
- `dotnet restore GFramework.Core.Tests/GFramework.Core.Tests.csproj -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:通过;host Windows `dotnet` 首次验证前补齐了缺失的 `Meziantou.Analyzer 3.0.48`
|
||||
- `dotnet build GFramework.Core/GFramework.Core.csproj -c Release --no-restore -p:TargetFramework=net8.0 -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:`9 Warning(s)`,`0 Error(s)`
|
||||
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-restore --filter "FullyQualifiedName~CoroutineSchedulerTests.Scheduler_Should_Raise_OnCoroutineException_With_EventArgs|FullyQualifiedName~AsyncLogAppenderTests.Flush_Should_Raise_OnFlushCompleted_With_Sender_And_Result|FullyQualifiedName~AsyncLogAppenderTests.ILogAppender_Flush_Should_Raise_OnFlushCompleted_Only_Once|FullyQualifiedName~ArchitectureLifecycleBehaviorTests.InitializeAsync_Should_Raise_PhaseChanged_With_Sender_And_EventArgs" -m:1 -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:`4 Passed`,`0 Failed`
|
||||
- 当前结论:
|
||||
- PR #267 里当前仍成立的 CodeRabbit 高信号项已在本地收口
|
||||
- 修复内容没有改变 `EventHandler<TEventArgs>` 迁移方向,只是补齐行为、文档与恢复信息
|
||||
- 下一步建议:
|
||||
- 恢复到 `MA0016` / `MA0002` 主批次,默认先看 `LoggingConfiguration`、`FilterConfiguration` 与 `CollectionExtensions`
|
||||
|
||||
## 2026-04-21 — RP-013
|
||||
|
||||
### 阶段:`MA0046` 事件签名批次收口(RP-013)
|
||||
|
||||
@ -126,10 +126,21 @@ protected override void OnInitialize()
|
||||
其中 `PhaseChanged` 现在遵循标准 `EventHandler<ArchitecturePhaseChangedEventArgs>` 约定,
|
||||
阶段值通过 `args.Phase` 读取。
|
||||
|
||||
如果你正在从旧版本迁移,需要把单参数写法 `phase => ...` 改成 `(_, args) => ...`,
|
||||
并通过 `ArchitecturePhaseChangedEventArgs.Phase` 读取阶段值。
|
||||
|
||||
如果你需要在 `Ready`、`Destroying` 等阶段执行横切逻辑,比起把这类逻辑塞进某个具体 `System`,更适合单独实现
|
||||
`IArchitectureLifecycleHook`。
|
||||
|
||||
```csharp
|
||||
architecture.PhaseChanged += (_, args) =>
|
||||
{
|
||||
if (args.Phase == ArchitecturePhase.Ready)
|
||||
{
|
||||
Console.WriteLine("Architecture ready from event.");
|
||||
}
|
||||
};
|
||||
|
||||
public sealed class MetricsHook : IArchitectureLifecycleHook
|
||||
{
|
||||
public void OnPhase(ArchitecturePhase phase, IArchitecture architecture)
|
||||
|
||||
@ -138,6 +138,9 @@ architecture.RegisterLifecycleHook(new MetricsHook());
|
||||
|
||||
如果你只需要观察阶段变化,也可以直接订阅:
|
||||
|
||||
如果你从旧版本的 `PhaseChanged` 迁移过来,需要把旧写法 `phase => ...` 改成 `(_, args) => ...`,
|
||||
并通过 `ArchitecturePhaseChangedEventArgs.Phase` 读取阶段值。
|
||||
|
||||
```csharp
|
||||
architecture.PhaseChanged += (_, args) =>
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user