1

活动任务很容易理解,因为它正在执行一项活动……但什么是决策任务?工作人员是否从一开始就贯穿整个工作流程(使用已完成活动的记录),直到它遇到下一个需要做的“有意义”的事情,同时对下一步需要做的事情做出“决定”?

4

2 回答 2

9

TL;博士

决策是工作流决策的缩写。

决策是工作流状态机中从一种状态到另一种状态的移动。本质上,您的工作流代码定义了一个状态机。此状态机必须是用于重放的确定性状态机,因此工作流代码必须是确定性的。

决策任务是工作人员执行工作流代码以生成决策的任务。

例子

假设我们有这个工作流代码:

public string sampleWorkflowMethod(...){
  var result = activityStubs.activityA(...)
  if(result.startsWith("x"){
     Workflow.sleep(...)
  }else{
     result = activityStubs.activityB(...)
  }
  
  return result
}

从 Cadence SDK 的角度来看,代码是一个状态机。

假设我们有一个执行,activityA 的结果是xyz,那么执行将进入 sleep 分支。

那么工作流执行流程就是这个图。 在此处输入图像描述

  • 工作流代码定义状态机,它是静态的。
  • 工作流执行将根据输入/结果/和代码逻辑决定如何在运行时从一种状态移动到另一种状态
  • 决策是 Cadence 内部的抽象。在工作流执行期间,当它从一种状态变为另一种状态时,决策就是该移动的结果。
  • 抽象基本上是定义当执行从一种状态转移到另一种状态时需要做什么——调度活动、计时器或 childWF 等。
  • 决策需要是确定性的——使用相同的输入/结果,工作流代码应该做出相同的决策——调度活动 A 或 B 必须相同。

示例中的时间轴

在上述工作流程执行期间会发生什么

  1. Cadence 服务安排第一个决策任务,分派给工作流工作者。
  2. Worker执行第一个决策任务,将调度activityA的决策结果返回给Cadence服务。然后工作流在那里等待。
  3. 作为调度activityA的结果,由Cadence服务生成一个activity任务,并将该任务分派给一个activity worker
  4. 活动工作者执行活动并将结果返回xyz给 Cadence 服务。
  5. 作为接收到活动结果的结果,Cadence 服务安排第二个决策任务,并分派给工作流工作者。
  6. 工作流工作者执行第二个决策任务,并将调度定时器的决策结果响应给Cadence服务。
  7. 在收到决策任务响应后,Cadence 服务会安排一个计时器
  8. 当计时器触发时,Cadence 服务会安排第三个决策任务并再次分派给工作流工作者
  9. 工作流工作者执行第三个决策任务,并以结果响应成功完成工作流执行的结果xyz

关于决定的更多事实

  • 工作流决策是协调那些其他实体,如活动/子工作流/计时器/等。

  • 决策(工作流)任务是与 Cadence 服务通信,告诉下一步要做什么。例如,开始/取消一些活动,或完成/失败/continueAsNew 一个工作流。

  • 对于每个工作流执行,总是最多有一个未完成的(正在运行/待处理的)决策任务。不可能开始一个,而另一个已经开始但尚未完成。

  • 在编写 Cadence 工作流程时,决策任务的性质会导致一些不确定性问题。更多细节可以参考文章

  • 在每个决策任务上,Cadence Client SDK 可以从头开始“重播”代码,例如,执行 activityA。但是,这种重放模式不会再次产生调度activityA的决定。因为客户端知道activityA 已经安排好了。

  • 但是,工作人员不必从一开始就运行代码。Cadence SDK 足够智能,可以将状态保存在内存中,稍后唤醒以继续之前的状态。这被称为“工作流粘性缓存”,因为工作流在工作主机上具有一段时间的粘性。

示例的历史事件:

1. WorkflowStarted
2. DecisionTaskScheduled
3. DecisionTaskStarted
4. DecisionTaskCompleted
5. ActivityTaskScheduled <this schedules activityA>
6. ActivityTaskStarted
7. ActivityTaskCompleted <this records the results of activityA>
8. DecisionTaskScheduled
9. DecisionTaskStarted
10. DecisionTaskCompleted
11. TimerStarted         < this schedules the timer>
12. TimerFired
13. DecisionTaskScheduled
14. DecisionTaskStarted
15. DecisionTaskCompleted
16. WorkflowCompleted
于 2020-09-19T02:29:32.773 回答
7

TLDR;当接收到新的外部事件时,工作流任务负责确定要执行的下一个命令。

时间/节奏工作流程由外部工作人员执行。因此,了解工作流必须采取哪些后续步骤的唯一方法是在每次有新信息可用时询问它。将此类请求分派给工作人员的唯一方法是将工作流任务放入任务队列中。工作流工作者将其拾取,将工作流从其缓存中取出,并将新事件应用到它。应用新事件后,工作流执行生成一组新命令。在工作流代码被阻止并且无法进行任何前进后,工作流任务将报告为已完成返回给服务。要执行的命令列表包含在完成请求中。

工作人员是否从头开始运行工作流(使用已完成活动的记录),直到遇到下一个需要做的“有意义”的事情,同时对下一步需要做的事情做出“决定”?

这取决于工作人员是否在其 LRU 缓存中具有工作流对象。如果工作流在缓存中,则不需要恢复,工作流任务中只包含新事件。如果对象没有被缓存,那么整个事件历史都会被发送,并且工作人员必须从一开始就执行工作流代码以将其恢复到当前状态。重放过去事件时产生的所有命令都是先前产生的命令的副本,并且被忽略。

以上意味着在工作流的生命周期中必须执行多个工作流任务。例如,对于按顺序调用两个活动的工作流:

a();
b();

将为每个状态转换执行任务:

-> workflow task at the beginning: command is ScheduleActivity "a"
    a();
-> workflow task when "a" completes: command is ScheduleActivity "b"
    b();
-> workflow task when "b" completes: command is CompleteWorkflowExecution

在答案中,我使用了 Cadence 的temporal.io分支采用的术语。以下是节奏概念映射到时间概念的方式:

  • 决策任务 -> 工作流任务
  • 决策 -> 命令,但在某些情况下它也可能意味着工作流任务
  • 任务列表 -> 任务队列
于 2020-07-15T15:16:28.263 回答