【发布时间】:2020-11-04 07:37:46
【问题描述】:
活动任务很容易理解,因为它正在执行一项活动……但什么是决策任务?工作人员是否从头开始运行工作流(使用已完成活动的记录),直到遇到下一个需要做的“有意义”的事情,同时对下一步需要做的事情做出“决定”?
【问题讨论】:
标签: cadence-workflow temporal-workflow
活动任务很容易理解,因为它正在执行一项活动……但什么是决策任务?工作人员是否从头开始运行工作流(使用已完成活动的记录),直到遇到下一个需要做的“有意义”的事情,同时对下一步需要做的事情做出“决定”?
【问题讨论】:
标签: cadence-workflow temporal-workflow
Decision 是 workflow decision 的缩写。
决策是工作流状态机中从一种状态到另一种状态的移动。本质上,您的工作流代码定义了一个状态机。此状态机必须是 deterministic state machine 才能重播,因此工作流代码必须是确定性的。
决策任务是工作人员执行工作流代码以生成决策的任务。
假设我们有这个工作流代码:
public string sampleWorkflowMethod(...){
var result = activityStubs.activityA(...)
if(result.startsWith("x"){
Workflow.sleep(...)
}else{
result = activityStubs.activityB(...)
}
return result
}
从 Cadence SDK 的角度来看,代码是一个状态机。
假设我们有一个执行,activityA的结果是xyz,那么执行就会进入sleep分支。
在上述工作流程执行期间会发生什么:
xyz返回给Cadence服务。xyz响应成功完成工作流执行的结果。工作流决策是协调那些其他实体,如活动/ChildWorkflow/Timer/等。
Decision(workflow) 任务是与 Cadence 服务通信,告诉下一步要做什么。例如,开始/取消一些活动,或完成/失败/continueAsNew 一个工作流。
对于每个工作流执行,总是最多有一个未完成(运行/待定)的决策任务。一个已经开始但还没有完成的时候,不可能开始一个。
在编写 Cadence 工作流程时,决策任务的性质会导致一些不确定性问题。更多详情可以参考article。
在每个决策任务上,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
【讨论】:
TLDR;当接收到新的外部事件时,工作流任务负责确定接下来要执行哪些命令。
Temporal/Cadence 工作流程由外部工作人员执行。因此,了解工作流必须采取的后续步骤的唯一方法是在每次有新信息可用时询问它。将此类请求分派给工作人员的唯一方法是将工作流任务放入任务队列中。工作流工作者将其拾取,从其缓存中取出工作流,并将新事件应用到它。应用新事件后,工作流执行生成一组新命令。在工作流代码被阻止并且无法进行任何向前进展后,工作流任务将报告为已完成返回给服务。要执行的命令列表包含在完成请求中。
工作人员是否从头开始运行工作流(使用已完成活动的记录),直到遇到下一个需要做的“有意义”的事情,同时对下一步需要做的事情做出“决定”?
这取决于工作人员是否在其 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 fork 采用的术语。以下是 Cadence 概念映射到 Temporal 概念的方式:
【讨论】: