Skip to content

Commit

Permalink
[Refactor] Remove global config references (#317)
Browse files Browse the repository at this point in the history
* Remove global config from client specs

* Remove global configuration from client and connection

* Remove global configuration from integration specs

* Remove global config from error messages and comments

* Remove global config from specs

* Remove global config from worker spec

* Add README section on global vs local configuration
  • Loading branch information
antstorm authored Sep 4, 2024
1 parent c73a07e commit f41efb7
Show file tree
Hide file tree
Showing 26 changed files with 129 additions and 83 deletions.
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,47 @@ Temporal.configure do |config|
end
```

## Configuration

This gem is optimised for the smoothest out-of-the-box experience, which is achieved using a global
configuration:

```ruby
Temporal.configure do |config|
config.host = '127.0.0.1' # sets global host
...
end

Temporal::Worker.new # uses global host
Temporal.start_workflow(...) # uses global host
```

This will work just fine for simpler use-cases, however at some point you might need to setup
multiple clients and workers within the same instance of your app (e.g. you have different Temporal
hosts, need to use different codecs/converters for different parts of your app, etc). Should this be
the case we recommend using explicit local configurations for each client/worker:

```ruby
config_1 = Temporal::Configuration.new
config_1.host = 'temporal-01'

config_2 = Temporal::Configuration.new
config_2.host = 'temporal-01'

worker_1 = Temporal::Worker.new(config_1)
worker_2 = Temporal::Worker.new(config_2)

client_1 = Temporal::Client.new(config_1)
client_1.start_workflow(...)

client_2 = Temporal::Client.new(config_2)
client_2.start_workflow(...)
```

*NOTE: Almost all the methods on the `Temporal` module are delegated to the default client that's
initialized using global configuration. The same methods can be used directly on your own client
instances.*

## Workflows

A workflow is defined using pure Ruby code, however it should contain only a high-level
Expand Down
7 changes: 5 additions & 2 deletions examples/init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@

metrics_logger = Logger.new(STDOUT, progname: 'metrics')

DEFAULT_NAMESPACE = 'ruby-samples'.freeze
DEFAULT_TASK_QUEUE = 'general'.freeze

Temporal.configure do |config|
config.host = ENV.fetch('TEMPORAL_HOST', 'localhost')
config.port = ENV.fetch('TEMPORAL_PORT', 7233).to_i
config.namespace = ENV.fetch('TEMPORAL_NAMESPACE', 'ruby-samples')
config.task_queue = ENV.fetch('TEMPORAL_TASK_QUEUE', 'general')
config.namespace = ENV.fetch('TEMPORAL_NAMESPACE', DEFAULT_NAMESPACE)
config.task_queue = ENV.fetch('TEMPORAL_TASK_QUEUE', DEFAULT_TASK_QUEUE)
config.metrics_adapter = Temporal::MetricsAdapters::Log.new(metrics_logger)
end
8 changes: 6 additions & 2 deletions examples/spec/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def wait_for_workflow_completion(workflow_id, run_id)
def fetch_history(workflow_id, run_id, options = {})
connection = Temporal.send(:default_client).send(:connection)
options = {
namespace: Temporal.configuration.namespace,
namespace: integration_spec_namespace,
workflow_id: workflow_id,
run_id: run_id,
}.merge(options)
Expand All @@ -30,6 +30,10 @@ def fetch_history(workflow_id, run_id, options = {})
end

def integration_spec_namespace
ENV.fetch('TEMPORAL_NAMESPACE', 'ruby-samples')
ENV.fetch('TEMPORAL_NAMESPACE', DEFAULT_NAMESPACE)
end

def integration_spec_task_queue
ENV.fetch('TEMPORAL_TASK_QUEUE', DEFAULT_TASK_QUEUE)
end
end
4 changes: 1 addition & 3 deletions examples/spec/integration/converter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
end

around(:each) do |example|
task_queue = Temporal.configuration.task_queue

Temporal.configure do |config|
config.task_queue = 'crypt'
config.payload_codec = codec
Expand All @@ -22,7 +20,7 @@
example.run
ensure
Temporal.configure do |config|
config.task_queue = task_queue
config.task_queue = integration_spec_task_queue
config.payload_codec = Temporal::Configuration::DEFAULT_PAYLOAD_CODEC
end
end
Expand Down
4 changes: 2 additions & 2 deletions examples/spec/integration/create_schedule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"Test",
options: {
workflow_id: workflow_id,
task_queue: Temporal.configuration.task_queue
task_queue: integration_spec_task_queue
}
),
policies: Temporal::Schedule::SchedulePolicies.new(
Expand Down Expand Up @@ -74,7 +74,7 @@
action: Temporal::Schedule::StartWorkflowAction.new(
"HelloWorldWorkflow",
"Test",
options: {task_queue: Temporal.configuration.task_queue}
options: {task_queue: integration_spec_task_queue}
)
)

Expand Down
2 changes: 1 addition & 1 deletion examples/spec/integration/delete_schedule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"HelloWorldWorkflow",
"Test",
options: {
task_queue: Temporal.configuration.task_queue
task_queue: integration_spec_task_queue
}
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@
# That worker runs a task queue, error_serialization_v2. This setup code will
# route workflow requests to that task queue.
around(:each) do |example|
task_queue = Temporal.configuration.task_queue

Temporal.configure do |config|
config.task_queue = 'error_serialization_v2'
end

example.run
ensure
Temporal.configure do |config|
config.task_queue = task_queue
config.task_queue = integration_spec_task_queue
end
end

Expand Down
2 changes: 1 addition & 1 deletion examples/spec/integration/list_schedules_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"HelloWorldWorkflow",
"Test",
options: {
task_queue: Temporal.configuration.task_queue
task_queue: integration_spec_task_queue
}
)
)
Expand Down
2 changes: 1 addition & 1 deletion examples/spec/integration/metadata_workflow_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
run_id: run_id,
)

expect(actual_result.task_queue).to eq(Temporal.configuration.task_queue)
expect(actual_result.task_queue).to eq(integration_spec_task_queue)
end

it 'workflow can retrieve its headers' do
Expand Down
2 changes: 1 addition & 1 deletion examples/spec/integration/pause_schedule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"HelloWorldWorkflow",
"Test",
options: {
task_queue: Temporal.configuration.task_queue
task_queue: integration_spec_task_queue
}
)
)
Expand Down
12 changes: 6 additions & 6 deletions examples/spec/integration/reset_workflow_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
require 'workflows/query_workflow'
require 'temporal/reset_reapply_type'

describe 'Temporal.reset_workflow' do
describe 'Temporal.reset_workflow', :integration do
it 'can reset a closed workflow to the beginning' do
workflow_id = SecureRandom.uuid
original_run_id = Temporal.start_workflow(
Expand All @@ -19,7 +19,7 @@
expect(original_result).to eq('Hello World, Test')

new_run_id = Temporal.reset_workflow(
Temporal.configuration.namespace,
integration_spec_namespace,
workflow_id,
original_run_id,
strategy: Temporal::ResetStrategy::FIRST_WORKFLOW_TASK
Expand All @@ -36,7 +36,7 @@
def reset_hello_world_workflow_twice(workflow_id, original_run_id, request_id:)
2.times.map do
new_run_id = Temporal.reset_workflow(
Temporal.configuration.namespace,
integration_spec_namespace,
workflow_id,
original_run_id,
strategy: Temporal::ResetStrategy::FIRST_WORKFLOW_TASK,
Expand Down Expand Up @@ -130,7 +130,7 @@ def start_query_workflow_and_signal_three_times
workflow_id, original_run_id = start_query_workflow_and_signal_three_times.values_at(:workflow_id, :run_id)

new_run_id = Temporal.reset_workflow(
Temporal.configuration.namespace,
integration_spec_namespace,
workflow_id,
original_run_id,
strategy: Temporal::ResetStrategy::FIRST_WORKFLOW_TASK,
Expand All @@ -147,7 +147,7 @@ def start_query_workflow_and_signal_three_times
workflow_id, original_run_id = start_query_workflow_and_signal_three_times.values_at(:workflow_id, :run_id)

new_run_id = Temporal.reset_workflow(
Temporal.configuration.namespace,
integration_spec_namespace,
workflow_id,
original_run_id,
strategy: Temporal::ResetStrategy::FIRST_WORKFLOW_TASK,
Expand All @@ -160,4 +160,4 @@ def start_query_workflow_and_signal_three_times
Temporal.terminate_workflow(workflow_id, run_id: new_run_id)
end
end


12 changes: 6 additions & 6 deletions examples/spec/integration/start_workflow_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'workflows/hello_world_workflow'
require 'workflows/long_workflow'

describe 'Temporal.start_workflow' do
describe 'Temporal.start_workflow', :integration do
let(:workflow_id) { SecureRandom.uuid }

it 'starts a workflow using a class reference' do
Expand All @@ -21,15 +21,15 @@
it 'starts a workflow using a string reference' do
run_id = Temporal.start_workflow('HelloWorldWorkflow', 'Test', options: {
workflow_id: workflow_id,
namespace: Temporal.configuration.namespace,
task_queue: Temporal.configuration.task_queue
namespace: integration_spec_namespace,
task_queue: integration_spec_task_queue
})

result = Temporal.await_workflow_result(
'HelloWorldWorkflow',
workflow_id: workflow_id,
run_id: run_id,
namespace: Temporal.configuration.namespace
namespace: integration_spec_namespace
)

expect(result).to eq('Hello World, Test')
Expand Down Expand Up @@ -82,11 +82,11 @@
})

execution_1 = Temporal.fetch_workflow_execution_info(
Temporal.configuration.namespace,
integration_spec_namespace,
workflow_id,
run_id_1)
execution_2 = Temporal.fetch_workflow_execution_info(
Temporal.configuration.namespace,
integration_spec_namespace,
workflow_id,
run_id_2)

Expand Down
2 changes: 1 addition & 1 deletion examples/spec/integration/trigger_schedule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"HelloWorldWorkflow",
"Test",
options: {
task_queue: Temporal.configuration.task_queue
task_queue: integration_spec_task_queue
}
)
)
Expand Down
4 changes: 2 additions & 2 deletions examples/spec/integration/update_schedule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"HelloWorldWorkflow",
"Test",
options: {
task_queue: Temporal.configuration.task_queue
task_queue: integration_spec_task_queue
}
),
policies: Temporal::Schedule::SchedulePolicies.new(
Expand All @@ -42,7 +42,7 @@
"HelloWorldWorkflow",
"UpdatedInput",
options: {
task_queue: Temporal.configuration.task_queue
task_queue: integration_spec_task_queue
}
),
policies: Temporal::Schedule::SchedulePolicies.new(
Expand Down
2 changes: 1 addition & 1 deletion lib/temporal/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ def reset_workflow(namespace, workflow_id, run_id, strategy: nil, workflow_task_
# for reference
# @param details [String, Array, nil] optional details to be stored in history
def terminate_workflow(workflow_id, namespace: nil, run_id: nil, reason: nil, details: nil)
namespace ||= Temporal.configuration.namespace
namespace ||= config.namespace

connection.terminate_workflow_execution(
namespace: namespace,
Expand Down
2 changes: 1 addition & 1 deletion lib/temporal/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def for_connection
credentials: credentials,
identity: identity || default_identity,
converter: converter,
connection_options: connection_options.merge(use_error_serialization_v2: @use_error_serialization_v2)
connection_options: connection_options.merge(use_error_serialization_v2: use_error_serialization_v2)
).freeze
end

Expand Down
2 changes: 1 addition & 1 deletion lib/temporal/connection/grpc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ def respond_activity_task_completed_by_id(namespace:, activity_id:, workflow_id:
end

def respond_activity_task_failed(namespace:, task_token:, exception:)
serialize_whole_error = options.fetch(:use_error_serialization_v2, Temporal.configuration.use_error_serialization_v2)
serialize_whole_error = options.fetch(:use_error_serialization_v2)
request = Temporalio::Api::WorkflowService::V1::RespondActivityTaskFailedRequest.new(
namespace: namespace,
identity: identity,
Expand Down
2 changes: 1 addition & 1 deletion lib/temporal/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ChildWorkflowTerminatedError < Error; end

# A superclass for activity exceptions raised explicitly
# with the intent to propagate to a workflow
# With v2 serialization (set with Temporal.configuration set with use_error_serialization_v2=true) you can
# With v2 serialization (set with Temporal::Configuration#use_error_serialization_v2=true) you can
# throw any exception from an activity and expect that it can be handled by the workflow.
class ActivityException < ClientError; end

Expand Down
4 changes: 2 additions & 2 deletions lib/temporal/workflow/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def self.generate_error(failure, converter, default_exception_class = StandardEr
exception_or_message = converter.from_details_payloads(details)
# v1 serialization only supports StandardErrors with a single "message" argument.
# v2 serialization supports complex errors using our converters to serialize them.
# enable v2 serialization in activities with Temporal.configuration.use_error_serialization_v2
# enable v2 serialization in activities with Temporal::Configuration#use_error_serialization_v2
if exception_or_message.is_a?(Exception)
exception = exception_or_message
else
Expand All @@ -37,7 +37,7 @@ def self.generate_error(failure, converter, default_exception_class = StandardEr
exception = default_exception_class.new(message)
Temporal.logger.error(
"Could not instantiate original error. Defaulting to StandardError. Make sure the worker running " \
"your activities is setting Temporal.configuration.use_error_serialization_v2. If so, make sure the " \
"your activities is configured with use_error_serialization_v2. If so, make sure the " \
"original error serialized by searching your logs for 'unserializable_error'. If not, you're using "\
"legacy serialization, and it's likely that "\
"your error's initializer takes something other than exactly one positional argument.",
Expand Down
5 changes: 0 additions & 5 deletions spec/config/temporal.rb

This file was deleted.

Loading

0 comments on commit f41efb7

Please sign in to comment.