Activity execution - Rust SDK
Start an Activity Execution
Calls to spawn Activity Executions are written within a Workflow Definition. The call to spawn an Activity Execution generates the ScheduleActivityTask Command. This results in a set of three Activity Task related Events in your Workflow Execution Event History: ActivityTaskScheduled, ActivityTaskStarted, and ActivityTaskClosed.
A single instance of the Activity implementation may be used across multiple concurrent Activity invocations. Activity implementation code should be idempotent.
Values passed to Activities as input parameters or returned as results are recorded in the Workflow Execution history. This history is replayed to Workflow Workers during recovery. Large payloads can negatively impact Workflow performance.
Be mindful of the size of data passed to and from Activities. Otherwise, there are no strict limitations on Activity implementations.
To spawn an Activity Execution, use the Workflow context’s Activity execution APIs within your Workflow code.
In Rust, Activities are typically executed using ctx.start_activity(...), which returns a Future that can be awaited.
#[workflow_methods]
impl GreetingWorkflow {
#[run]
pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> {
let name = ctx.state(|s| s.name.clone());
// Execute an activity
let greeting = ctx.start_activity(
MyActivities::greet,
name,
ActivityOptions {
start_to_close_timeout: Some(Duration::from_secs(10)),
..Default::default()
}
).await?;
println!("{}", greeting);
Ok(greeting)
}
}
Set the required Activity Timeouts
Activity Execution semantics rely on several timeout parameters. You need to set at least one of these:
These are configured as part of the Activity options when scheduling the Activity. Available timeouts include:
start_to_close_timeoutschedule_to_close_timeoutschedule_to_start_timeout
#[workflow_methods]
impl GreetingWorkflow {
#[run]
pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> {
let name = ctx.state(|s| s.name.clone());
// Execute an activity
let greeting = ctx.start_activity(
MyActivities::greet,
name,
ActivityOptions {
// Required timeout
start_to_close_timeout: Some(Duration::from_secs(10)),
// Optional timeouts:
// schedule_to_start_timeout: Some(Duration::from_secs(5)),
// schedule_to_close_timeout: Some(Duration::from_secs(10)),
..Default::default()
}
).await?;
println!("{}", greeting);
Ok(greeting)
}
}
Get the results of an Activity Execution
Spawning an Activity Execution generates a ScheduleActivityTask Command and returns a Future to the Workflow.
Workflows can either:
awaitthe result immediately (blocking progress), or- store the
Futureand await it later to allow concurrent execution.
In Rust, calling .await on the Activity invocation returns the result. If you need more control (e.g., parallel execution), you can create multiple Activity futures and await them selectively.
You must provide either schedule_to_close_timeout or start_to_close_timeout.
#[workflow_methods]
impl GreetingWorkflow {
#[run]
pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> {
let name = ctx.state(|s| s.name.clone());
// Execute an activity
let greeting = ctx.start_activity(
MyActivities::greet,
name,
ActivityOptions {
start_to_close_timeout: Some(Duration::from_secs(10)),
..Default::default()
}
).await?;
println!("{}", greeting);
Ok(greeting)
}
}
For concurrent execution:
#[run]
pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> {
let name = ctx.state(|s| s.name.clone());
// Execute an activity
let greeting = ctx.start_activity(
MyActivities::greet,
name,
ActivityOptions {
schedule_to_close_timeout: Some(Duration::from_secs(10)),
..Default::default()
}
);
let language = ctx.start_activity(
MyActivities::call_greeting_service,
ActivityLanguages::English,
ActivityOptions {
start_to_close_timeout: Some(Duration::from_secs(10)),
..Default::default()
}
);
// Run in parallel
let (greeting_res, language_res) = tokio::join!(greeting, language);
}
Use direct .await in most cases. More advanced patterns, like parallel execution or cancellation, can be built using Rust’s async primitives.