Standalone Activities - Ruby SDK
Temporal Ruby SDK support for Standalone Activities is at Pre-release.
Standalone Activities are Activities that run independently, without being orchestrated by a
Workflow. Instead of starting an Activity from within a Workflow Definition, you start a Standalone
Activity directly from a Temporalio::Client.
The way you write the Activity and register it with a Worker is identical to Workflow Activities. The only difference is that you execute a Standalone Activity directly from your Temporal Client.
This page covers the following:
- Get Started with Standalone Activities
- Define your Activity
- Run a Worker with the Activity registered
- Execute a Standalone Activity
- Start a Standalone Activity without waiting for the result
- Get a handle to an existing Standalone Activity
- Wait for the result of a Standalone Activity
- List Standalone Activities
- Count Standalone Activities
- Run Standalone Activities with Temporal Cloud
This documentation uses source code from the standalone_activity sample.
Get Started with Standalone Activities
Prerequisites:
-
Ruby 3.3+
-
Temporal Ruby SDK (v1.5.0 or higher). See the Ruby Quickstart for install instructions.
-
Temporal CLI v1.7.0 or higher
Install with Homebrew:
brew install temporalOr see the Temporal CLI install guide for other platforms.
Verify the installation:
temporal --version
Start the Temporal development server:
temporal server start-dev
This command automatically starts the Temporal development server with the Web UI, and creates the default Namespace.
It uses an in-memory database, so do not use it for real use cases.
All code samples on this page use
Temporalio::EnvConfig::ClientConfig.load_client_connect_options
to configure the Temporal Client connection. It responds to environment
variables and TOML configuration
files, so the same code works against a local dev
server and Temporal Cloud without changes. See Run Standalone Activities with Temporal
Cloud below.
The Temporal Server will now be available for client connections on localhost:7233, and the
Temporal Web UI will now be accessible at http://localhost:8233. Standalone
Activities are available from the nav bar item located towards the top left of the page:
Clone the samples-ruby repository to follow along:
git clone https://github.com/temporalio/samples-ruby.git
cd samples-ruby
bundle install
The sample consists of separate programs in the standalone_activity directory:
standalone_activity/
├── my_activities.rb # Activity definition
├── worker.rb # Worker that processes activity tasks
├── execute_activity.rb # Starts an activity and waits for the result
├── start_activity.rb # Starts an activity without blocking
├── list_activities.rb # Lists activity executions
└── count_activities.rb # Counts activity executions
Define your Activity
An Activity in the Temporal Ruby SDK is a subclass of Temporalio::Activity::Definition that
implements an execute method. The way you define a Standalone Activity is identical to how you
define an Activity orchestrated by a Workflow. In fact, the same Activity can be executed both as a
Standalone Activity and as a Workflow Activity.
require 'temporalio/activity'
module StandaloneActivity
module MyActivities
class ComposeGreeting < Temporalio::Activity::Definition
def execute(greeting, name)
"#{greeting}, #{name}!"
end
end
end
end
Run a Worker with the Activity registered
Running a Worker for Standalone Activities is the same as running a Worker for Workflow Activities —
you create a Temporalio::Worker, register the Activity class, and call worker.run. The Worker
doesn't need to know whether the Activity will be invoked from a Workflow or as a Standalone
Activity. See How to run a Worker for more details on
Worker setup and configuration options.
args, kwargs = Temporalio::EnvConfig::ClientConfig.load_client_connect_options
args[0] ||= 'localhost:7233'
args[1] ||= 'default'
client = Temporalio::Client.connect(*args, **kwargs)
worker = Temporalio::Worker.new(
client:,
task_queue: 'standalone-activity-sample',
activities: [StandaloneActivity::MyActivities::ComposeGreeting]
)
puts 'Starting worker (ctrl+c to exit)'
worker.run(shutdown_signals: ['SIGINT'])
Open a new terminal, navigate to the samples-ruby directory, and run the Worker:
bundle exec ruby standalone_activity/worker.rb
Leave this terminal running — the Worker needs to stay up to process activities.
Execute a Standalone Activity
Use Temporalio::Client#execute_activity to execute a
Standalone Activity and block until it completes. Call this from your application code, not from
inside a Workflow Definition. This durably enqueues your Standalone Activity in the Temporal Server,
waits for it to be executed on your Worker, and then returns the result.
result = client.execute_activity(
StandaloneActivity::MyActivities::ComposeGreeting,
'Hello', 'World',
id: 'standalone-activity-id',
task_queue: 'standalone-activity-sample',
start_to_close_timeout: 10
)
puts "Activity result: #{result}"
The first argument is the Activity to run. It can be the Activity::Definition subclass, an
instance of one, or a string/symbol name. Positional arguments after it are passed to the Activity's
execute method. The call requires id, task_queue, and at least one of start_to_close_timeout
or schedule_to_close_timeout.
To run it:
- Make sure the Temporal Server is running (from the Get Started step above).
- Make sure the Worker is running (from the Run a Worker step above).
- Open a new terminal, navigate to the
samples-rubydirectory, and run:
bundle exec ruby standalone_activity/execute_activity.rb
Or use the Temporal CLI:
temporal activity execute \
--type ComposeGreeting \
--activity-id standalone-activity-id \
--task-queue standalone-activity-sample \
--start-to-close-timeout 10s \
--input '"Hello"' \
--input '"World"'
Start a Standalone Activity without waiting for the result
Starting a Standalone Activity means sending a request to the Temporal Server to durably enqueue your Activity job, without waiting for it to be executed by your Worker.
Use Temporalio::Client#start_activity to start a
Standalone Activity and get a handle without waiting for the result:
handle = client.start_activity(
StandaloneActivity::MyActivities::ComposeGreeting,
'Hello', 'World',
id: 'standalone-activity-id',
task_queue: 'standalone-activity-sample',
start_to_close_timeout: 10
)
puts "Started Activity with id=#{handle.id} run_id=#{handle.run_id}"
# Wait for the result later
puts "Activity result: #{handle.result}"
With the Temporal Server and Worker running, open a new terminal in the samples-ruby directory and
run:
bundle exec ruby standalone_activity/start_activity.rb
Or use the Temporal CLI:
temporal activity start \
--type ComposeGreeting \
--activity-id standalone-activity-id \
--task-queue standalone-activity-sample \
--start-to-close-timeout 10s \
--input '"Hello"' \
--input '"World"'
Get a handle to an existing Standalone Activity
Use Temporalio::Client#activity_handle to create an ActivityHandle for a previously started Standalone Activity:
handle = client.activity_handle('standalone-activity-id')
Pass no run ID (the default) to target the latest run of the given Activity ID, or pass
activity_run_id: to target a specific run. You can then use the handle to wait for the result,
describe, cancel, or terminate the Activity:
handle.result # block until the activity completes; returns the result
handle.describe # fetch metadata (status, timestamps, attempt, last failure, etc.)
handle.cancel # request cancellation
handle.terminate # force-close the activity
Wait for the result of a Standalone Activity
Under the hood, calling client.execute_activity is the same as calling client.start_activity to
durably enqueue the Standalone Activity, and then calling handle.result to block until the
Activity completes and return the result:
result = handle.result
Or use the Temporal CLI to wait for a result by Activity ID:
temporal activity result --activity-id standalone-activity-id
List Standalone Activities
Use Temporalio::Client#list_activities to list
Standalone Activity Executions that match a List Filter query. The result is an
Enumerator of ActivityExecution values that fetches pages from the server on demand as the
enumerator is consumed.
These APIs return only Standalone Activity Executions. Activities running inside Workflows are not included.
client.list_activities("TaskQueue = 'standalone-activity-sample'").each do |execution|
puts "#{execution.activity_id} #{execution.activity_type} #{execution.status}"
end
Run it:
bundle exec ruby standalone_activity/list_activities.rb
Or use the Temporal CLI:
temporal activity list
The query parameter accepts the same List Filter syntax used for Workflow
Visibility. For example, ActivityType = 'ComposeGreeting' AND Status = 'Running'.
Count Standalone Activities
Use Temporalio::Client#count_activities to count
Standalone Activity Executions that match a List Filter query. This returns the
total count of executions (running, completed, failed, etc.) — not the number of queued tasks. It
works the same way as counting Workflow Executions.
result = client.count_activities("TaskQueue = 'standalone-activity-sample'")
puts "Total: #{result.count}"
result.groups.each do |group|
puts " #{group.group_values.join(',')} => #{group.count}"
end
Run it:
bundle exec ruby standalone_activity/count_activities.rb
Or use the Temporal CLI:
temporal activity count
Run Standalone Activities with Temporal Cloud
The code samples on this page use Temporalio::EnvConfig::ClientConfig.load_client_connect_options,
so the same code works against Temporal Cloud — just configure the connection via environment
variables or a TOML profile. No code changes are needed.
For a step-by-step guide on connecting to Temporal Cloud, including Namespace creation, certificate generation, and authentication setup in the Cloud UI, see Connect to Temporal Cloud.
Connect with mTLS
Set these environment variables with values from your Temporal Cloud Namespace settings:
export TEMPORAL_ADDRESS=<your-namespace>.<your-account-id>.tmprl.cloud:7233
export TEMPORAL_NAMESPACE=<your-namespace>.<your-account-id>
export TEMPORAL_TLS_CLIENT_CERT_PATH='path/to/your/client.pem'
export TEMPORAL_TLS_CLIENT_KEY_PATH='path/to/your/client.key'
Connect with an API key
Set these environment variables with values from your Temporal Cloud API key settings:
export TEMPORAL_ADDRESS=<region>.<cloud_provider>.api.temporal.io:7233
export TEMPORAL_NAMESPACE=<your-namespace>.<your-account-id>
export TEMPORAL_API_KEY=<your-api-key>
Then run the Worker and starter code as shown in the earlier sections.