mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-21 09:45:48 +08:00
- 新增 IGearTaskEventBus 接口及默认实现,用于解耦执行器与记录器、UI 投影等消费者 - 新增 IGearTaskResumable 接口,支持任务节点内部恢复(如 Pathing 任务可恢复至特定路径点) - 重构任务执行流程,使用 GearTaskExecutionRunner 替代旧的 GearTaskExecutionManager - 实现基于磁盘 JSON 的历史记录存储(IGearTaskHistoryStore),支持执行记录的保存、加载与清理 - 为 PathingGearTask 添加恢复能力,通过 PathingGearTaskResumeState 记录断点状态 - 在 PathExecutor 中集成运行时事件通知,支持路径点进入、完成、传送等事件的发布 - 统一执行事件模型(GearTaskExecutionEvent),包含任务定义、节点路径、时间戳等元数据 - 服务注册更新,使用新的执行器、事件总线、历史记录器等组件
98 lines
2.6 KiB
C#
98 lines
2.6 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using Microsoft.Extensions.Logging;
|
||
|
||
namespace BetterGenshinImpact.Service.GearTask.Execution;
|
||
|
||
/// <summary>
|
||
/// 默认事件总线实现。
|
||
/// 当前采用进程内同步分发,借由消费者内部自行决定是否异步缓冲。
|
||
/// </summary>
|
||
public sealed class GearTaskEventBus : IGearTaskEventBus
|
||
{
|
||
private readonly ILogger<GearTaskEventBus> _logger;
|
||
private readonly object _gate = new();
|
||
private readonly List<IGearTaskEventConsumer> _consumers = [];
|
||
|
||
public GearTaskEventBus(ILogger<GearTaskEventBus> logger)
|
||
{
|
||
_logger = logger;
|
||
}
|
||
|
||
public ValueTask PublishAsync(GearTaskExecutionEvent evt, CancellationToken ct = default)
|
||
{
|
||
IGearTaskEventConsumer[] snapshot;
|
||
lock (_gate)
|
||
{
|
||
// 先拷贝快照,避免消费者在回调期间订阅或退订影响当前广播。
|
||
snapshot = _consumers.ToArray();
|
||
}
|
||
|
||
return PublishCoreAsync(snapshot, evt, ct);
|
||
}
|
||
|
||
public IDisposable Subscribe(IGearTaskEventConsumer consumer)
|
||
{
|
||
lock (_gate)
|
||
{
|
||
_consumers.Add(consumer);
|
||
}
|
||
|
||
return new Subscription(this, consumer);
|
||
}
|
||
|
||
private async ValueTask PublishCoreAsync(IEnumerable<IGearTaskEventConsumer> consumers, GearTaskExecutionEvent evt, CancellationToken ct)
|
||
{
|
||
foreach (var consumer in consumers)
|
||
{
|
||
try
|
||
{
|
||
await consumer.ConsumeAsync(evt, ct);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex,
|
||
"GearTask 事件消费者处理失败,已隔离该异常。Consumer: {ConsumerType}, Event: {EventType}, RecordId: {RecordId}",
|
||
consumer.GetType().Name,
|
||
evt.GetType().Name,
|
||
evt.RecordId);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void Unsubscribe(IGearTaskEventConsumer consumer)
|
||
{
|
||
lock (_gate)
|
||
{
|
||
_consumers.Remove(consumer);
|
||
}
|
||
}
|
||
|
||
private sealed class Subscription : IDisposable
|
||
{
|
||
private readonly GearTaskEventBus _bus;
|
||
private readonly IGearTaskEventConsumer _consumer;
|
||
private bool _disposed;
|
||
|
||
public Subscription(GearTaskEventBus bus, IGearTaskEventConsumer consumer)
|
||
{
|
||
_bus = bus;
|
||
_consumer = consumer;
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
if (_disposed)
|
||
{
|
||
return;
|
||
}
|
||
|
||
_disposed = true;
|
||
_bus.Unsubscribe(_consumer);
|
||
}
|
||
}
|
||
}
|