Cadence工作流必须是确定性的,这意味着,如果使用相同的输入参数执行工作流,则预期将产生完全相同的结果。
当我以新的Cadence用户的身份学习上述要求时,我想知道当需要确定性突破性的更改时,如何长期维护工作流。
一个示例场景是,您有一个工作流连续执行Activity1和Activity2,然后您需要更改这些活动的顺序,以便工作流在Activtiy1之前执行Activity2。还有许多其他方法可以进行类似确定性的更改,我想了解如何处理这些更改。
在工作流可以长时间运行(例如几天,几周甚至几个月)的情况下,这一点尤其重要!
显然,这可能是新的Cadence开发人员提出的最常见问题之一。Cadence工作流必须是确定性算法。如果工作流算法不确定,则Cadence工作人员在尝试重播历史记录时(例如,在工作人员故障恢复期间)将面临遇到不确定性工作流程错误的风险。
有两种方法可以解决此问题:
下面是基于GetVersion()的方法的示例。假设您要在工作流程中更改以下行:
err = workflow.ExecuteActivity(ctx, foo).Get(ctx, nil)
至
err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
这是一个重大更改,因为它运行bar活动而不是foo。如果您只是进行更改而不必担心确定性,那么您的工作流将无法重播(如果需要),并且会陷入不确定性工作流错误中。正确进行此更改的正确方法是更新工作流,如下所示:
v := GetVersion(ctx, "fooChange", DefaultVersion, 1)
if v == DefaultVersion {
err = workflow.ExecuteActivity(ctx, foo).Get(ctx, nil)
} else {
err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
}
GetVersion函数接受4个参数:
当此工作流程的新实例首次到达上面的GetVersion()调用时,该函数将返回maxSupportedVersion参数,以便您可以运行最新版本的工作流程算法。同时,它还将在工作流程历史记录中记录该版本号(内部称为Marker Event),以便将来记住该版本号。稍后重播此工作流时,即使您传递了不同的maxSupportedVersion参数(例如,如果您的工作流具有更多版本),Cadence客户端也将继续返回相同的版本号。
如果在历史记录重播期间遇到GetVersion调用,并且该历史记录没有先前记录的标记事件,则该函数将返回DefaultVersion,并假设在此工作流程实例的上下文中不存在“ fooChange”。
如果您需要在工作流的同一步骤中进行更重大的更改,只需更改上面的代码,如下所示:
v := GetVersion(ctx, "fooChange", DefaultVersion, 2) // Note the new max version
if v == DefaultVersion {
err = workflow.ExecuteActivity(ctx, foo).Get(ctx, nil)
} else if v == 1 {
err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
} else { // This is the Version 2 logic
err = workflow.ExecuteActivity(ctx, baz).Get(ctx, nil)
}
如果您愿意放弃对Version 0的支持,则可以像下面这样更改上面的代码:
v := GetVersion(ctx, "fooChange", 1, 2) // DefaultVersion is no longer supported
if v == 1 {
err = workflow.ExecuteActivity(ctx, bar).Get(ctx, nil)
} else {
err = workflow.ExecuteActivity(ctx, baz).Get(ctx, nil)
}
进行此更改之后,如果您的工作流代码针对具有DefaultVersion版本的旧工作流实例运行,则Cadence客户端将引发错误并停止执行。
最终,您可能希望摆脱所有以前的版本,而仅支持最新版本。一种选择是简单地完全摆脱GetVersion调用和if语句,而只用一行代码来完成正确的事情。但是,将GetVersion()调用保留在其中实际上是一个更好的主意,这有两个原因:
考虑到上面提到的两个原因,当您应该放弃对所有旧版本的支持时,您应该像下面那样更新工作流代码:
GetVersion(ctx, "fooChange", 2, 2) // This acts like an assertion to give you a proper error
err = workflow.ExecuteActivity(ctx, baz).Get(ctx, nil)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句