活动定义
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 的重试策略相互独立。
设计建议
参数与返回值保持可序列化;写操作尽量幂等;外部调用优先使用业务幂等键。
粒度建议
过大活动会放大重试副作用,过细活动会增加历史事件。按“失败恢复边界”来拆分。