new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Temporal · Develop · all subjects

workflows/basics

456 notes in this subject, read out of this brain and free to use. This is page 6 of 8.

Get current workflow details in Ruby

Within a workflow definition in the Ruby SDK, you can retrieve the current workflow details using Temporalio::Workflow.current_details. This returns the current details that have been set for the workflow.

Set current workflow details in Ruby

Within a workflow definition in the Ruby SDK, you can update the current workflow details at any point during execution using Temporalio::Workflow.current_details = 'string'. Unlike static details set at workflow start, current workflow details can be updated throughout the life of the workflow. The format supports standard Markdown excluding images, HTML, and scripts, and can span multiple lines.

Example: Execute workflow synchronously with static summary and details in Ruby

require 'temporalio/client' client = Temporalio::Client.connect('localhost:7233') # Execute workflow synchronously result = client.execute_workflow( 'YourWorkflow', 'workflow input', id: 'your-workflow-id', task_queue: 'your-task-queue', static_summary: 'Order processing for customer #12345', static_details: 'Processing premium order with expedited shipping' )

Example: Start workflow with static summary and details in Ruby

require 'temporalio/client' # Create client client = Temporalio::Client.connect('localhost:7233') # Start a workflow with static summary and details handle = client.start_workflow( 'YourWorkflow', 'workflow input', id: 'your-workflow-id', task_queue: 'your-task-queue', static_summary: 'Order processing for customer #12345', static_details: 'Processing premium order with expedited shipping' )

Execute a Workflow in Ruby

Use client.execute_workflow(WorkflowClass, arguments, id: workflow_id, task_queue: task_queue_name) to execute a workflow synchronously. Example: result = client.execute_workflow(SayHelloWorkflow, 'Temporal', id: 'my-workflow-id', task_queue: 'my-task-queue')

Define a simple Workflow in Ruby

Create a Workflow by extending Temporalio::Workflow::Definition and implementing an execute method. Call activities using Temporalio::Workflow.execute_activity(ActivityClass, arguments, options). Example: require 'temporalio/workflow'; class SayHelloWorkflow < Temporalio::Workflow::Definition; def execute(name); Temporalio::Workflow.execute_activity(SayHelloActivity, name, schedule_to_close_timeout: 300); end; end

Event History limit is 51,200 Events or 50 MB

A Workflow Execution's Event History is limited to 51,200 Events or 50 MB. The system will warn after 10,240 Events or 10 MB to alert developers that they should consider using Continue-As-New.

Continue-As-New example in Ruby

raise Temporalio::Workflow::ContinueAsNewError.new('my-new-arg')

Raise ContinueAsNewError to perform Continue-As-New in Ruby

To Continue-As-New in Ruby, raise a Temporalio::Workflow::ContinueAsNewError from inside your Workflow with the appropriate arguments. This will stop the Workflow immediately and Continue-As-New.

Dynamic Workflow invocation at runtime

A Dynamic Workflow in Temporal is a Workflow that is invoked dynamically at runtime if no other Workflow with the same name is registered. A Workflow can be made dynamic by invoking the workflow_dynamic class method at the top of the definition. Only one Dynamic Workflow can be present on a Worker. The Dynamic Workflow must be registered with the Worker before it can be invoked.

Dynamic Workflow example in Ruby

This Ruby example shows a Dynamic Workflow that uses workflow_dynamic and workflow_raw_args class methods. The execute method receives raw_args as a splatted array, validates that a single argument is provided, converts the raw payload using Temporalio::Workflow.payload_converter.from_payload(), and then executes an activity with the converted argument: ```ruby class MyDynamicWorkflow < Temporalio::Workflow::Definition # Make this the dynamic workflow and accept raw args workflow_dynamic workflow_raw_args def execute(*raw_args) # Require a single arg for our workflow raise Temporalio::Error::ApplicationError, 'One arg expected' unless raw_args.size == 1 # Use payload converter to convert it name = Temporalio::Workflow.payload_converter.from_payload(raw_args.first.payload) Temporalio::Workflow.execute_activity( MyActivity, { greeting: 'Hello', name: }, start_to_close_timeout: 100 ) end end ```

workflow_dynamic and workflow_raw_args usage

Dynamic Workflows are often used in conjunction with workflow_raw_args, which does not convert arguments but instead passes them through as a splatted array of Temporalio::Converters::RawValue instances. This allows the Dynamic Workflow to handle raw arguments and convert them manually using the payload converter.

Ruby SDK Workflows documentation structure

The Ruby SDK Workflows documentation covers the following topics: Workflow basics, Child Workflows, Continue-As-New, Cancellation, Timeouts, Message passing, Schedules, Timers, Futures, Dynamic Workflow, and Versioning.

Workflow.wait_condition for awaiting results

The Ruby SDK provides Workflow.wait_condition as an alternative method for awaiting a result in workflows.

Temporalio::Workflow::Future for concurrent activity execution

Temporalio::Workflow::Future is a Temporal-safe wrapper around Fiber.schedule used for running multiple activities concurrently in a workflow. Futures are never used implicitly but work with all workflow code and constructs. Create a future by instantiating Temporalio::Workflow::Future with a block containing the activity execution.

Run multiple activities concurrently with futures

To run 3 activities concurrently and wait for them all to complete: Create three Temporalio::Workflow::Future objects, each wrapping a call to Temporalio::Workflow.execute_activity(). Call Temporalio::Workflow::Future.all_of(fut1, fut2, fut3).wait to block until all futures complete. Access results via the result property on each future.

Wait for first of multiple activities or timeout using any_of

To wait on whichever completes first among multiple activities or a timer: Create futures for each activity using Temporalio::Workflow::Future.new with execute_activity in the block. Create another future wrapping Temporalio::Workflow.sleep() for the timeout. Call Temporalio::Workflow::Future.any_of(sleep_fut, *act_futs).wait to return when any future completes. Check if a specific future (like sleep_fut) completed first using the done? method to determine which completed.

Temporalio::Workflow::Future.result property

Access the result of a completed Temporalio::Workflow::Future using the result property.

Temporalio::Workflow::Future.done? method

The done? method on a Temporalio::Workflow::Future returns true if the future has completed.

Temporalio::Workflow::Future.any_of method

The any_of class method takes multiple futures as arguments and returns a combined future that completes when any one of the input futures completes.

Use start_delay to schedule workflow at a future point

Use the start_delay parameter on either the start_workflow or execute_workflow methods in the Client to schedule a Workflow Execution at a specific one-time future point rather than on a recurring schedule. Example: handle = my_client.start_workflow(MyWorkflow, 'some-input', id: 'my-workflow-id', task_queue: 'my-task-queue', start_delay: 3 * 60 * 60).

Pause a scheduled workflow in Ruby

To pause a scheduled workflow in Ruby, use the pause method on the Schedule Handle. When you pause a Schedule, all future Workflow Runs associated with the Schedule are temporarily stopped. You can pass a note parameter to provide a reason for pausing. Example: handle = my_client.schedule_handle('my-schedule-id'); handle.pause(note: 'Pausing the schedule for now').

Trigger a scheduled workflow in Ruby

To trigger a scheduled workflow in Ruby, use the trigger method on the Schedule Handle. This triggers an immediate action with the given Schedule, subject to the Schedule's Overlap Policy. Example: handle = my_client.schedule_handle('my-schedule-id'); handle.trigger.

Update a scheduled workflow in Ruby

To update a scheduled workflow in Ruby, use the update method on the Schedule Handle. This method accepts a block that receives an update input object and must return an update with a new schedule to update, or nil to not update. Example: handle = my_client.schedule_handle('my-schedule-id'); handle.update do |input| Temporalio::Client::Schedule::Update.new(schedule: input.description.schedule.with(action: Temporalio::Client::Schedule::Action::StartWorkflow.new(MyNewWorkflow, 'some-new-input', id: 'my-workflow-id', task_queue: 'my-task-queue'))) end.

Create a scheduled workflow in Ruby

To create a scheduled workflow in Ruby, use the create_schedule method on the Client. Pass the Schedule ID and a Schedule object with an action set to StartWorkflow and a spec with intervals. Example: handle = my_client.create_schedule('my_schedule_id', Temporalio::Client::Schedule.new(action: Temporalio::Client::Schedule::Action::StartWorkflow.new(MyWorkflow, 'some-input', id: 'my-workflow-id', task_queue: 'my-task-queue'), spec: Temporalio::Client::Schedule::Spec.new(intervals: [Temporalio::Client::Schedule::Spec::Interval.new(every: 5 * 24 * 60 * 60.0)]))).

Schedule auto-deletion behavior

Once a Schedule has completed creating all its Workflow Executions, the Temporal Service automatically deletes it since it won't fire again. The Temporal Service does not guarantee when this removal will happen.

Backfill a scheduled workflow in Ruby

To backfill a scheduled workflow in Ruby, use the backfill method on the Schedule Handle. The backfill action executes Actions ahead of their specified time range, useful for executing missed or delayed Actions. Example: handle = my_client.schedule_handle('my-schedule-id'); now = Time.now(in: 'UTC'); handle.backfill(Temporalio::Client::Schedule::Backfill.new(start_at: now - (4 * 60), end_at: now - (2 * 60), overlap: Temporalio::Client::Schedule::OverlapPolicy::ALLOW_ALL)).

Delete a scheduled workflow in Ruby

To delete a scheduled workflow in Ruby, use the delete method on the Schedule Handle. When you delete a Schedule, it does not affect any Workflows that were already started by the Schedule. Example: handle = my_client.schedule_handle('my-schedule-id'); handle.delete.

Describe a scheduled workflow in Ruby

To describe a scheduled workflow in Ruby, use the describe method on the Schedule Handle. This shows the current Schedule configuration, including information about past, current, and future Workflow Runs. Example: handle = my_client.schedule_handle('my-schedule-id'); desc = handle.describe; puts "Schedule info: #{desc.info}".

List all scheduled workflows in Ruby

To list all schedules in Ruby, use the list_schedules asynchronous method on the Client. This returns an enumerator/enumerable. If a schedule is added or deleted, it may not be available in the list immediately. Example: my_client.list_schedules.each do |sched| puts "Schedule info: #{sched}" end.

Workflow Executions do not retry by default

Workflow Executions do not retry by default. Retry Policies should be used with Workflow Executions only in certain situations.

Ruby SDK Workflow retry policy example

Example of setting retry_policy in Ruby: result = my_client.execute_workflow(MyWorkflow, 'some-input', id: 'my-workflow-id', task_queue: 'my-task-queue', retry_policy: Temporalio::RetryPolicy.new(max_interval: 10))

Set Workflow retry policy in Ruby SDK

A retry_policy can be set when calling start_workflow or execute_workflow methods. Retry Policies work in cooperation with timeouts to provide fine controls to optimize the execution experience.

Example: Start Workflow Execution in Rust

let handle = client.start_workflow( GreetingsWorkflow::run, (), WorkflowStartOptions::new( "my-task-queue", "greetings-workflow-10", ).build() ).await?; This example starts a Workflow named GreetingsWorkflow with empty input, on task queue "my-task-queue" with workflow ID "greetings-workflow-10".

Set Task Queue for Workflow in Rust

Set the Task Queue in WorkflowStartOptions using WorkflowStartOptions::new("your-task-queue", "your-workflow-id").build(). In most cases, Task Queue is a required Workflow option. For a Workflow to make progress, at least one Worker must be polling the same Task Queue.

Start Workflow Execution in Rust with client.start_workflow

To start a Workflow Execution, use client.start_workflow(WorkflowType::run, input, WorkflowStartOptions::new("task-queue", "workflow-id").build()).await? The method requires the Workflow Type, Workflow input, a Task Queue that a Worker is polling, and a Workflow Id. This creates the first WorkflowExecutionStarted Event in Event History, followed by the first WorkflowTaskScheduled Event.

Example: Get Workflow results in Rust

let handle = client .start_workflow( GreetingsWorkflow::run, (), WorkflowStartOptions::new( "your-task-queue", "your-workflow-id" ).build(), ).await?; let result = handle.get_result(WorkflowGetResultOptions::default()).await; println!("Result: {:?}", result); This example shows how to start a Workflow and retrieve its result.

Set Workflow Id in Rust

Set the Workflow Id in WorkflowStartOptions using the second parameter in WorkflowStartOptions::new("task-queue", "your-workflow-id"). A Workflow Id is required and should usually map to a business process or business entity identifier, such as an order ID or customer ID.

Accessing workflow state in Rust

Workflow state is accessed using ctx.state(|s| ...) which provides a closure to access the workflow struct fields. Example: let name = ctx.state(|s| s.name.clone());

Starting a workflow from the CLI

Workflows are started using the temporal CLI with the command: temporal workflow start --type <WorkflowName> --task-queue <task-queue-name> --input <input-json>. Example: temporal workflow start --type GreetingWorkflow --task-queue my-task-queue --input '"Ziggy"'

Workflow definition in Rust

Workflows are defined using the #[workflow] macro on a struct and #[workflow_methods] macro on an impl block. The struct holds workflow state. Methods use #[init] for the constructor and #[run] for the main workflow logic. The #[run] method receives &mut WorkflowContext<Self> and returns WorkflowResult<T>. Example: #[workflow] pub struct GreetingWorkflow { name: String; } #[workflow_methods] impl GreetingWorkflow { #[init] fn new(_ctx: &WorkflowContextView, name: String) -> Self { Self { name } } #[run] pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> { ... } }

Workflow return type WorkflowResult

The #[run] method must return WorkflowResult<T>, which is a type alias for Result<T, WorkflowTermination>. Success is represented by Ok(value) and failure by Err(...). Workflow return values must be serializable.

Workflow struct with macros in Rust

A Workflow Definition in the Rust SDK consists of a struct decorated with the #[workflow] macro and an associated impl block decorated with #[workflow_methods] macro. The struct holds the Workflow state, and the impl block contains the Workflow methods.

Rust Workflow struct fields must be serializable

The Workflow struct holds the state of your Workflow Execution, which is persisted and recovered during replays. All fields in a Workflow struct should be serializable.

#[init] method optional initialization

The #[init] method is optional and is called when the Workflow first starts. It receives initial Workflow input parameters and initializes the Workflow struct. It receives a WorkflowContextView, which provides read-only access to Workflow execution information. The #[init] method can have any number of parameters with the same signature as the #[run] method.

#[run] method required Workflow logic

The #[run] method is required and contains the main Workflow logic. It must be async, must be public, receives a mutable WorkflowContext<Self>, returns WorkflowResult<T> where T is the Workflow return type, and executes exactly once per Workflow execution.

Workflow input parameters should use structs

Temporal Workflows may have any number of custom parameters. It is strongly recommended that structs are used as parameters, so that the object's individual fields may be altered without breaking the signature of the Workflow. All Workflow Definition parameters must be serializable by serde.

Customize Workflow type name with #[workflow] macro

Workflows have a Type that is referred to as the Workflow name. You can customize the Workflow type by providing a name parameter to the #[workflow] macro: #[workflow(name = "my-custom-workflow")]. The Workflow Type defaults to the struct name if not specified.

Rust Workflow deterministic execution requirements

Workflow code must be deterministic because the Temporal Server may replay your Workflow to reconstruct its state. Do not use: direct system time access (use ctx.workflow_time() instead of SystemTime::now()), random number generation (use ctx.random_seed() instead), external I/O like network or filesystem calls, UUID generation via random means, or tokio/futures concurrency primitives like tokio::select! or futures::select! that introduce non-deterministic behavior.

Rust Workflow-safe deterministic primitives

The Rust SDK provides these deterministic primitives for use in Workflow code: ctx.timer() for waiting a duration, ctx.wait_condition(closure) to wait until a condition is true, workflows::select! for deterministic select statements, ctx.start_activity() to execute Activities, ctx.start_local_activity() to execute local Activities, ctx.child_workflow() to execute child Workflows, and ctx.cancelled() to check if Workflow is cancelled.

Use deterministic wrappers instead of tokio primitives

Instead of using tokio or futures concurrency primitives directly in Workflow code, use the deterministic wrappers provided in temporalio_sdk::workflows: select! for deterministic select (polls in declaration order), join! for deterministic join of a fixed number of futures, and join_all for deterministic join of a dynamic collection of futures.

Access Workflow state with ctx.state() and ctx.state_mut()

Use ctx.state() for read-only access and ctx.state_mut() for mutable access to your Workflow state. In synchronous Signal and Update handlers, you can mutate state directly via &mut self.

ApplicationFailure for Workflow errors

For application failures in Workflows, construct an ApplicationFailure and convert it into WorkflowTermination by returning Err(ApplicationFailure::new("message").into()). Workflow errors cause the Workflow Execution to fail and the error details become available to clients.

Rust Workflow example with init and run methods

Example showing a basic Workflow with #[init] and #[run] methods: ```rust use temporalio_macros::{workflow, workflow_methods}; use temporalio_sdk::{WorkflowResult, WorkflowContextView, WorkflowContext}; #[workflow] pub struct GreetingWorkflow { name: String, } #[workflow_methods] impl GreetingWorkflow { #[init] fn new(_ctx: &WorkflowContextView, name: String) -> Self { Self { name } } #[run] pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> { let name = ctx.state(|s| s.name.clone()); Ok(format!("Hello, {}!", name)) } } ```

Rust Workflow with multiple init and run parameters

Example showing a Workflow where both #[init] and #[run] have the same parameters: ```rust #[workflow_methods] impl WorkflowRunSeesWorkflowInitWorkflow { #[init] fn new(_ctx: &WorkflowContextView, workflow_input: MyWorkflowInput) -> Self { Self { name_with_title: format!("Knight {}", workflow_input.name), title_has_been_checked: false, } } #[run] pub async fn get_greeting( ctx: &mut WorkflowContext<Self>, _workflow_input: MyWorkflowInput, ) -> WorkflowResult<String> { ctx.wait_condition(|state| state.title_has_been_checked).await; let name_with_title = ctx.state(|state| state.name_with_title.clone()); Ok(format!("Hello, {}", name_with_title)) } } ```

Rust Workflow input with struct parameter

Example showing a Workflow that receives structured input via #[init]: ```rust use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize)] pub struct ProcessingInput { pub data: Vec<String>, pub timeout_seconds: u32, } #[workflow] pub struct ProcessingWorkflow { data: Vec<String>, timeout_seconds: u32, } #[workflow_methods] impl ProcessingWorkflow { #[init] fn new(_ctx: &WorkflowContextView, input: ProcessingInput) -> Self { Self { data: input.data, timeout_seconds: input.timeout_seconds, } } #[run] pub async fn run(_ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> { Ok("Processing complete".to_string()) } } ```

Rust Workflow deterministic operations example

Example showing proper use of deterministic Workflow-safe primitives: ```rust use std::time::Duration; #[run] pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> { // Good - deterministic timer ctx.timer(TimerOptions { duration: Duration::from_secs(60), summary: Some("important timer".into()) }).await; // Good - deterministic wait for condition ctx.wait_condition(|s| s.data.len() >= 3).await; // Bad - nondeterministic sleep // tokio::time::sleep(Duration::from_secs(10)).await; // Bad - nondeterministic time // SystemTime::now() Ok("Done".to_string()) } ```

Rust Workflow ApplicationFailure example

Example showing how to return application failures from a Workflow: ```rust use temporalio_sdk::ApplicationFailure; #[run] pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> { if some_validation_fails { return Err(ApplicationFailure::new("validation_failed: Input is invalid").into()); } Ok("Success".to_string()) } ```

Cancel a Workflow Execution in Rust

To cancel a Workflow Execution in Rust, use the cancel method on the Workflow handle. Call handle.cancel() with WorkflowCancelOptions that can include a reason. This sends a graceful cancellation signal that records a WorkflowExecutionCancelRequested event in the Event History and schedules a Workflow Task to process the cancellation, allowing the Workflow code to execute cleanup logic.

Workflow cancellation graceful stop characteristics

Canceling a Workflow provides a graceful way to stop Workflow Execution, similar to sending SIGTERM to a process. The system records a WorkflowExecutionCancelRequested event in the Event History, a Workflow Task gets scheduled to process the cancellation, the Workflow code can handle the cancellation and execute cleanup logic, and the system does not forcefully stop the Workflow.

Give your agent this brain