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

Uber Cadence工作流异常:270小时计时器与UNHANDLED_DECISION错误求助

Uber Cadence 新手问题解答

一、计时器来源与UNHANDLED_DECISION错误解析

计时器来源排查

你遇到的270小时超长计时器,基本是代码中Workflow.sleep生成的,重点排查两段代码的配置或逻辑:

  • 第一段代码中,若LocalDateTime.now()未指定时区,与myWorkflow.getStartDateTime()的UTC时区不匹配,可能计算出异常时长;
  • 第二段代码中,若props里的waitPeriod数值配置错误(比如误填270)、或waitPeriodType单位选错(比如把分钟设为小时),会直接生成对应时长的计时器。

UNHANDLED_DECISION错误原因

这个错误本质是工作流非确定性导致的,Cadence要求工作流代码必须保证重放时的行为一致,常见触发场景:

  • 工作流代码修改后,旧工作流重放时,新代码的决策逻辑与历史记录不匹配;
  • 代码中使用了非确定性API(比如未指定时区的LocalDateTime.now()),重放时该值变化,导致Timer事件无法匹配对应生成逻辑,触发堆栈中的NonDeterminisicWorkflowError。

二、批量终止工作流的方法

1. Cadence Web UI操作

进入对应Domain的工作流列表页面,通过筛选条件(工作流类型、运行状态等)定位目标工作流,勾选后执行批量终止操作。若工作流数量过大,UI可能存在性能瓶颈,建议用CLI。

2. Cadence CLI批量处理

使用cadence workflow terminate命令结合查询条件批量终止,示例:

# 终止指定Domain下、指定类型的所有运行中工作流
cadence workflow terminate --domain your-domain --query "WorkflowType='YourWorkflowType' AND ExecutionStatus='RUNNING'" --reason "修复非确定性错误"

可通过Cadence查询语法设置更精准的筛选条件(如按启动时间范围过滤)。

三、代码正确性分析与修正

第一段代码(等待到未来启动时间)

原代码存在两个核心问题:

  • LocalDateTime.now()未指定时区,与UTC时区的startDateTime计算时差时会出错;
  • 直接使用系统时间API违反工作流确定性要求,重放时会导致行为不一致。

修正后的代码:

// 工作流中必须用Workflow.currentTimeMillis()获取时间,保证重放一致性
Instant now = Instant.ofEpochMilli(Workflow.currentTimeMillis());
Instant startInstant = myWorkflow.getStartDateTime().atZone(CampaignConstants.ZONE_ID_UTC).toInstant();

if (now.isBefore(startInstant)) {
    Duration waitDuration = Duration.between(now, startInstant);
    Workflow.sleep(waitDuration);
}

第二段代码(按指定时长等待)

原代码缺乏参数校验,易因非法配置生成超长计时器,且无异常处理逻辑。

修正后的代码:

try {
    String waitPeriodStr = (String) props.get("waitPeriod");
    String waitPeriodTypeStr = (String) props.get("waitPeriodType");
    
    if (waitPeriodStr == null || waitPeriodTypeStr == null) {
        throw new IllegalArgumentException("waitPeriod或waitPeriodType参数缺失");
    }
    
    Integer waitPeriod = Integer.parseInt(waitPeriodStr);
    ChronoUnit chronoUnit = ChronoUnit.valueOf(waitPeriodTypeStr.toUpperCase());
    
    // 校验时长合理性,避免生成超长计时器(可根据业务调整限制值)
    Duration waitDuration = Duration.of(waitPeriod, chronoUnit);
    if (waitDuration.toHours() > 24) {
        throw new IllegalArgumentException("等待时长超过最大限制(24小时)");
    }
    
    Workflow.sleep(waitDuration);
} catch (NumberFormatException | IllegalArgumentException e) {
    Workflow.getLogger(getClass()).error("等待参数配置无效", e);
    throw new RuntimeException("等待参数错误", e);
}

内容的提问来源于stack exchange,提问作者siva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 22:00:36