活动定义

Activity Definition 是活动的实现代码。官方建议活动应尽量具备幂等性, 并且把容易失败的外部调用封装在活动中,由 Temporal 统一重试与超时控制。

核心概念

  • Activity Definition:一段具体实现业务逻辑的函数/方法,是活动执行的「模板」。
  • Activity Type:给 Activity Definition 起的名字,用于在工作流代码中引用。
  • Activity Execution:某一次实际执行(包括重试),由 Worker 拉取任务并运行。

定义示例(Go)

ChargePaymentActivity.goGo
func ChargePaymentActivity(ctx context.Context, req ChargeRequest) (ChargeResult, error) {
    // 1) 参数校验(失败时尽早返回)
    if req.OrderID == "" {
        return ChargeResult{}, temporal.NewNonRetryableApplicationError("empty order id", "BadRequest", nil)
    }

    // 2) 调用外部系统(应支持幂等键)
    // e.g. idempotencyKey := req.OrderID + "-charge"

    // 3) 返回可序列化结果
    return ChargeResult{TransactionID: "txn-123"}, nil
}

幂等性(Idempotency)要点

Temporal 可能会因为网络抖动、Worker 崩溃等原因重试同一个 Activity。 为避免重复扣费或重复写入,活动应尽量设计为幂等。

  • 为支付、下单等写操作配置幂等键(如订单号 + 操作类型)。
  • 调用下游服务时,将幂等键传给对方(多数支付网关 / API 都支持)。
  • 宁可拆分为多个小活动,也不要在一个大活动里做「半成功」。

参数、超时与心跳

  • Activity 参数和返回值会被序列化并写入事件历史,建议保持结构简单、可序列化, 避免直接传递大对象(可改为传递 ID,再由 Activity 去加载)。
  • 至少配置 StartToClose 超时,用于控制单次执行最长时间, 长运行任务建议结合 Heartbeat 定期上报进度。
  • 可以在 Activity 上单独配置重试策略,和 Workflow 的重试策略相互独立。
设计建议
参数与返回值保持可序列化;写操作尽量幂等;外部调用优先使用业务幂等键。
粒度建议
过大活动会放大重试副作用,过细活动会增加历史事件。按“失败恢复边界”来拆分。

官方参考