从工作流代码中的 defer() 调用工作流 activity 是否安全?

Is it safe to invoke a workflow activity from defer() within the workflow code?

func MyWorkflow(ctx Context) (retErr error) { 
  log := workflow.GetLogger()
  log.Info("starting my workflow")
  defer func() {
    if retErr != nil {
      DoActivityCleanupError(ctx, ..)
    } else {
      DoActivityCleanupNoError(ctx, ...)
    }
  }
  err := DoActivityA(ctx, ...)
  if err != nil {
    return err
  }
  ...
  err := DoActivityB(ctx, ...)
  if err != nil {
    return err
  }
}
  

基本上,我们希望在工作流退出时执行所有活动,ActivityCleanupNoError 和 ActivityCleanupError(特别是在我们不想在所有错误中重复调用 ActivityCleanupError 的错误情况下 returns。

这适用于分布式决策吗?例如,如果工作流决策的所有权从一个工作人员转移到另一个工作人员,是否会触发原工作人员的延迟?

奖励问题:记录器是否只对每个工作流程强制记录一次 运行?即使决定从一名工人转移到另一名工人?您是否希望看到日志行出现在两个工作人员的日志中?还是幕后有魔法来防止这种情况发生?

是的。

但是要理解为什么它是安全的是相当复杂的。这是得出结论的方法:

  1. 在非粘性模式(没有粘性缓存)下,Cadence SDK 将始终执行工作流代码来做出(收集)工作流决策,并释放所有 goroutines/stack。释放它们时,将执行延迟,这意味着清理 activity 代码路径将 运行 -- HOWEVER,这些决定将被忽略。因此不会影响实际的正确性。

  2. 在sticky模式下,如果workflow没有关闭,Cadence SDK会在某处阻塞;如果工作流实际上正在关闭,那么将执行延迟并收集决策。

  3. 当sticky cache(goroutines/stack)被逐出时,会发生的事情和1完全一样,所以也是安全的。

Does the logger enforce logging only once per workflow run? Even if decisions are moved from one worker to another? Do you expect to see the log line appear in both worker's log? or is there magic behind the scene to prevent this from happening?

每条日志行只会出现在实际执行代码作为决策的工作人员中——换句话说,在非重放模式下。这是唯一的魔法:)