一个超轻量级工作流引擎:Workflow-Core
近期工作上有一个工作流的开发需求,自己基于面向对象和职责链模式捣鼓了一套小框架,后来在github上发现一个轻量级的工作流引擎轮子:Workflow-Core,看完其wiki之后决定放弃之前自己造的轮子,使用这个开源项目来改造,也就有了这一篇博文。
01
—
关于Workflow-Core
Workflow-Core是一个基于.NET Standard的轻量级工作流引擎,其GitHub地址为:https://github.com/danielgerlag/workflow-core,目前有超过1200+个star。它提供了FluentAPI、多任务、持久化以及并行处理的功能,适合于小型工作流、责任链的需求开发。
由于Workflow-Core支持工作流长期运行,因此Workflow-Core支持以下多种数据源格式的持久化,可以通过安装不同的Provider包来实现对应的持久化:
内存(默认提供,用于测试和开发)
MongoDB
MS SQL Server
MySql
Sqlite
Redis
PostgreSQL
立刻上手把,Nuget上安装一把,目前最新版本2.0.0:
PM> Install-Package WorkflowCore
02
—
Workflow-Core 基础使用
1、Hello World
这里创建了一个.NET Core控制台应用程序,快速演示第一个Workflow-Core的Hello World,展示如何开始一个Workflow:
(1)定义一个实现IWorkflow接口的Workflow:
public class HelloWorldWorkflow : IWorkflow { public string Id => "HelloWorld"; public int Version => 1; public void Build(IWorkflowBuilder<object> builder) { builder .StartWith<HelloWorld>() .Then<ActiveWorld>() .Then<GoodbyeWorld>(); } }
这里定义了一个HelloWorldWorkflow,其版本号为1,它有3个步骤:HelloWorld、ActiveWorld和GoodbyeWorld,会依次执行。
(2)定义三个继承自StepBody类的步骤类:
public class HelloWorld : StepBody { public override ExecutionResult Run(IStepExecutionContext context) { Console.WriteLine("Hello World!"); return ExecutionResult.Next(); } } public class ActiveWorld : StepBody { public override ExecutionResult Run(IStepExecutionContext context) { Console.WriteLine("I am activing in the World!"); return ExecutionResult.Next(); } } public class GoodbyeWorld : StepBody { public override ExecutionResult Run(IStepExecutionContext context) { Console.WriteLine("Goodbye World!"); return ExecutionResult.Next(); } } (3)ServiceCollection中注入Workflow-Core相关组件 private static IServiceProvider ConfigureServices() { IServiceCollection services = new ServiceCollection(); services.AddLogging(); // WorkflowCore需要用到logging service services.AddWorkflow(); var serviceProvider = services.BuildServiceProvider(); return serviceProvider; }
(4)在Program.cs的Main方法中获取到注入的host并执行工作流
public static void Main(string[] args) { var serviceProvider = ConfigureServices(); var host = serviceProvider.GetService<IWorkflowHost>(); host.RegisterWorkflow<HelloWorldWorkflow>(); host.Start(); // Demo1:Hello World host.StartWorkflow("HelloWorld"); Console.ReadKey(); host.Stop(); }
这里传入的是Workflow的Id,Workflow-Core会根据Id去自动匹配最新版本的对应Workflow,运行结果如下:
2、无处不在的If
在工作流处理中,往往会有很多的条件判断,那么在Workflow-Core中也提供了直接的If功能,如下面这个IfStatementWorkflow所示:
public class IfStatementWorkflow : IWorkflow<MyData> { public string Id => "if-sample"; public int Version => 1; public void Build(IWorkflowBuilder<MyData> builder) { builder .StartWith<SayHello>() .If(data => data.Counter < 3).Do(then => then .StartWith<PrintMessage>() .Input(step => step.Message, data => "Outcome is less than 3") ) .If(data => data.Counter < 5).Do(then => then .StartWith<PrintMessage>() .Input(step => step.Message, data => "Outcome is less than 5") ) .Then<SayGoodbye>(); } }
这个传递进来的MyData的定义如下:
public class MyData { public int Counter { get; set; } }
当传递进来的MyData的Counter属性<3 或 <5时会有不同的分支进行逻辑的处理。
3、MySQL持久化支持
想要将工作流配置持久化到MySQL,只需以下两步:
(1)通过Nuget安装MySQL Provider包:
PM> Install-Package WorkflowCore.Persistence.MySQL
(2)注入到ServiceCollection
services.AddWorkflow(x => x.UseMySQL(@"Server=127.0.0.1;Database=workflow;User=root;Password=password;", true, true));
一旦启动,你就会发现Workflow-Core自动帮你创建了很多表用于持久化工作流配置和实例。
4、计划任务和循环任务
Workflow-Core还继承了计划任务和循环任务的功能:
(1)计划任务:比如在工作流步骤中设置一个延迟5分钟执行的计划任务
builder .StartWith(context => Console.WriteLine("Hello")) .Schedule(data => TimeSpan.FromSeconds(5)).Do(schedule => schedule .StartWith(context => Console.WriteLine("Doing scheduled tasks")) ) .Then(context => Console.WriteLine("Doing normal tasks"));
(2)循环任务:比如在工作流步骤中设置一个延迟5分钟进行的循环任务,知道Counter > 5才结束
builder .StartWith(context => Console.WriteLine("Hello")) .Recur(data => TimeSpan.FromSeconds(5), data => data.Counter > 5).Do(recur => recur .StartWith(context => Console.WriteLine("Doing recurring task")) ) .Then(context => Console.WriteLine("Carry on"));
5、Saga支持
了解分布式事务方案的童鞋应该都知道Saga,在Workflow-Core中也有支持,这是一个十分有用的功能:
(1)比如:在创建一个客户信息之后,将其推送到Salesforce和ERP,如果推送过程中发生了错误,那么就通过重试进行补偿,并且重试有时间间隔。
builder .StartWith<CreateCustomer>() .Then<PushToSalesforce>() .OnError(WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10)) .Then<PushToERP>() .OnError(WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10));
(2)又比如:当Task2发生异常时,Workflow-Core会帮助执行UndoTask2 和 UndoTask1 帮你回滚数据以恢复状态。
builder .StartWith<LogStart>() .Saga(saga => saga .StartWith<Task1>() .CompensateWith<UndoTask1>() .Then<Task2>() .CompensateWith<UndoTask2>() .Then<Task3>() .CompensateWith<UndoTask3>() ) .OnError(Models.WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10)) .Then<LogEnd>();
更多Saga示例,请参考:https://github.com/danielgerlag/workflow-core/tree/master/src/samples/WorkflowCore.Sample17
03
—
ASP.NET Core中使用Workflow-Core
1、注入与初始化
(1)注入:使用AddWorkflow()扩展方法
public void ConfigureServices(IServiceCollection services) { services.AddWorkflow(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
(2)初始化:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { ....... app.UseWorkflow(); }
扩展方法如下:
public static class ConfigureExtensions { public static IApplicationBuilder UseWorkflow(this IApplicationBuilder app) { var host = app.ApplicationServices.GetService<IWorkflowHost>(); host.RegisterWorkflow<EdcWorkflow>(); host.RegisterWorkflow<EdcDataWorkflow, EdcData>(); host.Start(); var appLifetime = app.ApplicationServices.GetService<IApplicationLifetime>(); appLifetime.ApplicationStopping.Register(() => { host.Stop(); }); return app; } }
这里需要注意的就是:将你要用到的所有Workflow都事先进行Register注册。
在你想要用到的地方,无论是Controller还是Service,通过依赖注入获取到Host,并使用它:
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { private IWorkflowController _workflowService; public ValuesController(IWorkflowController workflowService) { _workflowService = workflowService; } // GET api/values [HttpGet] public async Task<IEnumerable<string>> Get() { await _workflowService.StartWorkflow("EdcWorkflow"); return new string[] { "EdcWorkflow v1" }; } // GET api/values/5 [HttpGet("{id}")] public async Task<string> Get(int id) { await _workflowService.StartWorkflow("EdcDataWorkflow", new EdcData() { Id = id }); return "EdcDataWorkflow v1"; } }
这两个Workflow的定义如下:
public class EdcWorkflow : IWorkflow { public string Id => "EdcWorkflow"; public int Version => 1; public void Build(IWorkflowBuilder<object> builder) { builder .StartWith<HelloWorld>() .Then<GoodbyeWorld>(); } } public class EdcDataWorkflow : IWorkflow<EdcData> { public string Id => "EdcDataWorkflow"; public int Version => 1; public void Build(IWorkflowBuilder<EdcData> builder) { builder .StartWith<HelloWorld>() .If(data => data.Id < 3).Do(then => then .StartWith<PrintMessage>() .Input(step => step.Message, data => "Passed Id is less than 3") ) .If(data => data.Id < 5).Do(then => then .StartWith<PrintMessage>() .Input(step => step.Message, data => "Passed Id is less than 5") ) .Then<GoodbyeWorld>(); } }
示例结果很简单:
(1)api/values
(2)api/values/1
04
—
小结
Workflow-Core是一个适合.NET Core的优秀的轻量级工作流引擎,对于小型工作流和责任链类型的需求开发很适合,可以节约大量时间避免重复造轮子,将时间主要花在业务逻辑上面。当然,这里演示的示例只是众多功能特性中的一小部分,我只是选取了我用到的部分而已,大家有兴趣的话可以去GitHub上先给个star再仔细研究其wiki文档,应用到自己的项目中去。
恰童鞋骚年,风华不再正茂,仍想挥斥方遒
点个在看少个bug ?
一个超轻量级工作流引擎:Workflow-Core相关推荐
- 一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core
一.关于Workflow-Core 近期工作上有一个工作流的开发需求,自己基于面向对象和职责链模式捣鼓了一套小框架,后来在github上发现一个轻量级的工作流引擎轮子:Workflow-Core,看完 ...
- .net mysql 工作流_一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core
一.关于Workflow-Core 近期工作上有一个工作流的开发需求,自己基于面向对象和职责链模式捣鼓了一套小框架,后来在github上发现一个轻量级的工作流引擎轮子:Workflow-Core,看完 ...
- python工作流引擎workflow.py_什么是工作流引擎
工作流引擎,是指workflow作为应用系统的一部分,并为之提供对各应用系统有决定作用的根据角色.分工和条件的不同决定信息传递路由.内容等级等核心解决方案. 以前一直在想如何构建一个灵活的OA工作流机 ...
- 老板要我开发一个简单的工作流引擎
点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 第1关 一天,老板找到我,说要做个简单的工作流引擎. 我查了 ...
- 今天,老板要我开发一个简单的工作流引擎
第1关 一天,老板找到我,说要做个简单的工作流引擎. 我查了一天啥是工作流,然后做出了如下版本: 按顺序添加任意个审批人组成一个链表,最后加一个结束节点 记录当前审批人,当审批完后,审批人向后移动一位 ...
- java工作流引擎,roadflow(一个强大的工作流引擎)
JAVA工作流引擎(J-RoadFlow) J-RoadFlow工作流平台是知名的.NET工作流引擎RoadFlow的JAVA移植版.该工作流平台由从事多年OA和工作流实施及开发的团队研发, 采用最简 ...
- 工作流引擎WorkFlow开源项目
1.WorkFlowEngine https://workflowengine.io/downloads/
- Workflow Core + asp.net core 5.0 实现简单审批工作流
我们知道企业业务系统到处都可以审批工作流的,但也很少有像OA系统一样复杂多级多条件的审批工作流需要设计,所以我们需要一个轻量级的容易上手的workflow框架,通过GitHub,我发现danielge ...
- 工作流(Workflow)简介
当今社会分工越来越细,在一个单位内部也越来越强调专业化,大部分工作都需要多个部门和员工合作完成.一个制度良好的单位往往对各种工作的工作流程以文件的形式固定下来,即使是管理不太正规的单位也有约定俗成的工 ...
最新文章
- BestCoder 2nd Anniversary
- Containers vs Serverless:怎么选择?
- 使用Pytorch从零搭建高精准度实时目标检测框架
- 属于程序员的等级,看看你是哪个级别?
- Python的类示例
- druid 异常 com.alibaba.druid.pool.GetConnectionTimeoutException
- js正则表达式——数字校验
- vue-cli 体验
- matlab指定的数据范围无效,c – 如何检查迭代器指定的范围是否有效?
- 海康威视球形摄像头激活,web二次开发
- 【转载】使用Winrar对压缩文件进行加密,并且给定解压密码
- 三大开源bi工具_Superset,基于web的开源BI工具,github三万star
- HTML炫酷粒子源代码
- 建行u盾弹不出来_建设银行网银盾检测不到怎么解决
- C语言分号总是报错,问什么C程序里总是提示缺少分号;,而明明有分号?
- 【学习】Congestion Control
- 计算机图形管线(实时渲染管线)
- 动物识别系统代码python_动物识别系统 代码
- Swift 5.0 (二) 可选类型 、函数
- 一个回车键黑掉一台服务器——使用Docker时不要这么懒啊喂
热门文章
- android仿ios弹框_在“提示”框中:iOS外观(在Android上运行),Google Maps作为Time Machine,下载Wii游戏保存...
- Android之Window与WindowManager
- 如何批量删除指定的GitHub Repos
- Kubernetes共享使用Ceph存储
- 计算机与操作系统基础小结
- 纯IPv6环境App适配的坑
- 设计模式--6大原则--单一职责原则
- Vim as Python IDE on windows
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(四) Logging Application Block
- 单元测试 | 如何在Mock时匹配匿名类型参数