正确的方式
这是你应该做的——在每次迭代中使用带有 changeId 的版本控制 API:
public class LoopWorkflowImpl implements LoopWorkflow{
private final Api api = Workflow.newActivityStub(Api.class, ...)
@override
public int start(){
int sum = 0;
for(int i=0; i<10; i++){
int version = Workflow.getVersion("useV2API"+i, Workflow.DEFAULT_VERSION, 1)
if( version == 1){
sum += api.getCountV2();
}else{
sum += api.getCount();
}
}
return sum;
}
}
A Wrong way by common 错误
许多人会这样做,它不适用于现有的工作流程
public class LoopWorkflowImpl implements LoopWorkflow{
private final Api api = Workflow.newActivityStub(Api.class, ...)
@override
public int start(){
int sum = 0;
for(int i=0; i<10; i++){
int version = Workflow.getVersion("useV2API", Workflow.DEFAULT_VERSION, 1)
if( version == 1){
sum += api.getCountV2();
}else{
sum += api.getCount();
}
}
return sum;
}
}
为什么
这是因为Workflow.getVersion() API 的一个重要合约——
来自 API 的相同 changeId 的返回值在返回后是不可变的。无论是否使用 MarkerRecord 事件将版本写入历史记录,都可以保证这一点。
所以在错误的答案中,在第一次迭代中,Workflow.getVersion() 将返回Workflow.DEFAULT_VERSION(-1),因为在回放期间没有版本标记。所以在其余的迭代中,它总是会返回Workflow.DEFAULT_VERSION。
修复的最佳方法是将迭代 Id 包含到 changeId 中。使用不同的 changeId 将允许版本控制为不同的迭代选择不同的版本。
如果您担心这会在历史记录中创建过多的版本标记事件,您可以将此解决方案与 global versioning pattern 结合使用,以便仅对旧工作流程执行此操作:
public class LoopWorkflowImpl implements LoopWorkflow{
private final Api api = Workflow.newActivityStub(Api.class, ...)
private GlovalVersionProvider globalVersionProvider = GlobalVersionProvider.get();
@override
public int start(){
if (globalVersionProvider.isAfterVersionOfUsingGlobalVersion()) {
GlobalVersionProvider.upsertGlobalVersionSearchAttribute();
}
int sum = 0;
for(int i=0; i<10; i++){
if (globalVersionProvider.isAfterVersionOfUsingV2Api()) {
sum += api.getCountV2();
}else{
int version = Workflow.getVersion("useV2API"+i, Workflow.DEFAULT_VERSION, 1)
if( version == 1){
sum += api.getCountV2();
}else{
sum += api.getCount();
}
}
}
return sum;
}
}
因此,具有迭代索引的版本控制标记仅适用于现有的旧工作流执行。