Skip to content
bitzorcas
中EN

Concept

Workflow 工作流引擎架构概览:DAG 状态机与分布式任务调度

深入解析 BitzOrcas.Modern 自研轻量级工作流引擎内核,掌握流程图(WorkflowDefinition)、运行时实例(WorkflowInstance)、活动节点(Activity)与人工审批流。

Last updated

在传统的企业级业务系统中,业务流程流转往往依赖第三方沉重的 BPMN 框架(如 Camunda / Flowable),这带来了严重的架构包袱:

  • 引入庞大的 Java/Spring 依赖:运维成本飙升,无法与 .NET 10 Native AOT 与双 ORM 深度融合;
  • 难以处理异步长时间等待:例如“等待第三方支付成功”或“等待高管审批 3 天”,轮询数据库导致严重的 CPU 损耗;
  • 状态难以追溯:流程执行出错时无法精准还原历史快照与变量分支。

BitzOrcas.Modern 内置了自研纯 C#、Native AOT 原生兼容的轻量级工作流引擎:基于 DAG 拓扑定义与持久化状态机,支持毫秒级恢复与长时间审批挂起。

工作流引擎执行状态机全景

是 (需要审批)否 (直接放行)审批人同意/拒绝

1. 业务触发流程启动 (StartWorkflowCommand)

2. WorkflowEngine (加载 WorkflowDefinition 定义)

3. 创建 WorkflowInstance (状态: Running, 持久化入库)

4. 执行自动化 Activity (如: 自动校验 / 扣款)

5. 决策网关评估 (Gateway: 金额 > 50,000)

6. 创建 ApprovalTask + 挂起流程 (状态: Suspended)

7. 执行后续自动化节点

8. ApproveTaskCommand (恢复流程实例继续执行)

9. 流程实例正常归档 (状态: Completed)


第一步:核心领域模型 WorkflowInstance

流程实例采用统一聚合根范式,直接映射物理表 WfInstance:

WorkflowInstance.cs: 工作流实例聚合根
using System;
using System.Collections.Generic;
using System.ComponentModel;
using BitzOrcas.Domain.Entities;
using BitzOrcas.Domain.Results;
using BitzOrcas.Persistence.Metadata;
namespace BitzOrcas.Workflow.Domain;
public static class WorkflowErrors
{
public static readonly Error InvalidState =
Error.Conflict("Workflow.InvalidState", "非运行状态的流程无法挂起。");
public static readonly Error NotFound =
Error.NotFound("Workflow.NotFound", "流程实例不存在。");
}
[BitzTable("WfInstance", IsTenant = true, IsSoftDelete = true, Description = "工作流运行时实例表")]
public sealed class WorkflowInstance : TenantAggregateRoot<string>
{
[BitzColumn(Length = 64, IsRequired = true)]
public string DefinitionId { get; private set; } = string.Empty;
[BitzColumn(IsRequired = true)]
public WorkflowState State { get; private set; } = WorkflowState.Pending;
[BitzColumn(Length = 64)]
public string CurrentNodeId { get; private set; } = string.Empty;
// JSON 动态流程上下文变量(存储表单数据与计算结果)
[BitzColumn(IsJson = true)]
public Dictionary<string, object?> ContextVariables { get; private set; } = [];
[Obsolete("仅供 ORM 持久化物化使用。请使用 Create 工厂方法。", error: true)]
[EditorBrowsable(EditorBrowsableState.Never)]
public WorkflowInstance()
: base("0")
{
}
// 领域方法:挂起流程等待人工审批
public Result SuspendForApproval(string approvalNodeId, string candidateRole)
{
// 1. 检查状态机不变量
if (State != WorkflowState.Running)
{
return Result.Failure(WorkflowErrors.InvalidState);
}
// 2. 状态机切换
CurrentNodeId = approvalNodeId;
State = WorkflowState.Suspended;
// 3. 发布审批任务就绪领域事件
AddDomainEvent(new ApprovalTaskCreatedDomainEvent(Id, TenantId, approvalNodeId, candidateRole));
return Result.Success();
}
}

第二步:审批命令垂直切片(ApproveTaskCommandHandler)

ApproveTaskCommandHandler.cs: 审批命令执行器
using System.Threading;
using System.Threading.Tasks;
using BitzOrcas.Application.Abstractions.Security;
using BitzOrcas.Domain.Abstractions;
using BitzOrcas.Domain.Results;
using BitzOrcas.Workflow.Domain;
public sealed class ApproveTaskCommandHandler(
ICommandRepository<WorkflowInstance, string> workflowRepo,
IWorkflowEngine workflowEngine,
ICurrentUser currentUser)
{
public async ValueTask<Result> Handle(ApproveTaskCommand command, CancellationToken ct)
{
// 1. 加载目标流程实例
var instanceResult = await workflowRepo.FindAsync(command.WorkflowInstanceId, ct);
if (instanceResult.IsFailure)
{
return Result.Failure(WorkflowErrors.NotFound);
}
var instance = instanceResult.Value;
// 2. 评估当前操作人的审批权限并记录审批意见
instance.ContextVariables["LastApproverId"] = currentUser.UserId;
instance.ContextVariables["ApprovalComment"] = command.Comment;
// 3. 唤醒流程引擎继续沿 DAG 拓扑执行后续节点
var resumeResult = await workflowEngine.ResumeAsync(instance, command.Decision, ct);
if (resumeResult.IsFailure) return resumeResult;
// 4. 持久化聚合(由 TransactionPipeline 自动提交)
await workflowRepo.UpdateAsync(instance, ct);
return Result.Success();
}
}

总结

BitzOrcas 自研工作流引擎兼具极简与高性能:

  • AOT 原生兼容:纯 C# 编写,零 JVM 依赖,启动毫秒级;
  • 状态持久化安全:每个节点流转由本地事务强一致保证;
  • 长周期无损挂起:挂起状态零 CPU 占用,支持跨月跨年超长业务流。

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%