事件
工作流还可以设定等待外部事件
//设定工作流
public class EventSampleWorkflow : IWorkflow<MyDataClass>
{
public void Build(IWorkflowBuilder<MyDataClass> builder)
{
builder
.StartWith(context => ExecutionResult.Next())
.WaitFor("MyEvent", data => "0")//等待MyEvent的事件发生,且key为0
.Output(data => data.Value, step => step.EventData)
.Then<CustomMessage>()
.Input(step => step.Message, data => "The data from the event is " + data.Value);
}
}
...
//外部定义的事件
//事件数据的key为0时,value为hello
host.PublishEvent("MyEvent", "0", "hello");
生效日期
还可以在等待事件时设定指定生效日期。以便于响应过去已经发生的事件,或者仅仅响应生效日期之后发生的事件。
案例
- dataclass
public class MyDataClass
{
public string Value1 { get; set; }
}
- step
public class CustomMessage : StepBody
{
public string Message { get; set; }
public override ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine(Message);
return ExecutionResult.Next();
}
}
- workflow
public class EventSampleWorkflow : IWorkflow<MyDataClass>
{
public string Id => "EventSampleWorkflow";
public int Version => 1;
public void Build(IWorkflowBuilder<MyDataClass> builder)
{
builder
.StartWith(context => ExecutionResult.Next())
.WaitFor("MyEvent", (data, context) => context.Workflow.Id)
.Output(data => data.Value1, step => step.EventData)
.Then<CustomMessage>()
.Input(step => step.Message, data => "The data from the event is " + data.Value1)
.Then(context => Console.WriteLine("workflow complete"));
}
}
- program
IServiceCollection services = new ServiceCollection();
services.AddLogging();
services.AddWorkflow();
var serviceProvider = services.BuildServiceProvider();
var host = serviceProvider.GetService<IWorkflowHost>();
host.RegisterWorkflow<EventSampleWorkflow, MyDataClass>();
host.Start();
var initialData = new MyDataClass();
var workflowId = host.StartWorkflow("EventSampleWorkflow", 1, initialData).Result;
Console.WriteLine("Enter value to publish");
string value = Console.ReadLine();
host.PublishEvent("MyEvent", workflowId, value);
Console.ReadLine();
host.Stop();
活动
活动是外部的一个运行程序,该程序可以被工作流等待。
//该工作流将等待activity-1执行,然后再继续执行。
//同时,工作流还将data.Value1的值传递给activity-1活动,并且获取activity-1的运算结果复制给data.value2
public class ActivityWorkflow : IWorkflow<MyData>
{
public void Build(IWorkflowBuilder<MyData> builder)
{
builder
.StartWith<HelloWorld>()
.Activity("activity-1", (data) => data.Value1)
.Output(data => data.Value2, step => step.Result)
.Then<PrintMessage>()
.Input(step => step.Message, data => data.Value2);
}
}
...
//获取活动和工作流正在等待的数据 参数:活动、工作流id、过期时间
var activity = host.GetPendingActivity("activity-1", "worker1", TimeSpan.FromMinutes(1)).Result;
if (activity != null)
{
Console.WriteLine(activity.Parameters);
host.SubmitActivitySuccess(activity.Token, "Some response data");
}
案例
- dataclass
class MyData
{
public string Request { get; set; }
public string ApprovedBy { get; set; }
}
- steps
public class HelloWorld : StepBody
{
public override ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine("Hello world");
return ExecutionResult.Next();
}
}
public class GoodbyeWorld : StepBody
{
public override ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine("Goodbye world");
return ExecutionResult.Next();
}
}
public class CustomMessage : StepBody
{
public string Message { get; set; }
public override ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine(Message);
return ExecutionResult.Next();
}
}
- workflow
class ActivityWorkflow : IWorkflow<MyData>
{
public string Id => "activity-sample";
public int Version => 1;
public void Build(IWorkflowBuilder<MyData> builder)
{
builder
.StartWith<HelloWorld>()
.Activity("get-approval", (data) => data.Request)
.Output(data => data.ApprovedBy, step => step.Result)
.Then<CustomMessage>()
.Input(step => step.Message, data => "Approved by " + data.ApprovedBy)
.Then<GoodbyeWorld>();
}
}
- program
IServiceCollection services = new ServiceCollection();
services.AddLogging(cfg =>
{
cfg.AddConsole();
cfg.AddDebug();
});
services.AddWorkflow();
var serviceProvider = services.BuildServiceProvider();
var host = serviceProvider.GetService<IWorkflowHost>();
host.RegisterWorkflow<ActivityWorkflow, MyData>();
host.Start();
Console.WriteLine("Starting workflow...");
var workflowId = host.StartWorkflow("activity-sample", new MyData { Request = "Spend $1,000,000" }).Result;
var approval = host.GetPendingActivity("get-approval", workflowId, TimeSpan.FromMinutes(1)).Result;
if (approval != null)
{
Console.WriteLine("Approval required for " + approval.Parameters);
host.SubmitActivitySuccess(approval.Token, "John Smith");
}
Console.ReadLine();
host.Stop();
错误处理
每个步骤都可以配置自己的错误处理流程,可以稍后重试,暂停工作流或者终止工作流
public void Build(IWorkflowBuilder<object> builder)
{
builder
.StartWith<HelloWorld>()
.OnError(WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10))
.Then<GoodbyeWorld>();
}
WorkflowHost服务可以定于全局的错误处理,可以用于全局级别拦截工作流的异常
host.OnStepError +=处理异常事件