You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 14:35:12