【发布时间】:2019-09-14 08:41:29
【问题描述】:
升级正在运行的工作流的推荐做法是什么?
如果已经使用以前的工作流实现创建了正在运行的执行,那么进行任何代码更改或更新工作流逻辑都会导致 Cadence 出现“非确定性错误”,因为它无法使用更新的实现重放现有工作流执行的历史记录。
在不破坏现有工作流程执行的情况下,有哪些策略可以处理升级?
【问题讨论】:
标签: cadence-workflow
升级正在运行的工作流的推荐做法是什么?
如果已经使用以前的工作流实现创建了正在运行的执行,那么进行任何代码更改或更新工作流逻辑都会导致 Cadence 出现“非确定性错误”,因为它无法使用更新的实现重放现有工作流执行的历史记录。
在不破坏现有工作流程执行的情况下,有哪些策略可以处理升级?
【问题讨论】:
标签: cadence-workflow
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)
}
那么bar必须改成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。
【讨论】: