diff --git a/.github/workflows/dotnet-build.yml b/.github/workflows/dotnet-build.yml index d1794a4..5d148cc 100644 --- a/.github/workflows/dotnet-build.yml +++ b/.github/workflows/dotnet-build.yml @@ -8,7 +8,16 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v6 + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: | + 3.1.x + 6.0.x + 8.0.x + 9.0.x + 10.0.x - name: Build with dotnet run: dotnet build --configuration Release diff --git a/.github/workflows/nuget-tag-publish.yml b/.github/workflows/nuget-tag-publish.yml index 2a0cc6f..a0f6af1 100644 --- a/.github/workflows/nuget-tag-publish.yml +++ b/.github/workflows/nuget-tag-publish.yml @@ -11,7 +11,19 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v6 + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: | + 3.1.x + 6.0.x + 8.0.x + 9.0.x + 10.0.x + + - name: Add .NET global tools to PATH + run: echo "$HOME/.dotnet/tools" >> $GITHUB_PATH - name: Install dotnet tool run: dotnet tool install -g dotnetCampus.TagToVersion @@ -24,16 +36,10 @@ jobs: dotnet build --configuration Release dotnet pack --configuration Release --no-build - - name: Install Nuget - uses: nuget/setup-nuget@v1 - with: - nuget-version: '5.x' - - - name: Add private GitHub registry to NuGet - run: | - nuget sources add -name github -Source https://nuget.pkg.github.com/dotnet-campus/index.json -Username dotnet-campus -Password ${{ secrets.GITHUB_TOKEN }} - - - name: Push generated package to GitHub registry + - name: Publish run: | - nuget push .\bin\Release\*.nupkg -Source github -SkipDuplicate - nuget push .\bin\Release\*.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NugetKey }} + dotnet nuget push ".\bin\Release\*.nupkg" --api-key ${{ secrets.NugetKey }} --source https://api.nuget.org/v3/index.json --skip-duplicate + dotnet nuget push ".\bin\Release\*.nupkg" \ + --api-key ${{ secrets.GITHUB_TOKEN }} \ + --source https://nuget.pkg.github.com/${{ github.repository_owner }} \ + --skip-duplicate \ No newline at end of file diff --git a/src/LightWorkFlowManager.Tests/MessageWorkerManagerTest.cs b/src/LightWorkFlowManager.Tests/MessageWorkerManagerTest.cs index e2ca92a..b10c1ab 100644 --- a/src/LightWorkFlowManager.Tests/MessageWorkerManagerTest.cs +++ b/src/LightWorkFlowManager.Tests/MessageWorkerManagerTest.cs @@ -12,11 +12,17 @@ namespace LightWorkFlowManager.Tests; +/// +/// `MessageWorkerManager` 相关测试。 +/// [TestClass] public class MessageWorkerManagerTest { private const int UnknownError = 7000; + /// + /// 验证工作器管理器在失败、重试与异常场景下的行为。 + /// [ContractTestCase] public void RunFail() { @@ -120,6 +126,14 @@ await Assert.ThrowsExceptionAsync(async () }); } + /// + /// 创建用于测试的工作器管理器。 + /// + /// 可选的服务提供器。 + /// 可选的任务标识。 + /// 可选的任务名称。 + /// 重试次数。 + /// 测试用工作器管理器实例。 public static MessageWorkerManager GetTestMessageWorkerManager(IServiceProvider? serviceProvider = null, string? taskId = null, string? taskName = null, int retryCount = 3) { @@ -128,6 +142,10 @@ public static MessageWorkerManager GetTestMessageWorkerManager(IServiceProvider? return messageWorkerManager; } + /// + /// 构建测试用服务提供器。 + /// + /// 测试用服务提供器实例。 public static IServiceProvider BuildServiceProvider() { var serviceCollection = new ServiceCollection(); diff --git a/src/LightWorkFlowManager.Tests/MessageWorkerTest.cs b/src/LightWorkFlowManager.Tests/MessageWorkerTest.cs index 91df4dd..741d04f 100644 --- a/src/LightWorkFlowManager.Tests/MessageWorkerTest.cs +++ b/src/LightWorkFlowManager.Tests/MessageWorkerTest.cs @@ -11,9 +11,15 @@ namespace LightWorkFlowManager.Tests; +/// +/// `MessageWorker` 相关测试。 +/// [TestClass] public class MessageWorkerTest { + /// + /// 验证工作器内部可以继续运行其他工作器。 + /// [ContractTestCase] public void RunWorkerOnWorker() { diff --git a/src/LightWorkFlowManager.Tests/ProgressCompositorTest.cs b/src/LightWorkFlowManager.Tests/ProgressCompositorTest.cs index 04ca90f..aa76072 100644 --- a/src/LightWorkFlowManager.Tests/ProgressCompositorTest.cs +++ b/src/LightWorkFlowManager.Tests/ProgressCompositorTest.cs @@ -6,9 +6,15 @@ namespace LightWorkFlowManager.Tests; +/// +/// `ProgressCompositor` 相关测试。 +/// [TestClass] public class ProgressCompositorTest { + /// + /// 验证子进度合成后的进度计算结果。 + /// [ContractTestCase] public void TestSubProgressReport() { diff --git a/src/LightWorkFlowManager/Contexts/IWorkerContext.cs b/src/LightWorkFlowManager/Contexts/IWorkerContext.cs index 52520c8..f9ca996 100644 --- a/src/LightWorkFlowManager/Contexts/IWorkerContext.cs +++ b/src/LightWorkFlowManager/Contexts/IWorkerContext.cs @@ -11,15 +11,15 @@ public interface IWorkerContext /// /// 获取上下文信息 /// - /// - /// 如果获取不到,返回空 + /// 上下文类型。 + /// 如果获取不到则返回空。 T? GetContext(); /// /// 设置上下文信息 /// - /// - /// + /// 上下文类型。 + /// 要保存的上下文对象。 void SetContext(T context); } @@ -31,9 +31,9 @@ public static class MessageContextExtension /// /// 获取一定存在的上下文信息 /// - /// - /// - /// + /// 上下文类型。 + /// 工作器上下文。 + /// 已存在的上下文对象。 /// 如果上下文信息不存在,就抛出异常 public static T GetEnsureContext(this IWorkerContext workerContext) { diff --git a/src/LightWorkFlowManager/Contexts/WorkFlowErrorCode.cs b/src/LightWorkFlowManager/Contexts/WorkFlowErrorCode.cs index df0467b..7bd6f55 100644 --- a/src/LightWorkFlowManager/Contexts/WorkFlowErrorCode.cs +++ b/src/LightWorkFlowManager/Contexts/WorkFlowErrorCode.cs @@ -12,6 +12,8 @@ namespace DC.LightWorkFlowManager.Contexts; /// /// 创建错误码 /// + /// 错误码数值。 + /// 错误码对应的可读信息。 public WorkFlowErrorCode(int code, string message) { Code = code; @@ -38,8 +40,8 @@ public WorkFlowErrorCode(int code, string message) /// /// 追加信息 /// - /// - /// + /// 要追加的描述信息。 + /// 追加描述后的错误码。 public WorkFlowErrorCode AppendMessage(string? appendMessage) { if (appendMessage == null) @@ -55,7 +57,8 @@ public WorkFlowErrorCode AppendMessage(string? appendMessage) /// /// 隐式转换为 int 类型 /// - /// + /// 工作流错误码。 + /// 错误码数值。 public static implicit operator int(WorkFlowErrorCode code) { return code.Code; @@ -64,7 +67,8 @@ public static implicit operator int(WorkFlowErrorCode code) /// /// 从 int 类型隐式转换为错误信息 /// - /// + /// 错误码数值。 + /// 对应的工作流错误码。 public static implicit operator WorkFlowErrorCode(int code) { if (ErrorCodeDictionary.TryGetValue(code, out var value)) @@ -107,9 +111,9 @@ public override int GetHashCode() /// /// 判断相等 /// - /// - /// - /// + /// 左侧错误码。 + /// 右侧错误码。 + /// 两个错误码是否相等。 public static bool operator ==(WorkFlowErrorCode left, WorkFlowErrorCode right) { return left.Equals(right); @@ -118,9 +122,9 @@ public override int GetHashCode() /// /// 判断不相等 /// - /// - /// - /// + /// 左侧错误码。 + /// 右侧错误码。 + /// 两个错误码是否不相等。 public static bool operator !=(WorkFlowErrorCode left, WorkFlowErrorCode right) { return !left.Equals(right); diff --git a/src/LightWorkFlowManager/Contexts/WorkerContext.cs b/src/LightWorkFlowManager/Contexts/WorkerContext.cs index e1f5a23..84f38bc 100644 --- a/src/LightWorkFlowManager/Contexts/WorkerContext.cs +++ b/src/LightWorkFlowManager/Contexts/WorkerContext.cs @@ -3,8 +3,12 @@ namespace DC.LightWorkFlowManager.Contexts; +/// +/// 提供基于类型索引的工作器上下文实现。 +/// public class WorkerContext : IWorkerContext { + /// [System.Diagnostics.DebuggerStepThrough] public T? GetContext() { @@ -16,6 +20,7 @@ public class WorkerContext : IWorkerContext return default; } + /// public void SetContext(T context) { _contextDictionary[typeof(T)] = context; diff --git a/src/LightWorkFlowManager/Exceptions/MessageWorkerException.cs b/src/LightWorkFlowManager/Exceptions/MessageWorkerException.cs index 2114fef..ff8de22 100644 --- a/src/LightWorkFlowManager/Exceptions/MessageWorkerException.cs +++ b/src/LightWorkFlowManager/Exceptions/MessageWorkerException.cs @@ -11,7 +11,7 @@ public class MessageWorkerException : WorkFlowException /// /// 工作过程的异常 /// - /// + /// 工作流错误码。 /// 默认 false 表示不能重试 public MessageWorkerException(WorkFlowErrorCode errorCode, bool canRetryWorker = false) { @@ -22,6 +22,8 @@ public MessageWorkerException(WorkFlowErrorCode errorCode, bool canRetryWorker = /// /// 工作过程的异常 /// + /// 工作流错误码。 + /// 导致当前异常的内部异常。 public MessageWorkerException(WorkFlowErrorCode errorCode, Exception innerException) : base(errorCode.Message, innerException) { ErrorCode = errorCode; @@ -32,7 +34,12 @@ public MessageWorkerException(WorkFlowErrorCode errorCode, Exception innerExcept /// 是否可以重试 /// public bool CanRetryWorker { get; } + + /// + /// 获取当前异常对应的工作流错误码。 + /// public WorkFlowErrorCode ErrorCode { get; } + /// public override string Message => ErrorCode.Message; } diff --git a/src/LightWorkFlowManager/Exceptions/MessageWorkerInputArgumentException.cs b/src/LightWorkFlowManager/Exceptions/MessageWorkerInputArgumentException.cs index c694ad6..bf628bb 100644 --- a/src/LightWorkFlowManager/Exceptions/MessageWorkerInputArgumentException.cs +++ b/src/LightWorkFlowManager/Exceptions/MessageWorkerInputArgumentException.cs @@ -7,6 +7,10 @@ namespace DC.LightWorkFlowManager.Exceptions; /// public class MessageWorkerInputArgumentException : MessageWorkerException { + /// + /// 使用指定错误码初始化输入参数异常。 + /// + /// 输入参数错误对应的工作流错误码。 public MessageWorkerInputArgumentException(WorkFlowErrorCode errorCode) : base(errorCode,canRetryWorker: false) { } diff --git a/src/LightWorkFlowManager/Exceptions/MessageWorkerInputNotFoundException.cs b/src/LightWorkFlowManager/Exceptions/MessageWorkerInputNotFoundException.cs index c8deada..f859232 100644 --- a/src/LightWorkFlowManager/Exceptions/MessageWorkerInputNotFoundException.cs +++ b/src/LightWorkFlowManager/Exceptions/MessageWorkerInputNotFoundException.cs @@ -7,6 +7,10 @@ namespace DC.LightWorkFlowManager.Exceptions; /// public class MessageWorkerInputNotFoundException : InvalidOperationException, IWorkFlowException { + /// + /// 使用指定错误消息初始化异常。 + /// + /// 异常消息。 public MessageWorkerInputNotFoundException(string? message) : base(message) { } diff --git a/src/LightWorkFlowManager/Exceptions/WorkFlowException.cs b/src/LightWorkFlowManager/Exceptions/WorkFlowException.cs index a01c6ac..26a04b4 100644 --- a/src/LightWorkFlowManager/Exceptions/WorkFlowException.cs +++ b/src/LightWorkFlowManager/Exceptions/WorkFlowException.cs @@ -8,18 +8,35 @@ namespace DC.LightWorkFlowManager.Exceptions; /// public abstract class WorkFlowException : Exception, IWorkFlowException { + /// + /// 初始化工作流异常。 + /// protected WorkFlowException() { } + /// + /// 使用序列化信息初始化工作流异常。 + /// + /// 保存序列化对象数据的对象。 + /// 有关源或目标的上下文信息。 protected WorkFlowException(SerializationInfo info, StreamingContext context) : base(info, context) { } + /// + /// 使用指定错误消息初始化工作流异常。 + /// + /// 异常消息。 protected WorkFlowException(string? message) : base(message) { } + /// + /// 使用指定错误消息和内部异常初始化工作流异常。 + /// + /// 异常消息。 + /// 导致当前异常的内部异常。 protected WorkFlowException(string? message, Exception? innerException) : base(message, innerException) { } diff --git a/src/LightWorkFlowManager/Exceptions/WorkerContextNotFoundException.cs b/src/LightWorkFlowManager/Exceptions/WorkerContextNotFoundException.cs index c228b9c..c9a2db4 100644 --- a/src/LightWorkFlowManager/Exceptions/WorkerContextNotFoundException.cs +++ b/src/LightWorkFlowManager/Exceptions/WorkerContextNotFoundException.cs @@ -1,13 +1,24 @@ namespace DC.LightWorkFlowManager.Exceptions; +/// +/// 表示无法从工作器上下文中找到指定类型数据的异常。 +/// public class WorkerContextNotFoundException : WorkFlowException { + /// + /// 使用缺失的上下文键初始化异常。 + /// + /// 缺失的上下文键。 public WorkerContextNotFoundException(string key) { Key = key; } + /// + /// 获取缺失的上下文键。 + /// public string Key { get; } + /// public override string Message => $"Can not find {Key}"; } diff --git a/src/LightWorkFlowManager/MessageWorkerManager.cs b/src/LightWorkFlowManager/MessageWorkerManager.cs index bb21760..5875322 100644 --- a/src/LightWorkFlowManager/MessageWorkerManager.cs +++ b/src/LightWorkFlowManager/MessageWorkerManager.cs @@ -22,12 +22,12 @@ public class MessageWorkerManager : IAsyncDisposable /// /// 创建工作器管理 /// - /// + /// 任务标识。 /// 任务名,任务类型,如 PDF 解析或 PPT 解析等 - /// + /// 用于解析工作器与依赖项的服务作用域。 /// 每个工作器的失败重试次数,默认三次 /// 参数上下文信息 - /// + /// 工作器运行监控器。 public MessageWorkerManager(string taskId, string taskName, IServiceScope serviceScope, int retryCount = 3, IWorkerContext? context = null, IWorkerRunMonitor? workerRunMonitor = null) { @@ -99,9 +99,9 @@ public MessageWorkerManager(string taskId, string taskName, IServiceScope servic /// /// 设置上下文信息。设计上要求一个类型对应一个参数,不允许相同的类型作为不同的参数 /// - /// - /// - /// + /// 上下文类型。 + /// 要保存的上下文对象。 + /// 当前工作器管理器。 public MessageWorkerManager SetContext(T context) { Context.SetContext(context); @@ -113,9 +113,9 @@ public MessageWorkerManager SetContext(T context) /// /// 现有的参数类型 /// 转换后的参数类型 - /// + /// 参数转换委托。 /// 如果前置步骤失败,即 为 IsFail 时,将不执行委托内容 - /// + /// 当前工作器管理器。 public MessageWorkerManager SetContext(Func worker) { if (MessageWorkerStatus.IsFail) @@ -133,8 +133,8 @@ public MessageWorkerManager SetContext(Func wo /// /// 获取工作器,获取到的工作器将会被注入信息 /// - /// - /// + /// 工作器类型。 + /// 已注入管理器信息的工作器实例。 public T GetWorker() where T : IMessageWorker { var messageWorker = ServiceProvider.GetRequiredService(); @@ -145,12 +145,12 @@ public T GetWorker() where T : IMessageWorker /// /// 执行委托工作器,执行的内容为 参数的内容 /// - /// - /// - /// + /// 输入参数类型。 + /// 输出参数类型。 + /// 同步执行委托。 /// 此委托代表的工作器名,用于调试和埋点上报 /// 是否在当前 前置步骤已失败时,依然可以执行。默认为 false 表示在前置步骤失败时,不执行 - /// + /// 工作器执行结果。 public ValueTask RunWorker(Func messageTask, string? workerName = null, bool canRunWhenFail = false) { var worker = new DelegateMessageWorker(messageTask, workerName ?? messageTask.Method.DeclaringType?.FullName, canRunWhenFail); @@ -160,12 +160,12 @@ public ValueTask RunWorker(Func /// /// 执行委托工作器,执行的内容为 参数的内容 /// - /// - /// - /// + /// 输入参数类型。 + /// 输出参数类型。 + /// 异步执行委托。 /// 此委托代表的工作器名,用于调试和埋点上报 /// 是否在当前 前置步骤已失败时,依然可以执行。默认为 false 表示在前置步骤失败时,不执行 - /// + /// 工作器执行结果。 public ValueTask RunWorker(Func> messageTask, string? workerName = null, bool canRunWhenFail = false) { var worker = new DelegateMessageWorker(messageTask, workerName ?? messageTask.Method.DeclaringType?.FullName, canRunWhenFail); @@ -175,11 +175,11 @@ public ValueTask RunWorker(Func /// 执行委托工作器,执行的内容为 参数的内容 /// - /// - /// + /// 输入参数类型。 + /// 异步执行委托。 /// 此委托代表的工作器名,用于调试和埋点上报 /// 是否在当前 前置步骤已失败时,依然可以执行。默认为 false 表示在前置步骤失败时,不执行 - /// + /// 工作器执行结果。 public ValueTask RunWorker(Func messageTask, string? workerName = null, bool canRunWhenFail = false) { var worker = new DelegateMessageWorker(messageTask, workerName ?? messageTask.Method.DeclaringType?.FullName, canRunWhenFail); @@ -189,10 +189,10 @@ public ValueTask RunWorker(Func message /// /// 执行委托工作器,执行的内容为 参数的内容 /// - /// + /// 异步执行委托。 /// 此委托代表的工作器名,用于调试和埋点上报 /// 是否在当前 前置步骤已失败时,依然可以执行。默认为 false 表示在前置步骤失败时,不执行 - /// + /// 工作器执行结果。 public ValueTask RunWorker(Func messageTask, string? workerName = null, bool canRunWhenFail = false) { var worker = new DelegateMessageWorker(_ => messageTask(), workerName ?? messageTask.Method.DeclaringType?.FullName, canRunWhenFail); @@ -202,11 +202,11 @@ public ValueTask RunWorker(Func messageTask, string? wo /// /// 执行委托工作器,执行的内容为 参数的内容 /// - /// - /// + /// 输入参数类型。 + /// 同步执行委托。 /// 此委托代表的工作器名,用于调试和埋点上报 /// 是否在当前 前置步骤已失败时,依然可以执行。默认为 false 表示在前置步骤失败时,不执行 - /// + /// 工作器执行结果。 public ValueTask RunWorker(Action messageTask, string? workerName = null, bool canRunWhenFail = false) { var worker = new DelegateMessageWorker(input => @@ -220,10 +220,10 @@ public ValueTask RunWorker(Action messageTask, str /// /// 执行委托工作器,执行的内容为 参数的内容 /// - /// + /// 同步执行委托。 /// 此委托代表的工作器名,用于调试和埋点上报 /// 是否在当前 前置步骤已失败时,依然可以执行。默认为 false 表示在前置步骤失败时,不执行 - /// + /// 工作器执行结果。 public ValueTask RunWorker(Action messageTask, string? workerName = null, bool canRunWhenFail = false) { var worker = new DelegateMessageWorker(messageTask, workerName ?? messageTask.Method.DeclaringType?.FullName, canRunWhenFail); @@ -233,10 +233,10 @@ public ValueTask RunWorker(Action messageTask, str /// /// 执行委托工作器,执行的内容为 参数的内容 /// - /// + /// 同步执行委托。 /// 此委托代表的工作器名,用于调试和埋点上报 /// 是否在当前 前置步骤已失败时,依然可以执行。默认为 false 表示在前置步骤失败时,不执行 - /// + /// 工作器执行结果。 public ValueTask RunWorker(Action messageTask, string? workerName = null, bool canRunWhenFail = false) { var worker = new DelegateMessageWorker(_ => messageTask(), workerName ?? messageTask.Method.DeclaringType?.FullName, canRunWhenFail); @@ -246,10 +246,10 @@ public ValueTask RunWorker(Action messageTask, string? workerName /// /// 执行委托工作器,执行的内容为 参数的内容 /// - /// + /// 异步执行委托。 /// 此委托代表的工作器名,用于调试和埋点上报 /// 是否在当前 前置步骤已失败时,依然可以执行。默认为 false 表示在前置步骤失败时,不执行 - /// + /// 工作器执行结果。 public ValueTask RunWorker(Func messageTask, string? workerName = null, bool canRunWhenFail = false) { var worker = new DelegateMessageWorker(messageTask, workerName ?? messageTask.Method.DeclaringType?.FullName, canRunWhenFail); @@ -259,8 +259,8 @@ public ValueTask RunWorker(Func message /// /// 执行工作器 /// - /// - /// + /// 工作器类型。 + /// 工作器执行结果。 public ValueTask RunWorker() where TWorker : IMessageWorker { var worker = ServiceProvider.GetRequiredService(); @@ -270,8 +270,8 @@ public ValueTask RunWorker() where TWorker : IMessageWork /// /// 执行工作器 /// - /// - /// + /// 要执行的工作器。 + /// 工作器执行结果。 public virtual async ValueTask RunWorker(IMessageWorker worker) { SetManager(worker as IMessageWorkerManagerSensitive); @@ -508,6 +508,10 @@ internal WorkerResult GetFailResult() canRetry: false); } + /// + /// 异步释放当前管理器持有的工作器和服务作用域。 + /// + /// 表示异步释放操作的任务。 public async ValueTask DisposeAsync() { while (_workerStack.TryPop(out var worker)) diff --git a/src/LightWorkFlowManager/Monitors/IWorkerRunMonitor.cs b/src/LightWorkFlowManager/Monitors/IWorkerRunMonitor.cs index 6d2f2b2..79a40d0 100644 --- a/src/LightWorkFlowManager/Monitors/IWorkerRunMonitor.cs +++ b/src/LightWorkFlowManager/Monitors/IWorkerRunMonitor.cs @@ -4,9 +4,28 @@ namespace DC.LightWorkFlowManager.Monitors; +/// +/// 提供工作器执行过程的监控回调。 +/// public interface IWorkerRunMonitor { + /// + /// 在工作器开始执行时调用。 + /// + /// 即将执行的工作器。 void OnWorkerStart(IMessageWorker worker); + + /// + /// 在工作器执行完成时调用。 + /// + /// 已执行完成的工作器。 + /// 工作器执行结果。 void OnWorkerFinish(IMessageWorker worker, WorkerResult result); + + /// + /// 在工作器执行出现异常时调用。 + /// + /// 发生异常的工作器。 + /// 执行过程中抛出的异常。 void OnWorkerException(IMessageWorker worker, Exception exception); } diff --git a/src/LightWorkFlowManager/Monitors/Progress/ProgressCompositor.cs b/src/LightWorkFlowManager/Monitors/Progress/ProgressCompositor.cs index bb218ee..beef029 100644 --- a/src/LightWorkFlowManager/Monitors/Progress/ProgressCompositor.cs +++ b/src/LightWorkFlowManager/Monitors/Progress/ProgressCompositor.cs @@ -6,7 +6,7 @@ namespace DC.LightWorkFlowManager.Monitors; /// /// 进度合成器,允许包含多个子进度 /// -/// +/// 随进度一起上报的数据类型。 /// 规则: /// - 可以注册多个子进度,每个子进度都有自己的权值 /// - 子进度的进度贡献到上级进度时,将叠加上子进度自己的权值。如占比一半权值的子进度,就最多只贡献一半的进度 @@ -16,7 +16,7 @@ public class ProgressCompositor /// /// 创建进度合成器 /// - /// + /// 进度名。 public ProgressCompositor(string name) { Name = name; @@ -88,6 +88,11 @@ public IReadOnlyList> RegisterSubProgressCompositors(IRead return subProgressList; } + /// + /// 注册单个子进度合成器。 + /// + /// 子进度注册信息。 + /// 创建出的子进度合成器。 public ProgressCompositor RegisterSubProgressCompositor(SubProgressCompositorInfo subProgressCompositor) { var progressCompositor = new ProgressCompositor(subProgressCompositor.Name); @@ -109,8 +114,8 @@ private void SubProgressCompositor_Reported(object? sender, ProgressReportedEven /// /// 上报进度 /// - /// - /// + /// 当前进度值。 + /// 随进度上报的数据。 public void Report(ProgressPercentage percentage, T? value = default) { _selfProgressPercentage = percentage; @@ -127,8 +132,8 @@ public void Report(ProgressPercentage percentage, T? value = default) /// /// 上报增量进度,将叠加上当前的进度 /// - /// - /// + /// 要增加的进度值。 + /// 随进度上报的数据。 public void ReportIncreased(ProgressPercentage percentage, T? value = default) { var currentPercentageValue = _selfProgressPercentage.Value + percentage.Value; diff --git a/src/LightWorkFlowManager/Monitors/Progress/ProgressPercentage.cs b/src/LightWorkFlowManager/Monitors/Progress/ProgressPercentage.cs index 343e896..1aa4ff5 100644 --- a/src/LightWorkFlowManager/Monitors/Progress/ProgressPercentage.cs +++ b/src/LightWorkFlowManager/Monitors/Progress/ProgressPercentage.cs @@ -10,7 +10,7 @@ public readonly record struct ProgressPercentage /// /// 进度百分比 0-1 范围 /// - /// + /// 进度值,范围在 0 到 1 之间。 public ProgressPercentage(double value) { Value = value; @@ -22,9 +22,18 @@ public ProgressPercentage(double value) } } + /// + /// 获取当前进度值。 + /// public double Value { get; init; } + /// + /// 获取最小进度值。 + /// public static ProgressPercentage MinValue => new ProgressPercentage(0); + /// + /// 获取最大进度值。 + /// public static ProgressPercentage MaxValue => new ProgressPercentage(1); } \ No newline at end of file diff --git a/src/LightWorkFlowManager/Monitors/Progress/ProgressReportedEventArgument.cs b/src/LightWorkFlowManager/Monitors/Progress/ProgressReportedEventArgument.cs index 2864f41..1354d7b 100644 --- a/src/LightWorkFlowManager/Monitors/Progress/ProgressReportedEventArgument.cs +++ b/src/LightWorkFlowManager/Monitors/Progress/ProgressReportedEventArgument.cs @@ -1,3 +1,29 @@ namespace DC.LightWorkFlowManager.Monitors; -public readonly record struct ProgressReportedEventArgument(ProgressPercentage ProgressPercentage, T? Value); \ No newline at end of file +/// +/// 表示进度上报事件参数。 +/// +/// 随进度一同上报的数据类型。 +public readonly record struct ProgressReportedEventArgument +{ + /// + /// 初始化进度上报事件参数。 + /// + /// 当前进度值。 + /// 随进度上报的数据。 + public ProgressReportedEventArgument(ProgressPercentage progressPercentage, T? value) + { + ProgressPercentage = progressPercentage; + Value = value; + } + + /// + /// 获取当前进度值。 + /// + public ProgressPercentage ProgressPercentage { get; init; } + + /// + /// 获取随进度上报的数据。 + /// + public T? Value { get; init; } +} diff --git a/src/LightWorkFlowManager/Monitors/Progress/SubProgressCompositorInfo.cs b/src/LightWorkFlowManager/Monitors/Progress/SubProgressCompositorInfo.cs index 03b177c..fd02f7d 100644 --- a/src/LightWorkFlowManager/Monitors/Progress/SubProgressCompositorInfo.cs +++ b/src/LightWorkFlowManager/Monitors/Progress/SubProgressCompositorInfo.cs @@ -1,3 +1,28 @@ namespace DC.LightWorkFlowManager.Monitors; -public readonly record struct SubProgressCompositorInfo(string Name, double Weight); \ No newline at end of file +/// +/// 表示子进度合成器的注册信息。 +/// +public readonly record struct SubProgressCompositorInfo +{ + /// + /// 初始化子进度合成器信息。 + /// + /// 子进度名称。 + /// 子进度权重。 + public SubProgressCompositorInfo(string name, double weight) + { + Name = name; + Weight = weight; + } + + /// + /// 获取子进度名称。 + /// + public string Name { get; init; } + + /// + /// 获取子进度权重。 + /// + public double Weight { get; init; } +} diff --git a/src/LightWorkFlowManager/Protocols/MessageWorkerStatus.cs b/src/LightWorkFlowManager/Protocols/MessageWorkerStatus.cs index 9ed4063..550e3ae 100644 --- a/src/LightWorkFlowManager/Protocols/MessageWorkerStatus.cs +++ b/src/LightWorkFlowManager/Protocols/MessageWorkerStatus.cs @@ -4,12 +4,24 @@ namespace DC.LightWorkFlowManager.Protocols; +/// +/// 表示工作流管理器的当前执行状态。 +/// public class MessageWorkerStatus { + /// + /// 获取当前状态是否为失败。 + /// public bool IsFail => Status != WorkFlowErrorCode.Ok; + /// + /// 获取当前记录的状态码。 + /// public WorkFlowErrorCode Status { get; private set; } = WorkFlowErrorCode.Ok; + /// + /// 获取或设置最后一次异常。 + /// public Exception? LastException { get; set; } /// @@ -17,8 +29,18 @@ public class MessageWorkerStatus /// public IMessageWorker? FailWorker { get; private set; } + /// + /// 设置当前状态码。 + /// + /// 要设置的状态码。 public void SetErrorCode(WorkFlowErrorCode errorCode) => Status = errorCode; + /// + /// 在当前尚未失败时尝试记录失败状态。 + /// + /// 失败状态码。 + /// 触发失败的工作器。 + /// 如果成功记录失败状态则返回 ;否则返回 public bool TrySetErrorCode(WorkFlowErrorCode errorCode, IMessageWorker failWorker) { if (IsFail) @@ -32,6 +54,7 @@ public bool TrySetErrorCode(WorkFlowErrorCode errorCode, IMessageWorker failWork return true; } + /// public override string ToString() { if (IsFail) diff --git a/src/LightWorkFlowManager/Protocols/WorkerResult.cs b/src/LightWorkFlowManager/Protocols/WorkerResult.cs index 389f85e..3f292ce 100644 --- a/src/LightWorkFlowManager/Protocols/WorkerResult.cs +++ b/src/LightWorkFlowManager/Protocols/WorkerResult.cs @@ -4,8 +4,17 @@ namespace DC.LightWorkFlowManager.Protocols; +/// +/// 表示工作器执行结果。 +/// public class WorkerResult { + /// + /// 创建工作器执行结果。 + /// + /// 是否执行成功。 + /// 执行失败时的错误码。 + /// 执行失败后是否允许重试。 public WorkerResult(bool isSuccess, WorkFlowErrorCode errorCode, bool canRetry) { IsSuccess = isSuccess; @@ -18,10 +27,19 @@ public WorkerResult(bool isSuccess, WorkFlowErrorCode errorCode, bool canRetry) } } + /// + /// 获取当前执行是否成功。 + /// public virtual bool IsSuccess { get; } + /// + /// 获取当前执行是否失败。 + /// public bool IsFail => !IsSuccess; + /// + /// 获取执行失败时的错误码。 + /// public WorkFlowErrorCode ErrorCode { get; } /// @@ -29,9 +47,21 @@ public WorkerResult(bool isSuccess, WorkFlowErrorCode errorCode, bool canRetry) /// public bool CanRetry { get; } + /// + /// 创建一个成功结果。 + /// + /// 表示成功的执行结果。 public static WorkerResult Success() => new WorkerResult(true, WorkFlowErrorCode.Ok, false); + + /// + /// 创建一个失败结果。 + /// + /// 失败时的错误码。 + /// 失败后是否允许重试。 + /// 表示失败的执行结果。 public static WorkerResult Fail(WorkFlowErrorCode errorCode, bool canRetry=true) => new WorkerResult(false, errorCode, canRetry); + /// public override string ToString() { if (IsSuccess) @@ -45,29 +75,60 @@ public override string ToString() } } +/// +/// 表示带返回值的工作器执行结果。 +/// +/// 结果值类型。 public class WorkerResult : WorkerResult { + /// + /// 创建一个成功的执行结果。 + /// + /// 工作器输出结果。 public WorkerResult(T result) : base(isSuccess: true, WorkFlowErrorCode.Ok, canRetry: false) { Result = result; } + /// + /// 创建一个失败的执行结果。 + /// + /// 失败时的错误码。 + /// 失败后是否允许重试。 public WorkerResult(WorkFlowErrorCode errorCode, bool canRetry) : base(isSuccess: false, errorCode, canRetry) { Result = default; } + /// + /// 获取当前执行是否成功。 + /// [MemberNotNullWhen(true, nameof(Result))] public override bool IsSuccess => Result != null; + + /// + /// 获取工作器输出结果。 + /// public T? Result { get; } + /// + /// 将输出结果隐式转换为成功的执行结果。 + /// + /// 输出结果。 + /// 包装后的执行结果。 public static implicit operator WorkerResult(T workerResult) { return new WorkerResult(workerResult); } + /// + /// 从执行结果中隐式获取输出结果。 + /// + /// 执行结果。 + /// 输出结果。 public static implicit operator T?(WorkerResult workerResult) => workerResult.Result; + /// public override string ToString() { if (IsSuccess) diff --git a/src/LightWorkFlowManager/Workers/DelegateMessageWorker.cs b/src/LightWorkFlowManager/Workers/DelegateMessageWorker.cs index 46e9aab..1bd3f94 100644 --- a/src/LightWorkFlowManager/Workers/DelegateMessageWorker.cs +++ b/src/LightWorkFlowManager/Workers/DelegateMessageWorker.cs @@ -5,8 +5,18 @@ namespace DC.LightWorkFlowManager.Workers; +/// +/// 表示基于委托实现的单输入工作器。 +/// +/// 输入参数类型。 public class DelegateMessageWorker : MessageWorker { + /// + /// 使用异步委托初始化工作器。 + /// + /// 实际执行逻辑。 + /// 工作器名称。 + /// 当前置步骤失败时是否仍可运行。 public DelegateMessageWorker(Func messageTask, string? workerName = null, bool canRunWhenFail = false) { _messageTask = messageTask; @@ -15,6 +25,7 @@ public DelegateMessageWorker(Func messageTask, string? worker CanRunWhenFail = canRunWhenFail; } + /// public override string WorkerName => _workerName ?? base.WorkerName; private readonly string? _workerName; @@ -28,8 +39,19 @@ protected override async ValueTask DoAsync(TInput input) private readonly Func _messageTask; } +/// +/// 表示基于委托实现的输入输出工作器。 +/// +/// 输入参数类型。 +/// 输出参数类型。 public class DelegateMessageWorker : MessageWorker { + /// + /// 使用同步委托初始化工作器。 + /// + /// 实际执行逻辑。 + /// 工作器名称。 + /// 当前置步骤失败时是否仍可运行。 public DelegateMessageWorker(Func messageTask, string? workerName = null, bool canRunWhenFail = false) { _workerName = workerName; @@ -42,6 +64,12 @@ public DelegateMessageWorker(Func messageTask, string? workerNa CanRunWhenFail = canRunWhenFail; } + /// + /// 使用异步委托初始化工作器。 + /// + /// 实际执行逻辑。 + /// 工作器名称。 + /// 当前置步骤失败时是否仍可运行。 public DelegateMessageWorker(Func> messageTask, string? workerName = null, bool canRunWhenFail = false) { _messageTask = messageTask; @@ -57,13 +85,23 @@ protected override async ValueTask> DoInnerAsync(TInput in private readonly Func> _messageTask; + /// public override string WorkerName => _workerName ?? base.WorkerName; private readonly string? _workerName; } +/// +/// 表示基于委托实现的无固定输入工作器。 +/// public class DelegateMessageWorker : MessageWorkerBase { + /// + /// 使用同步委托初始化工作器。 + /// + /// 实际执行逻辑。 + /// 工作器名称。 + /// 当前置步骤失败时是否仍可运行。 public DelegateMessageWorker(Action messageAction, string? workerName = null, bool canRunWhenFail=false) { _messageTask = c => @@ -76,6 +114,12 @@ public DelegateMessageWorker(Action messageAction, string? worke CanRunWhenFail = canRunWhenFail; } + /// + /// 使用异步委托初始化工作器。 + /// + /// 实际执行逻辑。 + /// 工作器名称。 + /// 当前置步骤失败时是否仍可运行。 public DelegateMessageWorker(Func messageTask, string? workerName = null, bool canRunWhenFail=false) { _messageTask = async c => @@ -88,6 +132,12 @@ public DelegateMessageWorker(Func messageTask, string CanRunWhenFail = canRunWhenFail; } + /// + /// 使用返回执行结果的异步委托初始化工作器。 + /// + /// 实际执行逻辑。 + /// 工作器名称。 + /// 当前置步骤失败时是否仍可运行。 public DelegateMessageWorker(Func> messageTask, string? workerName = null, bool canRunWhenFail = false) { _messageTask = messageTask; @@ -96,12 +146,14 @@ public DelegateMessageWorker(Func> messa CanRunWhenFail = canRunWhenFail; } + /// public override string WorkerName => _workerName ?? base.WorkerName; private readonly string? _workerName; private readonly Func> _messageTask; + /// public override ValueTask Do(IWorkerContext context) { return _messageTask(context); diff --git a/src/LightWorkFlowManager/Workers/IMessageWorker.cs b/src/LightWorkFlowManager/Workers/IMessageWorker.cs index ef2755b..f8d7fe5 100644 --- a/src/LightWorkFlowManager/Workers/IMessageWorker.cs +++ b/src/LightWorkFlowManager/Workers/IMessageWorker.cs @@ -10,6 +10,9 @@ namespace DC.LightWorkFlowManager.Workers; /// public interface IMessageWorker { + /// + /// 获取或设置当前任务标识。 + /// string TaskId { get; set; } /// @@ -36,10 +39,19 @@ public interface IMessageWorker /// /// 遇到失败时,是否能执行 /// - /// bool CanRunWhenFail { get; } + /// + /// 执行当前工作器。 + /// + /// 工作器上下文。 + /// 工作器执行结果。 ValueTask Do(IWorkerContext context); + /// + /// 在工作器被释放时执行清理逻辑。 + /// + /// 工作器上下文。 + /// 表示异步清理操作的任务。 ValueTask OnDisposeAsync(IWorkerContext context); } diff --git a/src/LightWorkFlowManager/Workers/MessageWorker.cs b/src/LightWorkFlowManager/Workers/MessageWorker.cs index d757911..114eed3 100644 --- a/src/LightWorkFlowManager/Workers/MessageWorker.cs +++ b/src/LightWorkFlowManager/Workers/MessageWorker.cs @@ -6,8 +6,13 @@ namespace DC.LightWorkFlowManager.Workers; +/// +/// 表示需要单个输入参数的工作器基类。 +/// +/// 输入参数类型。 public abstract class MessageWorker : MessageWorkerBase { + /// public sealed override ValueTask Do(IWorkerContext context) { var input = context.GetContext(); @@ -23,6 +28,11 @@ public sealed override ValueTask Do(IWorkerContext context) protected abstract ValueTask DoAsync(TInput input); } +/// +/// 表示带输入与输出参数的工作器基类。 +/// +/// 输入参数类型。 +/// 输出参数类型。 public abstract class MessageWorker : MessageWorker { protected sealed override async ValueTask DoAsync(TInput input) @@ -37,6 +47,12 @@ protected sealed override async ValueTask DoAsync(TInput input) return output; } + /// + /// 使用当前上下文中的参数转换为输入后运行工作器。 + /// + /// 当前上下文中的参数类型。 + /// 将上下文参数转换为输入参数的委托。 + /// 带输出结果的工作器执行结果。 public ValueTask> RunAsync(Func converter) { var argument = CurrentContext.GetEnsureContext(); @@ -44,6 +60,11 @@ public ValueTask> RunAsync(Func + /// 使用指定输入参数运行工作器。 + /// + /// 工作器输入参数。 + /// 带输出结果的工作器执行结果。 public ValueTask> RunAsync(TInput input) { ThrowNotManager(); @@ -52,6 +73,10 @@ public ValueTask> RunAsync(TInput input) return RunAsync(); } + /// + /// 使用当前上下文运行工作器并返回输出结果。 + /// + /// 带输出结果的工作器执行结果。 public new async ValueTask> RunAsync() { ThrowNotManager(); diff --git a/src/LightWorkFlowManager/Workers/MessageWorkerBase.cs b/src/LightWorkFlowManager/Workers/MessageWorkerBase.cs index 1223f8c..ec7b318 100644 --- a/src/LightWorkFlowManager/Workers/MessageWorkerBase.cs +++ b/src/LightWorkFlowManager/Workers/MessageWorkerBase.cs @@ -12,7 +12,12 @@ namespace DC.LightWorkFlowManager.Workers; /// public abstract class MessageWorkerBase : IMessageWorker, IMessageWorkerManagerSensitive { + /// public string TaskId { get; set; } = null!; + + /// + /// 获取当前工作器名称。 + /// public virtual string WorkerName => GetType().Name; /// @@ -20,6 +25,9 @@ public abstract class MessageWorkerBase : IMessageWorker, IMessageWorkerManagerS /// public virtual bool CanRetry { protected set; get; } = true; + /// + /// 获取重试前的等待时间。 + /// public virtual TimeSpan RetryDelayTime => TimeSpan.FromSeconds(1); /// @@ -29,11 +37,16 @@ public abstract class MessageWorkerBase : IMessageWorker, IMessageWorkerManagerS // 默认遇到错误不能运行 = false; + /// public abstract ValueTask Do(IWorkerContext context); protected MessageWorkerStatus Status => GetEnsureContext(); protected IWorkerContext CurrentContext => Manager.Context; protected IServiceProvider ServiceProvider => Manager.ServiceProvider; + + /// + /// 获取当前工作器使用的日志器。 + /// public ILogger Logger { get; private set; } // 框架注入 = null!; @@ -62,6 +75,10 @@ protected T GetScopeWithContext() where T:notnull protected T? GetContext() => CurrentContext.GetContext(); protected void SetContext(T context) => CurrentContext.SetContext(context); + /// + /// 通过当前管理器执行当前工作器。 + /// + /// 工作器执行结果。 public async ValueTask RunAsync() { ThrowNotManager(); @@ -70,6 +87,7 @@ public async ValueTask RunAsync() return result; } + /// public async ValueTask OnDisposeAsync(IWorkerContext context) { if (_onDispose != null)