Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Demonstrate interoperability with Coinbase Ruby SDK #23

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
7 changes: 6 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

source 'https://rubygems.org'

gem 'temporalio'
# Primary Temporal dependency
gem 'temporalio', path: '../temporal-sdk-ruby/temporalio'

# Additional dependencies for certain samples
gem 'google-protobuf', '~> 3.25'
Comment on lines +6 to +9
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix this invalid path-specific dependency when temporalio/sdk-ruby#213 released

gem 'temporal-ruby', path: '../coinbase-temporal-ruby'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point to GitHub repo when coinbase/temporal-ruby#335 merged (or consider pointing to fork temporarily)


group :development do
gem 'minitest'
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Prerequisites:
<!-- Keep this list in alphabetical order -->
* [activity_simple](activity_simple) - Simple workflow that calls two activities.
* [activity_worker](activity_worker) - Use Ruby activities from a workflow in another language.
* [coinbase_ruby](coinbase_ruby) - Demonstrate interoperability with the
[Coinbase Ruby SDK](https://github.com/coinbase/temporal-ruby).
* [context_propagation](context_propagation) - Use interceptors to propagate thread/fiber local data from clients
through workflows/activities.
* [message_passing_simple](message_passing_simple) - Simple workflow that accepts signals, queries, and updates.
Expand Down
24 changes: 24 additions & 0 deletions coinbase_ruby/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Coinbase Ruby

This sample shows a workflow, activity, and client from [Coinbase Ruby SDK](https://github.com/coinbase/temporal-ruby)
Copy link

@mjameswh mjameswh Feb 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sample shows a workflow, activity, and client from Coinbase Ruby SDK able to interoperate with a workflow, activity, and client from Temporal Ruby SDK

Maybe that's just me, but the "… able to …" in the middle reads badly.

able to interoperate with a workflow, activity, and client from Temporal Ruby SDK. Specifically this sample contains an
activity in both SDKs, a workflow in both SDKs each calling both activities, a worker in both SDKs running in the same
process, and a starter with clients from each SDK each invoking both workflows.

To run, first see [README.md](../README.md) for prerequisites. Then, in another terminal, start the Ruby worker
from this directory:

bundle exec ruby worker.rb

Finally in another terminal, use the Ruby client to the workflow from this directory:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Finally in another terminal, use the Ruby client to the workflow from this directory:
Finally in another terminal, use the Ruby client to run the workflow from this directory:


bundle exec ruby starter.rb

The Ruby code will invoke 4 workflows. The output of the final command should be:

```
Coinbase SDK workflow result from Temporal SDK client: ["Hello from Coinbase Ruby SDK, user1!", "Hello from Temporal Ruby SDK, user1!"]
Temporal SDK workflow result from Temporal SDK client: ["Hello from Coinbase Ruby SDK, user2!", "Hello from Temporal Ruby SDK, user2!"]
Coinbase SDK workflow result from Coinbase SDK client: ["Hello from Coinbase Ruby SDK, user3!", "Hello from Temporal Ruby SDK, user3!"]
Temporal SDK workflow result from Coinbase SDK client: ["Hello from Coinbase Ruby SDK, user4!", "Hello from Temporal Ruby SDK, user4!"]
```
9 changes: 9 additions & 0 deletions coinbase_ruby/coinbase_activity.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'temporal-ruby'

module CoinbaseRuby
class CoinbaseActivity < Temporal::Activity
def execute(name)
"Hello from Coinbase Ruby SDK, #{name}!"
end
end
end
15 changes: 15 additions & 0 deletions coinbase_ruby/coinbase_workflow.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'temporal-ruby'
require_relative 'coinbase_activity'

module CoinbaseRuby
class CoinbaseWorkflow < Temporal::Workflow
def execute(name)
[
# Execute activity on Coinbase SDK worker
CoinbaseActivity.execute!(name),
# Execute activity on Temporal SDK worker
workflow.execute_activity!(:TemporalActivity, name, options: { task_queue: 'coinbase-ruby-sample-temporal' })
]
end
end
end
56 changes: 56 additions & 0 deletions coinbase_ruby/starter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

# We must require Temporal SDK first and set the env var to prevent Coinbase SDK from trying to load its protos
require 'temporalio/client'
ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] = '1'

require_relative 'coinbase_workflow'
require_relative 'temporal_workflow'
require 'logger'
require 'temporal-ruby'

# Create Temporal SDK client
client = Temporalio::Client.connect('localhost:7233', 'default')

# Run Coinbase workflow
result = client.execute_workflow(
CoinbaseRuby::CoinbaseWorkflow.name, 'user1',
id: 'coinbase-ruby-sample-workflow-id-1', task_queue: 'coinbase-ruby-sample-coinbase'
)
puts "Coinbase SDK workflow result from Temporal SDK client: #{result}"

# Run Temporal workflow
result = client.execute_workflow(
CoinbaseRuby::TemporalWorkflow, 'user2',
id: 'coinbase-ruby-sample-workflow-id-2', task_queue: 'coinbase-ruby-sample-temporal'
)
puts "Temporal SDK workflow result from Temporal SDK client: #{result}"

# Now do the same with Coinbase SDK, first configuring the client
Temporal.configure do |config|
config.host = 'localhost'
config.port = 7233
config.namespace = 'default'
end

# Run Coinbase workflow
run_id = Temporal.start_workflow(
CoinbaseRuby::CoinbaseWorkflow, 'user3',
options: { workflow_id: 'coinbase-ruby-sample-workflow-id-3', task_queue: 'coinbase-ruby-sample-coinbase' }
)
result = Temporal.await_workflow_result(
CoinbaseRuby::CoinbaseWorkflow,
workflow_id: 'coinbase-ruby-sample-workflow-id-3', run_id:
)
puts "Coinbase SDK workflow result from Coinbase SDK client: #{result}"

# Run Temporal workflow
run_id = Temporal.start_workflow(
:TemporalWorkflow, 'user4',
options: { workflow_id: 'coinbase-ruby-sample-workflow-id-4', task_queue: 'coinbase-ruby-sample-temporal' }
)
result = Temporal.await_workflow_result(
:TemporalWorkflow,
workflow_id: 'coinbase-ruby-sample-workflow-id-4', run_id:
)
puts "Temporal SDK workflow result from Coinbase SDK client: #{result}"
11 changes: 11 additions & 0 deletions coinbase_ruby/temporal_activity.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

require 'temporalio/activity'

module CoinbaseRuby
class TemporalActivity < Temporalio::Activity::Definition
def execute(name)
"Hello from Temporal Ruby SDK, #{name}!"
end
end
end
19 changes: 19 additions & 0 deletions coinbase_ruby/temporal_workflow.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

require 'temporalio/workflow'
require_relative 'coinbase_activity'
require_relative 'temporal_activity'

module CoinbaseRuby
class TemporalWorkflow < Temporalio::Workflow::Definition
def execute(name)
[
# Execute activity on Coinbase SDK worker
Temporalio::Workflow.execute_activity(CoinbaseActivity.name, name,
start_to_close_timeout: 10, task_queue: 'coinbase-ruby-sample-coinbase'),
# Execute activity on Temporal SDK worker
Temporalio::Workflow.execute_activity(TemporalActivity, name, start_to_close_timeout: 10)
]
end
end
end
47 changes: 47 additions & 0 deletions coinbase_ruby/worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

# We must require Temporal SDK first and set the env var to prevent Coinbase SDK from trying to load its protos
require 'temporalio/client'
require 'temporalio/worker'
ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] = '1'

require_relative 'coinbase_activity'
require_relative 'coinbase_workflow'
require_relative 'temporal_activity'
require_relative 'temporal_workflow'
require 'logger'
require 'temporal-ruby'
require 'temporal/worker'

# Create a Temporal client
client = Temporalio::Client.connect(
'localhost:7233',
'default',
logger: Logger.new($stdout, level: Logger::INFO)
)

# Create Temporal worker with the activity and workflow on the coinbase-ruby-sample-temporal task queue
worker = Temporalio::Worker.new(
client:,
task_queue: 'coinbase-ruby-sample-temporal',
activities: [CoinbaseRuby::TemporalActivity],
workflows: [CoinbaseRuby::TemporalWorkflow]
)

# Run the Temporal worker and inside it run the Coinbase worker
puts 'Starting worker on both Temporal Ruby SDK and Coinbase Ruby SDK'
worker.run do
# Configure Coinbase client/worker on the coinbase-ruby-sample-coinbase task queue
Temporal.configure do |config|
config.host = 'localhost'
config.port = 7233
config.namespace = 'default'
config.task_queue = 'coinbase-ruby-sample-coinbase'
end

# Run the Coinbase worker
worker = Temporal::Worker.new
worker.register_activity(CoinbaseRuby::CoinbaseActivity)
worker.register_workflow(CoinbaseRuby::CoinbaseWorkflow)
worker.start
end
75 changes: 75 additions & 0 deletions test/coinbase_ruby/workflow_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

require 'securerandom'
require 'test'
require 'temporalio/testing'
require 'temporalio/worker'
ENV['COINBASE_TEMPORAL_RUBY_DISABLE_PROTO_LOAD'] = '1'
require 'temporal-ruby'
require 'temporal/worker'

require 'coinbase_ruby/coinbase_workflow'
require 'coinbase_ruby/temporal_workflow'

module CoinbaseRuby
class WorkflowTest < Test
def test_both_sdks
# Start a local env
Temporalio::Testing::WorkflowEnvironment.start_local do |env|
# Create Coinbase config, client, and worker
coinbase_config = Temporal::Configuration.new
host, port = env.client.connection.options.target_host.split(':')
coinbase_config.host = host
coinbase_config.port = port.to_i
coinbase_config.namespace = 'default'
coinbase_config.task_queue = 'coinbase-ruby-sample-coinbase'
coinbase_client = Temporal::Client.new(coinbase_config)
coinbase_worker = Temporal::Worker.new(coinbase_config)
coinbase_worker.register_activity(CoinbaseRuby::CoinbaseActivity)
coinbase_worker.register_workflow(CoinbaseRuby::CoinbaseWorkflow)

# Run all inside Temporal worker
worker = Temporalio::Worker.new(
client: env.client,
task_queue: 'coinbase-ruby-sample-temporal',
activities: [CoinbaseRuby::TemporalActivity],
workflows: [CoinbaseRuby::TemporalWorkflow]
)
worker.run do
# Run Coinbase worker in background, stop it when done
Thread.new { coinbase_worker.start }

# Run both workflows from Temporal client
assert_equal ['Hello from Coinbase Ruby SDK, user-a!', 'Hello from Temporal Ruby SDK, user-a!'],
env.client.execute_workflow(
CoinbaseRuby::CoinbaseWorkflow.name, 'user-a',
id: "wf-#{SecureRandom.uuid}", task_queue: 'coinbase-ruby-sample-coinbase'
)
assert_equal ['Hello from Coinbase Ruby SDK, user-b!', 'Hello from Temporal Ruby SDK, user-b!'],
env.client.execute_workflow(
CoinbaseRuby::TemporalWorkflow, 'user-b',
id: "wf-#{SecureRandom.uuid}", task_queue: 'coinbase-ruby-sample-temporal'
)

# Run both workflows from Coinbase client
workflow_id = "wf-#{SecureRandom.uuid}"
run_id = coinbase_client.start_workflow(
CoinbaseRuby::CoinbaseWorkflow, 'user-c',
options: { workflow_id:, task_queue: 'coinbase-ruby-sample-coinbase' }
)
assert_equal ['Hello from Coinbase Ruby SDK, user-c!', 'Hello from Temporal Ruby SDK, user-c!'],
coinbase_client.await_workflow_result(CoinbaseRuby::CoinbaseWorkflow, workflow_id:, run_id:)
workflow_id = "wf-#{SecureRandom.uuid}"
run_id = coinbase_client.start_workflow(
:TemporalWorkflow, 'user-d',
options: { workflow_id:, task_queue: 'coinbase-ruby-sample-temporal' }
)
assert_equal ['Hello from Coinbase Ruby SDK, user-d!', 'Hello from Temporal Ruby SDK, user-d!'],
coinbase_client.await_workflow_result(:TemporalWorkflow, workflow_id:, run_id:)
ensure
coinbase_worker.stop
end
end
end
end
end
Loading