如何在不破坏确定性的前提下对Uber Cadence Workflow进行更改或修复?

时间:2019-04-25 00:55:50

标签: cadence-workflow

升级正在运行的工作流程的推荐做法是什么?

如果已经使用先前的工作流程实现创建了正在运行的执行,则进行任何代码更改或更新工作流程逻辑都会导致Cadence出现“非确定性错误”,因为它无法使用更新的实现来重放现有工作流程执行的历史记录。 >

在不中断现有工作流程执行的情况下,有哪些应对升级的策略?

1 个答案:

答案 0 :(得分:0)

GetVersion用于安全地对工作流程定义执行向后不兼容的更改。在有工作流运行时,不允许更新工作流代码,因为这将破坏确定性。解决方案是既有用于重播现有工作流程的旧代码,又有第一次执行时使用的新代码。首次执行时,GetVersion返回maxSupported版本。此版本作为标记事件记录在工作流历史记录中。即使maxSupported版本已更改,也会在重播时返回记录的版本。 DefaultVersion常量包含以前未版本化的代码版本。例如,最初的工作流程具有以下代码:

err = cadence.ExecuteActivity(ctx, foo).Get(ctx, nil)

它应该更新为

err = cadence.ExecuteActivity(ctx, bar).Get(ctx, nil)

执行更新的向后兼容方式是

v :=  GetVersion(ctx, "fooChange", DefaultVersion, 1)
if v  == DefaultVersion {
    err = cadence.ExecuteActivity(ctx, foo).Get(ctx, nil)
} else {
    err = cadence.ExecuteActivity(ctx, bar).Get(ctx, nil)
}

然后必须将栏更改为baz:

v :=  GetVersion(ctx, "fooChange", DefaultVersion, 2)
if v  == DefaultVersion {
    err = cadence.ExecuteActivity(ctx, foo).Get(ctx, nil)
} else if v == 1 {
    err = cadence.ExecuteActivity(ctx, bar).Get(ctx, nil)
} else {
    err = cadence.ExecuteActivity(ctx, baz).Get(ctx, nil)
}

以后,当没有工作流运行DefaultVersion时,可以删除相应的分支:

v :=  GetVersion(ctx, "fooChange", 1, 2)
if v == 1 {
    err = cadence.ExecuteActivity(ctx, bar).Get(ctx, nil)
} else {
    err = cadence.ExecuteActivity(ctx, baz).Get(ctx, nil)
}

在引入GetVersion调用之后,目前尚不支持将其完全删除的方法。即使只剩下一个分支也要保留它:

GetVersion(ctx, "fooChange", 2, 2)
err = cadence.ExecuteActivity(ctx, baz).Get(ctx, nil)

GetVersion必须根据工作流程历史记录对版本进行验证,如果工作流程代码与此版本不兼容,则决策失败。

Java具有类似的Workflow.getVersion API。