Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Prerequisites:
* [rails_app](rails_app) - Basic Rails API application using Temporal workflows and activities.
* [saga](saga) - Using undo/compensation using a very simplistic Saga pattern.
* [sorbet_generic](sorbet_generic) - Proof of concept of how to do _advanced_ Sorbet typing with the SDK.
* [standalone_activity](standalone_activity) - Execute, start, list, and count Standalone Activities -- Activities run directly from a Client without a Workflow.
* [updatable_timer](updatable_timer) - Demonstrates a blocking sleep that can be updated.
* [worker_specific_task_queues](worker_specific_task_queues) - Use a unique Task Queue for each Worker to run a sequence of Activities on the same Worker.
* [worker_versioning](worker_versioning) - Use the Worker Versioning feature to more easily version your workflows & other code.
Expand Down
74 changes: 74 additions & 0 deletions standalone_activity/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Standalone Activity

This sample demonstrates [Standalone Activities](https://docs.temporal.io/standalone-activity):
Activities executed directly from a Client, without a Workflow.

To run, first see [README.md](../README.md) for prerequisites. Standalone Activities require
Temporal CLI v1.7.0+ and Temporal Server v1.31.0+.

Start a Temporal dev server in one terminal:

temporal server start-dev

In another terminal, start the Worker from this directory:

bundle exec ruby worker.rb

The Worker registers `ComposeGreeting` and polls the `standalone-activity-sample` Task Queue.
No Workflows are required.

## Execute a Standalone Activity

Run an Activity from the Client and block until the result is returned:

bundle exec ruby execute_activity.rb

Expected output:

Activity result: Hello, World!

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

Start an Activity, get back an `ActivityHandle`, and fetch the result later:

bundle exec ruby 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"'

## List Standalone Activities

List Standalone Activity Executions matching a [List Filter](https://docs.temporal.io/list-filter):

bundle exec ruby list_activities.rb

Or use the Temporal CLI:

temporal activity list --query "TaskQueue = 'standalone-activity-sample'"

## Count Standalone Activities

Count Standalone Activity Executions matching a List Filter:

bundle exec ruby count_activities.rb

Or use the Temporal CLI:

temporal activity count --query "TaskQueue = 'standalone-activity-sample'"
20 changes: 20 additions & 0 deletions standalone_activity/count_activities.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

require 'temporalio/client'
require 'temporalio/env_config'

# Load config and apply defaults
args, kwargs = Temporalio::EnvConfig::ClientConfig.load_client_connect_options
args[0] ||= 'localhost:7233' # Default address
args[1] ||= 'default' # Default namespace

client = Temporalio::Client.connect(*args, **kwargs)

# Count Standalone Activity Executions matching a query. Only Standalone
# Activity Executions are counted -- Activities scheduled inside Workflows
# are not.
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
24 changes: 24 additions & 0 deletions standalone_activity/execute_activity.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

require 'temporalio/client'
require 'temporalio/env_config'
require_relative 'my_activities'

# Load config and apply defaults
args, kwargs = Temporalio::EnvConfig::ClientConfig.load_client_connect_options
args[0] ||= 'localhost:7233' # Default address
args[1] ||= 'default' # Default namespace

client = Temporalio::Client.connect(*args, **kwargs)

# Execute a Standalone Activity directly from the Client and block until it
# returns a result. The Activity is durably enqueued on the Server and run by
# the Worker registered for the same Task Queue.
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}"
18 changes: 18 additions & 0 deletions standalone_activity/list_activities.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require 'temporalio/client'
require 'temporalio/env_config'

# Load config and apply defaults
args, kwargs = Temporalio::EnvConfig::ClientConfig.load_client_connect_options
args[0] ||= 'localhost:7233' # Default address
args[1] ||= 'default' # Default namespace

client = Temporalio::Client.connect(*args, **kwargs)

# List Standalone Activity Executions on this Task Queue. Only Standalone
# Activity Executions are returned -- Activities scheduled inside Workflows
# are not.
client.list_activities("TaskQueue = 'standalone-activity-sample'").each do |execution|
puts "#{execution.activity_id} #{execution.activity_type} #{execution.status}"
end
13 changes: 13 additions & 0 deletions standalone_activity/my_activities.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require 'temporalio/activity'

module StandaloneActivity
module MyActivities
class ComposeGreeting < Temporalio::Activity::Definition
def execute(greeting, name)
"#{greeting}, #{name}!"
end
end
end
end
26 changes: 26 additions & 0 deletions standalone_activity/start_activity.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require 'temporalio/client'
require 'temporalio/env_config'
require_relative 'my_activities'

# Load config and apply defaults
args, kwargs = Temporalio::EnvConfig::ClientConfig.load_client_connect_options
args[0] ||= 'localhost:7233' # Default address
args[1] ||= 'default' # Default namespace

client = Temporalio::Client.connect(*args, **kwargs)

# Start a Standalone Activity without waiting for the result. The call returns
# as soon as the Activity is durably enqueued on the Server.
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 via the handle.
puts "Activity result: #{handle.result}"
26 changes: 26 additions & 0 deletions standalone_activity/worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require 'logger'
require 'temporalio/client'
require 'temporalio/env_config'
require 'temporalio/worker'
require_relative 'my_activities'

# Load config and apply defaults
args, kwargs = Temporalio::EnvConfig::ClientConfig.load_client_connect_options
args[0] ||= 'localhost:7233' # Default address
args[1] ||= 'default' # Default namespace

client = Temporalio::Client.connect(*args, **kwargs, logger: Logger.new($stdout, level: Logger::INFO))

# A Worker for Standalone Activities is configured the same way as one for
# Workflow Activities: register the Activity classes and run the Worker. No
# Workflows are required.
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'])