Uber Cadence(Java):如何暂停工作流并等待外部信号事件?
Cadence工作流等待外部信号恢复执行的实现方案
问题背景与现有代码
工作流接口
public interface IMyWorkflow { @WorkflowMethod(executionStartToCloseTimeoutSeconds = 60 * 60) void begin(); @SignalMethod void continueWorkflow(); }
工作流实现类
public class MyWorkflowImpl implements IMyWorkflow { private final JmsSender sender; private static final String QUEUE = "my-queue"; public void begin() { int sum = 0; // step 1 sum++; sender.sendMessage(QUEUE, "1st call" + sum); // 暂停并等待 // step 2 sum++; sender.sendMessage(QUEUE, "2nd call" + sum); // 暂停并等待 // step 3 sum++; sender.sendMessage(QUEUE, "3rd call" + sum); // 暂停并等待 } @Override public void continueWorkflow() { // } }
首次使用Uber Cadence,卡在步骤间暂停并等待外部信号恢复执行的环节。需求是工作流在每个步骤后暂停,等待外部发送信号后继续执行后续步骤。曾尝试用Workflow.await(() -> false);实现暂停,但不知道如何恢复后续步骤。
解决方案与最佳实践
Cadence实现工作流等待外部信号的核心逻辑是:用状态标记变量配合Workflow.await(),信号方法触发时更新状态标记,让await的条件变为true,从而恢复工作流执行。
修改后的完整代码示例
public class MyWorkflowImpl implements IMyWorkflow { private final JmsSender sender; private static final String QUEUE = "my-queue"; // 用布尔变量标记各步骤的执行权限 private boolean canProceedToStep2 = false; private boolean canProceedToStep3 = false; private boolean canFinish = false; // Cadence工作流类的构造函数参数需通过依赖注入传入,保证序列化合规 public MyWorkflowImpl(JmsSender sender) { this.sender = sender; } @Override public void begin() { int sum = 0; // Step 1:执行第一个任务 sum++; sender.sendMessage(QUEUE, "1st call" + sum); // 等待外部信号,直到canProceedToStep2变为true Workflow.await(() -> canProceedToStep2); // Step 2:执行第二个任务 sum++; sender.sendMessage(QUEUE, "2nd call" + sum); // 等待外部信号触发下一步 Workflow.await(() -> canProceedToStep3); // Step 3:执行第三个任务 sum++; sender.sendMessage(QUEUE, "3rd call" + sum); // 等待结束信号(按需保留) Workflow.await(() -> canFinish); } @Override public void continueWorkflow() { // 按顺序自动推进步骤,也可接收参数指定目标步骤 if (!canProceedToStep2) { canProceedToStep2 = true; } else if (!canProceedToStep3) { canProceedToStep3 = true; } else { canFinish = true; } } }
关键要点说明
- 状态变量持久化:工作流类的成员变量会被Cadence自动持久化,即使工作流重启也能保留状态,这是实现断点续行的核心。
- Workflow.await()的正确用法:
await接收一个布尔条件lambda,当条件为true时,工作流从暂停状态恢复执行。 - 信号方法的作用:信号方法仅负责更新状态标记,不执行业务逻辑,确保工作流的可重放性。
- 序列化合规:工作流类的成员变量必须可序列化,外部服务实例需通过依赖注入传入,避免直接实例化。
进阶优化(适合多场景)
如果步骤较多或需要灵活控制,可用计数器代替多个布尔变量:
public class MyWorkflowImpl implements IMyWorkflow { private final JmsSender sender; private static final String QUEUE = "my-queue"; private int currentStep = 1; public MyWorkflowImpl(JmsSender sender) { this.sender = sender; } @Override public void begin() { int sum = 0; while (currentStep <= 3) { switch(currentStep) { case 1: sum++; sender.sendMessage(QUEUE, "1st call" + sum); break; case 2: sum++; sender.sendMessage(QUEUE, "2nd call" + sum); break; case 3: sum++; sender.sendMessage(QUEUE, "3rd call" + sum); break; } // 等待信号推进步骤 Workflow.await(() -> currentStep > 1); } } @Override public void continueWorkflow() { currentStep++; } }
这种方式更简洁,适合步骤数量不确定或需要动态调整的场景。
内容的提问来源于stack exchange,提问作者Noah
相关产品推荐
相关产品推荐

