升级正在运行的工作流的推荐做法是什么?
如果已经使用以前的工作流实现创建了正在运行的执行,则进行任何代码更改或更新工作流逻辑会导致 Cadence 出现“非确定性错误”,因为它无法使用更新的实现重放现有工作流执行的历史记录。
有哪些策略可以在不破坏现有工作流程执行的情况下处理升级?
升级正在运行的工作流的推荐做法是什么?
如果已经使用以前的工作流实现创建了正在运行的执行,则进行任何代码更改或更新工作流逻辑会导致 Cadence 出现“非确定性错误”,因为它无法使用更新的实现重放现有工作流执行的历史记录。
有哪些策略可以在不破坏现有工作流程执行的情况下处理升级?
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。