一、关于Workflow-Core

近期工作上有一个工作流的开发需求,自己基于面向对象和职责链模式捣鼓了一套小框架,后来在github上发现一个轻量级的工作流引擎轮子:Workflow-Core,看完其wiki之后决定放弃之前自己造的轮子,使用这个开源项目来改造,也就有了这一篇博文。

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

二、Workflow-Core的基本使用

2.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 builder)

{

builder

.StartWith()

.Then()

.Then();

}

}

这里定义了一个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();

host.RegisterWorkflow();

host.Start();

// Demo1:Hello World

host.StartWorkflow("HelloWorld");

Console.ReadKey();

host.Stop();

}

这里传入的是Workflow的Id,Workflow-Core会根据Id去自动匹配最新版本的对应Workflow,运行结果如下:

2.2 If语句

在工作流处理中,往往会有很多的条件判断,那么在Workflow-Core中也提供了直接的If功能,如下面这个IfStatementWorkflow所示:

public class IfStatementWorkflow : IWorkflow

{

public string Id => "if-sample";

public int Version => 1;

public void Build(IWorkflowBuilder builder)

{

builder

.StartWith()

.If(data => data.Counter < 3).Do(then => then

.StartWith()

.Input(step => step.Message, data => "Outcome is less than 3")

)

.If(data => data.Counter < 5).Do(then => then

.StartWith()

.Input(step => step.Message, data => "Outcome is less than 5")

)

.Then();

}

}

这个传递进来的MyData的定义如下:

public class MyData

{

public int Counter { get; set; }

}

当传递进来的MyData的Counter属性<3 或 <5时会有不同的分支进行逻辑的处理。

2.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自动帮你创建了很多表用于持久化工作流配置和实例。

2.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"));

2.5 Saga支持

了解分布式事务方案的童鞋应该都知道Saga,在Workflow-Core中也有支持,这是一个十分有用的功能:

(1)比如:在创建一个客户信息之后,将其推送到Salesforce和ERP,如果推送过程中发生了错误,那么就通过重试进行补偿,并且重试有时间间隔。

builder

.StartWith()

.Then()

.OnError(WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10))

.Then()

.OnError(WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10));

(2)又比如:当Task2发生异常时,Workflow-Core会帮助执行UndoTask2 和 UndoTask1 帮你回滚数据以恢复状态。

builder

.StartWith()

.Saga(saga => saga

.StartWith()

.CompensateWith()

.Then()

.CompensateWith()

.Then()

.CompensateWith()

)

.OnError(Models.WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10))

.Then();

三、在ASP.NET Core中使用Workflow-Core

3.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();

host.RegisterWorkflow();

host.RegisterWorkflow();

host.Start();

var appLifetime = app.ApplicationServices.GetService();

appLifetime.ApplicationStopping.Register(() =>

{

host.Stop();

});

return app;

}

}

这里需要注意的就是:将你要用到的所有Workflow都事先进行Register注册。

3.2 通过DI获取使用

在你想要用到的地方,无论是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> Get()

{

await _workflowService.StartWorkflow("EdcWorkflow");

return new string[] { "EdcWorkflow v1" };

}

// GET api/values/5

[HttpGet("{id}")]

public async Task 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 builder)

{

builder

.StartWith()

.Then();

}

}

public class EdcDataWorkflow : IWorkflow

{

public string Id => "EdcDataWorkflow";

public int Version => 1;

public void Build(IWorkflowBuilder builder)

{

builder

.StartWith()

.If(data => data.Id < 3).Do(then => then

.StartWith()

.Input(step => step.Message, data => "Passed Id is less than 3")

)

.If(data => data.Id < 5).Do(then => then

.StartWith()

.Input(step => step.Message, data => "Passed Id is less than 5")

)

.Then();

}

}

示例结果很简单:

(1)api/values

(2)api/values/1

四、小结

Workflow-Core是一个适合.NET Core的优秀的轻量级工作流引擎,对于小型工作流和责任链类型的需求开发很适合,可以节约大量时间避免重复造轮子,将时间主要花在业务逻辑上面。当然,这里演示的示例只是众多功能特性中的一小部分,我只是选取了我用到的部分而已,大家有兴趣的话可以去GitHub上先给个star再仔细研究其wiki文档,应用到自己的项目中去。

.net mysql 工作流_一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core相关推荐

  1. 一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core

    一.关于Workflow-Core 近期工作上有一个工作流的开发需求,自己基于面向对象和职责链模式捣鼓了一套小框架,后来在github上发现一个轻量级的工作流引擎轮子:Workflow-Core,看完 ...

  2. 一个超轻量级工作流引擎:Workflow-Core

    近期工作上有一个工作流的开发需求,自己基于面向对象和职责链模式捣鼓了一套小框架,后来在github上发现一个轻量级的工作流引擎轮子:Workflow-Core,看完其wiki之后决定放弃之前自己造的轮 ...

  3. excel转mysql 工具_一个简单的批量excel转mysql工具

    背景:工作中,经常发现需要将excel中的表数据导入到mysql中,实际操作一般都是用navcat,但是使用中也发现navcat只支持单个表导入,对xlsx格式支持不友好.于是写了这么一个导表工具.在 ...

  4. php简单的mysql类_一个简单的php mysql操作类

    本文分享一个简单的php.mysql操作类,很简单,主要是数据的连接.查询等.有需要的朋友参考下吧. 分享一段php.mysql操作类的代码,供初学的朋友参考. 一个简单的类使用php和mysql数据 ...

  5. 腾讯云mysql架构_一个数据库存储架构的独白

    本文由云+社区发表 本文作者:许中清,腾讯云自研数据库CynosDB的分布式存储CynosStore负责人.从事数据库内核开发.数据库产品架构和规划.曾就职于华为,2015年加入腾讯,参与过TBase ...

  6. 怎么抽象mysql数据库_一个用于mysql的数据库抽象层函数库

    一个用于mysql的数据库抽象层函数库 更新时间:2006年10月09日 00:00:00   作者: // // SourceForge: Breaking Down the Barriers to ...

  7. mysql 围栏_一个电子围栏需求的脚本记录

    需求:系统对接了厂家的GPS数据,基于这些GPS数据,过滤出指定区域的数据 从网上找到了一个电子围栏的python脚本,现在需要的是循环取数据判断是否在指定区域,在指定区域就把这部分数据拿出来放到另外 ...

  8. 一个机器能装两个mysql吗_一个机器安装多个mysql

    /home/setup/mysql-5.0.96 grep config config.status :查看mysq的编译参数 './configure'  '–prefix=/usr/local/m ...

  9. mysql浏览器_一个简单的MySQL数据浏览器

    一个简单的MySQL数据浏览器 更新时间:2006年10月09日 00:00:00   作者: 这个程序可以用来浏览MySQL中的数据,您可以稍做修改就可以做出很不错的MySQL浏览器. */ /* ...

最新文章

  1. 循环神经网络(recurrent neural network)(RNN)
  2. Android listview viewholder
  3. redis的学习资源
  4. 关于Zend framework 里一段代码的疑问
  5. windows系统启用2个以上的mysql服务
  6. mysql+5.6+左连接_第5章 索引与算法
  7. AIX LV删除后,ORACLE数据库文件全部恢复成功
  8. Chrome浏览器showModalDialog兼容性及解决方案
  9. python 执行shell 事务_python中执行shell的两种方法总结
  10. mysql模式匹配详解_老生常谈MYSQL模式匹配 REGEXP和like的用法
  11. Java自学要多久?
  12. 擦黑板特效表白H5源码+非常浪漫/附BGM
  13. Goole 和 Bing 和 Baidu 搜索语法
  14. 集合易支付源码完美版
  15. iOS永久不掉签名工具,TrollStore超详使用教程
  16. ssh和telnet客户软件ZOC如何设置UTF-8
  17. w7计算机防火墙无法更改,Win7提示Windows防火墙无法更改某些设置怎么办?
  18. RuPengWang项目
  19. radan7中文使用手册
  20. 这届网友实在是太有才了!用python爬取15万条《我是余欢水》弹幕

热门文章

  1. SQLite学习总结(2)——使用Java操作SQLite
  2. Java基础学习总结(78)——Java main方法深入研究学习
  3. linux下进程调度算法实验,Linux下进程调度算法的模拟实现.doc
  4. canvas画条形图 微信小程序_小程序-引入 echart 图表画圆饼图
  5. mysql age字段类型_mysql 列类型
  6. c java交互_C和Java程序之间的交互/通信
  7. 匿名对象方案与实体对象方案对比
  8. spring cloud 资源
  9. 加载gif图片的方法:(需要SDWebImage方法)
  10. Unity 全面理解加载和内存管理