temporalio 0.3.0-x86_64-linux-musl → 0.5.0-x86_64-linux-musl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/Gemfile +4 -0
- data/Rakefile +1 -1
- data/lib/temporalio/activity/cancellation_details.rb +58 -0
- data/lib/temporalio/activity/context.rb +17 -1
- data/lib/temporalio/activity/definition.rb +45 -4
- data/lib/temporalio/activity/info.rb +28 -4
- data/lib/temporalio/activity.rb +2 -0
- data/lib/temporalio/api/activity/v1/message.rb +1 -1
- data/lib/temporalio/api/batch/v1/message.rb +9 -2
- data/lib/temporalio/api/cloud/account/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +11 -2
- data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +2 -2
- data/lib/temporalio/api/cloud/identity/v1/message.rb +7 -2
- data/lib/temporalio/api/cloud/namespace/v1/message.rb +6 -2
- data/lib/temporalio/api/cloud/nexus/v1/message.rb +3 -2
- data/lib/temporalio/api/cloud/operation/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/region/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/resource/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/sink/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/usage/v1/message.rb +1 -1
- data/lib/temporalio/api/command/v1/message.rb +2 -2
- data/lib/temporalio/api/common/v1/grpc_status.rb +1 -1
- data/lib/temporalio/api/common/v1/message.rb +4 -2
- data/lib/temporalio/api/deployment/v1/message.rb +39 -0
- data/lib/temporalio/api/enums/v1/batch_operation.rb +2 -2
- data/lib/temporalio/api/enums/v1/command_type.rb +1 -1
- data/lib/temporalio/api/enums/v1/common.rb +5 -2
- data/lib/temporalio/api/enums/v1/deployment.rb +24 -0
- data/lib/temporalio/api/enums/v1/event_type.rb +2 -2
- data/lib/temporalio/api/enums/v1/failed_cause.rb +2 -2
- data/lib/temporalio/api/enums/v1/namespace.rb +1 -1
- data/lib/temporalio/api/enums/v1/nexus.rb +21 -0
- data/lib/temporalio/api/enums/v1/query.rb +1 -1
- data/lib/temporalio/api/enums/v1/reset.rb +2 -2
- data/lib/temporalio/api/enums/v1/schedule.rb +1 -1
- data/lib/temporalio/api/enums/v1/task_queue.rb +1 -1
- data/lib/temporalio/api/enums/v1/update.rb +1 -1
- data/lib/temporalio/api/enums/v1/workflow.rb +3 -2
- data/lib/temporalio/api/errordetails/v1/message.rb +4 -2
- data/lib/temporalio/api/export/v1/message.rb +1 -1
- data/lib/temporalio/api/failure/v1/message.rb +5 -2
- data/lib/temporalio/api/filter/v1/message.rb +1 -1
- data/lib/temporalio/api/history/v1/message.rb +6 -2
- data/lib/temporalio/api/namespace/v1/message.rb +1 -1
- data/lib/temporalio/api/nexus/v1/message.rb +3 -2
- data/lib/temporalio/api/operatorservice/v1/request_response.rb +1 -1
- data/lib/temporalio/api/operatorservice/v1/service.rb +1 -1
- data/lib/temporalio/api/payload_visitor.rb +162 -7
- data/lib/temporalio/api/protocol/v1/message.rb +1 -1
- data/lib/temporalio/api/query/v1/message.rb +3 -2
- data/lib/temporalio/api/replication/v1/message.rb +1 -1
- data/lib/temporalio/api/rules/v1/message.rb +27 -0
- data/lib/temporalio/api/schedule/v1/message.rb +2 -2
- data/lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb +1 -1
- data/lib/temporalio/api/sdk/v1/task_complete_metadata.rb +1 -1
- data/lib/temporalio/api/sdk/v1/user_metadata.rb +1 -1
- data/lib/temporalio/api/sdk/v1/workflow_metadata.rb +1 -1
- data/lib/temporalio/api/taskqueue/v1/message.rb +5 -2
- data/lib/temporalio/api/testservice/v1/request_response.rb +1 -1
- data/lib/temporalio/api/testservice/v1/service.rb +1 -1
- data/lib/temporalio/api/update/v1/message.rb +1 -1
- data/lib/temporalio/api/version/v1/message.rb +1 -1
- data/lib/temporalio/api/worker/v1/message.rb +30 -0
- data/lib/temporalio/api/workflow/v1/message.rb +22 -2
- data/lib/temporalio/api/workflowservice/v1/request_response.rb +58 -12
- data/lib/temporalio/api/workflowservice/v1/service.rb +2 -2
- data/lib/temporalio/api.rb +1 -0
- data/lib/temporalio/client/async_activity_handle.rb +12 -4
- data/lib/temporalio/client/connection/cloud_service.rb +60 -0
- data/lib/temporalio/client/connection/workflow_service.rb +343 -28
- data/lib/temporalio/client/interceptor.rb +64 -7
- data/lib/temporalio/client/schedule.rb +35 -3
- data/lib/temporalio/client/with_start_workflow_operation.rb +123 -0
- data/lib/temporalio/client/workflow_execution.rb +19 -0
- data/lib/temporalio/client/workflow_handle.rb +47 -7
- data/lib/temporalio/client/workflow_update_handle.rb +9 -3
- data/lib/temporalio/client.rb +231 -4
- data/lib/temporalio/common_enums.rb +14 -0
- data/lib/temporalio/contrib/open_telemetry.rb +474 -0
- data/lib/temporalio/converters/data_converter.rb +18 -8
- data/lib/temporalio/converters/failure_converter.rb +6 -3
- data/lib/temporalio/converters/payload_converter/binary_null.rb +2 -2
- data/lib/temporalio/converters/payload_converter/binary_plain.rb +2 -2
- data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +2 -2
- data/lib/temporalio/converters/payload_converter/composite.rb +6 -4
- data/lib/temporalio/converters/payload_converter/encoding.rb +4 -2
- data/lib/temporalio/converters/payload_converter/json_plain.rb +2 -2
- data/lib/temporalio/converters/payload_converter/json_protobuf.rb +2 -2
- data/lib/temporalio/converters/payload_converter.rb +16 -6
- data/lib/temporalio/error/failure.rb +19 -1
- data/lib/temporalio/error.rb +2 -1
- data/lib/temporalio/internal/bridge/3.2/temporalio_bridge.so +0 -0
- data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.so +0 -0
- data/lib/temporalio/internal/bridge/3.4/temporalio_bridge.so +0 -0
- data/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +1 -1
- data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +3 -2
- data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +1 -1
- data/lib/temporalio/internal/bridge/api/common/common.rb +3 -2
- data/lib/temporalio/internal/bridge/api/core_interface.rb +1 -1
- data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +1 -1
- data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +3 -2
- data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +2 -2
- data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +3 -2
- data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +3 -2
- data/lib/temporalio/internal/bridge/runtime.rb +3 -0
- data/lib/temporalio/internal/bridge/testing.rb +3 -0
- data/lib/temporalio/internal/bridge/worker.rb +28 -4
- data/lib/temporalio/internal/bridge.rb +1 -1
- data/lib/temporalio/internal/client/implementation.rb +281 -51
- data/lib/temporalio/internal/proto_utils.rb +38 -6
- data/lib/temporalio/internal/worker/activity_worker.rb +107 -25
- data/lib/temporalio/internal/worker/multi_runner.rb +2 -2
- data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +8 -6
- data/lib/temporalio/internal/worker/workflow_instance/context.rb +96 -5
- data/lib/temporalio/internal/worker/workflow_instance/details.rb +7 -2
- data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +2 -2
- data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +64 -18
- data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +39 -40
- data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +22 -2
- data/lib/temporalio/internal/worker/workflow_instance.rb +134 -55
- data/lib/temporalio/internal/worker/workflow_worker.rb +19 -6
- data/lib/temporalio/priority.rb +59 -0
- data/lib/temporalio/runtime/metric_buffer.rb +94 -0
- data/lib/temporalio/runtime.rb +48 -10
- data/lib/temporalio/search_attributes.rb +13 -0
- data/lib/temporalio/testing/activity_environment.rb +49 -10
- data/lib/temporalio/testing/workflow_environment.rb +29 -6
- data/lib/temporalio/version.rb +1 -1
- data/lib/temporalio/versioning_override.rb +56 -0
- data/lib/temporalio/worker/deployment_options.rb +45 -0
- data/lib/temporalio/worker/illegal_workflow_call_validator.rb +64 -0
- data/lib/temporalio/worker/interceptor.rb +16 -1
- data/lib/temporalio/worker/poller_behavior.rb +61 -0
- data/lib/temporalio/worker/thread_pool.rb +6 -6
- data/lib/temporalio/worker/workflow_executor/thread_pool.rb +9 -3
- data/lib/temporalio/worker/workflow_replayer.rb +19 -13
- data/lib/temporalio/worker.rb +97 -27
- data/lib/temporalio/worker_deployment_version.rb +67 -0
- data/lib/temporalio/workflow/child_workflow_handle.rb +10 -2
- data/lib/temporalio/workflow/definition.rb +217 -35
- data/lib/temporalio/workflow/external_workflow_handle.rb +3 -1
- data/lib/temporalio/workflow/future.rb +2 -2
- data/lib/temporalio/workflow/info.rb +26 -1
- data/lib/temporalio/workflow.rb +113 -15
- data/lib/temporalio.rb +1 -0
- data/temporalio.gemspec +3 -1
- metadata +33 -4
@@ -22,6 +22,7 @@ module Temporalio
|
|
22
22
|
ExecuteInput = Data.define(
|
23
23
|
:proc,
|
24
24
|
:args,
|
25
|
+
:result_hint,
|
25
26
|
:headers
|
26
27
|
)
|
27
28
|
|
@@ -59,7 +60,8 @@ module Temporalio
|
|
59
60
|
|
60
61
|
# Input for {Outbound.heartbeat}.
|
61
62
|
HeartbeatInput = Data.define(
|
62
|
-
:details
|
63
|
+
:details,
|
64
|
+
:detail_hints
|
63
65
|
)
|
64
66
|
|
65
67
|
# Outbound interceptor for intercepting outbound activity calls. This should be extended by users needing to
|
@@ -206,6 +208,7 @@ module Temporalio
|
|
206
208
|
:activity,
|
207
209
|
:args,
|
208
210
|
:task_queue,
|
211
|
+
:summary,
|
209
212
|
:schedule_to_close_timeout,
|
210
213
|
:schedule_to_start_timeout,
|
211
214
|
:start_to_close_timeout,
|
@@ -215,6 +218,9 @@ module Temporalio
|
|
215
218
|
:cancellation_type,
|
216
219
|
:activity_id,
|
217
220
|
:disable_eager_execution,
|
221
|
+
:priority,
|
222
|
+
:arg_hints,
|
223
|
+
:result_hint,
|
218
224
|
:headers
|
219
225
|
)
|
220
226
|
|
@@ -230,6 +236,8 @@ module Temporalio
|
|
230
236
|
:cancellation,
|
231
237
|
:cancellation_type,
|
232
238
|
:activity_id,
|
239
|
+
:arg_hints,
|
240
|
+
:result_hint,
|
233
241
|
:headers
|
234
242
|
)
|
235
243
|
|
@@ -244,6 +252,7 @@ module Temporalio
|
|
244
252
|
:signal,
|
245
253
|
:args,
|
246
254
|
:cancellation,
|
255
|
+
:arg_hints,
|
247
256
|
:headers
|
248
257
|
)
|
249
258
|
|
@@ -254,6 +263,7 @@ module Temporalio
|
|
254
263
|
:signal,
|
255
264
|
:args,
|
256
265
|
:cancellation,
|
266
|
+
:arg_hints,
|
257
267
|
:headers
|
258
268
|
)
|
259
269
|
|
@@ -270,6 +280,8 @@ module Temporalio
|
|
270
280
|
:args,
|
271
281
|
:id,
|
272
282
|
:task_queue,
|
283
|
+
:static_summary,
|
284
|
+
:static_details,
|
273
285
|
:cancellation,
|
274
286
|
:cancellation_type,
|
275
287
|
:parent_close_policy,
|
@@ -281,6 +293,9 @@ module Temporalio
|
|
281
293
|
:cron_schedule,
|
282
294
|
:memo,
|
283
295
|
:search_attributes,
|
296
|
+
:priority,
|
297
|
+
:arg_hints,
|
298
|
+
:result_hint,
|
284
299
|
:headers
|
285
300
|
)
|
286
301
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Temporalio
|
4
|
+
class Worker
|
5
|
+
# Base class for poller behaviors that control how polling scales.
|
6
|
+
class PollerBehavior
|
7
|
+
# @!visibility private
|
8
|
+
def _to_bridge_options
|
9
|
+
raise NotImplementedError, 'Subclasses must implement this method'
|
10
|
+
end
|
11
|
+
|
12
|
+
# A poller behavior that attempts to poll as long as a slot is available, up to the
|
13
|
+
# provided maximum. Cannot be less than two for workflow tasks, or one for other tasks.
|
14
|
+
class SimpleMaximum < PollerBehavior
|
15
|
+
# @return [Integer] Maximum number of concurrent poll requests.
|
16
|
+
attr_reader :maximum
|
17
|
+
|
18
|
+
# @param maximum [Integer] Maximum number of concurrent poll requests.
|
19
|
+
def initialize(maximum)
|
20
|
+
super()
|
21
|
+
@maximum = maximum
|
22
|
+
end
|
23
|
+
|
24
|
+
# @!visibility private
|
25
|
+
def _to_bridge_options
|
26
|
+
Internal::Bridge::Worker::PollerBehaviorSimpleMaximum.new(simple_maximum: @maximum)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# A poller behavior that automatically scales the number of pollers based on feedback
|
31
|
+
# from the server. A slot must be available before beginning polling.
|
32
|
+
class Autoscaling < PollerBehavior
|
33
|
+
# @return [Integer] Minimum number of poll calls (assuming slots are available).
|
34
|
+
attr_reader :minimum
|
35
|
+
# @return [Integer] Maximum number of poll calls that will ever be open at once.
|
36
|
+
attr_reader :maximum
|
37
|
+
# @return [Integer] Number of polls attempted initially before scaling kicks in.
|
38
|
+
attr_reader :initial
|
39
|
+
|
40
|
+
# @param minimum [Integer] Minimum number of poll calls (assuming slots are available).
|
41
|
+
# @param maximum [Integer] Maximum number of poll calls that will ever be open at once.
|
42
|
+
# @param initial [Integer] Number of polls attempted initially before scaling kicks in.
|
43
|
+
def initialize(minimum: 1, maximum: 100, initial: 5)
|
44
|
+
super()
|
45
|
+
@minimum = minimum
|
46
|
+
@maximum = maximum
|
47
|
+
@initial = initial
|
48
|
+
end
|
49
|
+
|
50
|
+
# @!visibility private
|
51
|
+
def _to_bridge_options
|
52
|
+
Internal::Bridge::Worker::PollerBehaviorAutoscaling.new(
|
53
|
+
minimum: @minimum,
|
54
|
+
maximum: @maximum,
|
55
|
+
initial: @initial
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Much of this logic taken from
|
4
|
-
# https://github.com/ruby-concurrency/concurrent-ruby/blob/044020f44b36930b863b930f3ee8fa1e9f750469/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb,
|
5
|
-
# see MIT license at
|
6
|
-
# https://github.com/ruby-concurrency/concurrent-ruby/blob/044020f44b36930b863b930f3ee8fa1e9f750469/LICENSE.txt
|
7
|
-
|
8
3
|
module Temporalio
|
9
4
|
class Worker
|
10
5
|
# Implementation of a thread pool. This implementation is a stripped down form of Concurrent Ruby's
|
11
6
|
# `CachedThreadPool`.
|
12
7
|
class ThreadPool
|
8
|
+
# Much of this logic taken from
|
9
|
+
# https://github.com/ruby-concurrency/concurrent-ruby/blob/044020f44b36930b863b930f3ee8fa1e9f750469/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb,
|
10
|
+
# see MIT license at
|
11
|
+
# https://github.com/ruby-concurrency/concurrent-ruby/blob/044020f44b36930b863b930f3ee8fa1e9f750469/LICENSE.txt
|
12
|
+
|
13
13
|
# @return [ThreadPool] Default/shared thread pool instance with unlimited max threads.
|
14
14
|
def self.default
|
15
15
|
@default ||= new
|
@@ -125,7 +125,7 @@ module Temporalio
|
|
125
125
|
|
126
126
|
private
|
127
127
|
|
128
|
-
def locked_assign_worker(&block)
|
128
|
+
def locked_assign_worker(&block) # rubocop:disable Naming/PredicateMethod
|
129
129
|
# keep growing if the pool is not at the minimum yet
|
130
130
|
worker, = @ready.pop || locked_add_busy_worker
|
131
131
|
if worker
|
@@ -186,8 +186,12 @@ module Temporalio
|
|
186
186
|
raise 'Missing initialize job in initial activation' unless init_job
|
187
187
|
|
188
188
|
# Obtain definition
|
189
|
-
definition = worker_state.workflow_definitions[init_job.workflow_type]
|
190
|
-
|
189
|
+
definition = worker_state.workflow_definitions[init_job.workflow_type]
|
190
|
+
# If not present and not reserved, try dynamic
|
191
|
+
if !definition && !Internal::ProtoUtils.reserved_name?(init_job.workflow_type)
|
192
|
+
definition = worker_state.workflow_definitions[nil]
|
193
|
+
end
|
194
|
+
|
191
195
|
unless definition
|
192
196
|
raise Error::ApplicationError.new(
|
193
197
|
"Workflow type #{init_job.workflow_type} is not registered on this worker, available workflows: " +
|
@@ -209,7 +213,9 @@ module Temporalio
|
|
209
213
|
interceptors: worker_state.workflow_interceptors,
|
210
214
|
disable_eager_activity_execution: worker_state.disable_eager_activity_execution,
|
211
215
|
illegal_calls: worker_state.illegal_calls,
|
212
|
-
workflow_failure_exception_types: worker_state.workflow_failure_exception_types
|
216
|
+
workflow_failure_exception_types: worker_state.workflow_failure_exception_types,
|
217
|
+
unsafe_workflow_io_enabled: worker_state.unsafe_workflow_io_enabled,
|
218
|
+
assert_valid_local_activity: worker_state.assert_valid_local_activity
|
213
219
|
)
|
214
220
|
)
|
215
221
|
end
|
@@ -7,6 +7,7 @@ require 'temporalio/internal/bridge/worker'
|
|
7
7
|
require 'temporalio/internal/worker/multi_runner'
|
8
8
|
require 'temporalio/internal/worker/workflow_worker'
|
9
9
|
require 'temporalio/worker/interceptor'
|
10
|
+
require 'temporalio/worker/poller_behavior'
|
10
11
|
require 'temporalio/worker/thread_pool'
|
11
12
|
require 'temporalio/worker/tuner'
|
12
13
|
require 'temporalio/worker/workflow_executor'
|
@@ -24,12 +25,12 @@ module Temporalio
|
|
24
25
|
:data_converter,
|
25
26
|
:workflow_executor,
|
26
27
|
:interceptors,
|
27
|
-
:build_id,
|
28
28
|
:identity,
|
29
29
|
:logger,
|
30
30
|
:illegal_workflow_calls,
|
31
31
|
:workflow_failure_exception_types,
|
32
32
|
:workflow_payload_codec_thread_pool,
|
33
|
+
:unsafe_workflow_io_enabled,
|
33
34
|
:debug_mode,
|
34
35
|
:runtime
|
35
36
|
)
|
@@ -50,9 +51,6 @@ module Temporalio
|
|
50
51
|
# @param workflow_executor [WorkflowExecutor] Workflow executor that workflow tasks run within. This must be a
|
51
52
|
# {WorkflowExecutor::ThreadPool} currently.
|
52
53
|
# @param interceptors [Array<Interceptor::Workflow>] Workflow interceptors.
|
53
|
-
# @param build_id [String] Unique identifier for the current runtime. This is best set as a unique value
|
54
|
-
# representing all code and should change only when code does. This can be something like a git commit hash. If
|
55
|
-
# unset, default is hash of known Ruby code.
|
56
54
|
# @param identity [String, nil] Override the identity for this replater.
|
57
55
|
# @param logger [Logger] Logger to use. Defaults to stdout with warn level. Callers setting this logger are
|
58
56
|
# responsible for closing it.
|
@@ -69,6 +67,9 @@ module Temporalio
|
|
69
67
|
# @param workflow_payload_codec_thread_pool [ThreadPool, nil] Thread pool to run payload codec encode/decode
|
70
68
|
# within. This is required if a payload codec exists and the worker is not fiber based. Codecs can potentially
|
71
69
|
# block execution which is why they need to be run in the background.
|
70
|
+
# @param unsafe_workflow_io_enabled [Boolean] If false, the default, workflow code that invokes io_wait on the
|
71
|
+
# fiber scheduler will fail. Instead of setting this to true, users are encouraged to use
|
72
|
+
# {Workflow::Unsafe.io_enabled} with a block for narrower enabling of IO.
|
72
73
|
# @param debug_mode [Boolean] If true, deadlock detection is disabled. Deadlock detection will fail workflow tasks
|
73
74
|
# if they block the thread for too long. This defaults to true if the `TEMPORAL_DEBUG` environment variable is
|
74
75
|
# `true` or `1`.
|
@@ -83,12 +84,12 @@ module Temporalio
|
|
83
84
|
data_converter: Converters::DataConverter.default,
|
84
85
|
workflow_executor: WorkflowExecutor::ThreadPool.default,
|
85
86
|
interceptors: [],
|
86
|
-
build_id: Worker.default_build_id,
|
87
87
|
identity: nil,
|
88
88
|
logger: Logger.new($stdout, level: Logger::WARN),
|
89
89
|
illegal_workflow_calls: Worker.default_illegal_workflow_calls,
|
90
90
|
workflow_failure_exception_types: [],
|
91
91
|
workflow_payload_codec_thread_pool: nil,
|
92
|
+
unsafe_workflow_io_enabled: false,
|
92
93
|
debug_mode: %w[true 1].include?(ENV['TEMPORAL_DEBUG'].to_s.downcase),
|
93
94
|
runtime: Runtime.default,
|
94
95
|
&
|
@@ -100,17 +101,19 @@ module Temporalio
|
|
100
101
|
data_converter:,
|
101
102
|
workflow_executor:,
|
102
103
|
interceptors:,
|
103
|
-
build_id:,
|
104
104
|
identity:,
|
105
105
|
logger:,
|
106
106
|
illegal_workflow_calls:,
|
107
107
|
workflow_failure_exception_types:,
|
108
108
|
workflow_payload_codec_thread_pool:,
|
109
|
+
unsafe_workflow_io_enabled:,
|
109
110
|
debug_mode:,
|
110
111
|
runtime:
|
111
112
|
).freeze
|
112
113
|
# Preload definitions and other settings
|
113
|
-
@workflow_definitions = Internal::Worker::WorkflowWorker.workflow_definitions(
|
114
|
+
@workflow_definitions = Internal::Worker::WorkflowWorker.workflow_definitions(
|
115
|
+
workflows, should_enforce_versioning_behavior: false
|
116
|
+
)
|
114
117
|
@nondeterminism_as_workflow_fail, @nondeterminism_as_workflow_fail_for_types =
|
115
118
|
Internal::Worker::WorkflowWorker.bridge_workflow_failure_exception_type_options(
|
116
119
|
workflow_failure_exception_types:, workflow_definitions: @workflow_definitions
|
@@ -201,12 +204,13 @@ module Temporalio
|
|
201
204
|
tuner: Tuner.create_fixed(
|
202
205
|
workflow_slots: 2, activity_slots: 1, local_activity_slots: 1
|
203
206
|
)._to_bridge_options,
|
204
|
-
build_id: options.build_id,
|
205
207
|
identity_override: options.identity,
|
206
208
|
max_cached_workflows: 2,
|
207
|
-
|
209
|
+
workflow_task_poller_behavior:
|
210
|
+
Temporalio::Worker::PollerBehavior::SimpleMaximum.new(2)._to_bridge_options,
|
208
211
|
nonsticky_to_sticky_poll_ratio: 1.0,
|
209
|
-
|
212
|
+
activity_task_poller_behavior:
|
213
|
+
Temporalio::Worker::PollerBehavior::SimpleMaximum.new(1)._to_bridge_options,
|
210
214
|
no_remote_activities: true,
|
211
215
|
sticky_queue_schedule_to_start_timeout: 1.0,
|
212
216
|
max_heartbeat_throttle_interval: 1.0,
|
@@ -214,9 +218,9 @@ module Temporalio
|
|
214
218
|
max_worker_activities_per_second: nil,
|
215
219
|
max_task_queue_activities_per_second: nil,
|
216
220
|
graceful_shutdown_period: 0.0,
|
217
|
-
use_worker_versioning: false,
|
218
221
|
nondeterminism_as_workflow_fail:,
|
219
|
-
nondeterminism_as_workflow_fail_for_types
|
222
|
+
nondeterminism_as_workflow_fail_for_types:,
|
223
|
+
deployment_options: Worker.default_deployment_options._to_bridge_options
|
220
224
|
)
|
221
225
|
)
|
222
226
|
|
@@ -237,8 +241,10 @@ module Temporalio
|
|
237
241
|
illegal_workflow_calls: options.illegal_workflow_calls,
|
238
242
|
workflow_failure_exception_types: options.workflow_failure_exception_types,
|
239
243
|
workflow_payload_codec_thread_pool: options.workflow_payload_codec_thread_pool,
|
244
|
+
unsafe_workflow_io_enabled: options.unsafe_workflow_io_enabled,
|
240
245
|
debug_mode: options.debug_mode,
|
241
|
-
on_eviction: proc { |_, remove_job| @last_workflow_remove_job = remove_job } # steep:ignore
|
246
|
+
on_eviction: proc { |_, remove_job| @last_workflow_remove_job = remove_job }, # steep:ignore
|
247
|
+
assert_valid_local_activity: ->(_) {}
|
242
248
|
)
|
243
249
|
|
244
250
|
# Create the runner
|
data/lib/temporalio/worker.rb
CHANGED
@@ -6,12 +6,16 @@ require 'temporalio/client'
|
|
6
6
|
require 'temporalio/error'
|
7
7
|
require 'temporalio/internal/bridge'
|
8
8
|
require 'temporalio/internal/bridge/worker'
|
9
|
+
require 'temporalio/internal/proto_utils'
|
9
10
|
require 'temporalio/internal/worker/activity_worker'
|
10
11
|
require 'temporalio/internal/worker/multi_runner'
|
11
12
|
require 'temporalio/internal/worker/workflow_instance'
|
12
13
|
require 'temporalio/internal/worker/workflow_worker'
|
13
14
|
require 'temporalio/worker/activity_executor'
|
15
|
+
require 'temporalio/worker/deployment_options'
|
16
|
+
require 'temporalio/worker/illegal_workflow_call_validator'
|
14
17
|
require 'temporalio/worker/interceptor'
|
18
|
+
require 'temporalio/worker/poller_behavior'
|
15
19
|
require 'temporalio/worker/thread_pool'
|
16
20
|
require 'temporalio/worker/tuner'
|
17
21
|
require 'temporalio/worker/workflow_executor'
|
@@ -32,7 +36,6 @@ module Temporalio
|
|
32
36
|
:activity_executors,
|
33
37
|
:workflow_executor,
|
34
38
|
:interceptors,
|
35
|
-
:build_id,
|
36
39
|
:identity,
|
37
40
|
:logger,
|
38
41
|
:max_cached_workflows,
|
@@ -46,15 +49,20 @@ module Temporalio
|
|
46
49
|
:max_activities_per_second,
|
47
50
|
:max_task_queue_activities_per_second,
|
48
51
|
:graceful_shutdown_period,
|
49
|
-
:use_worker_versioning,
|
50
52
|
:disable_eager_activity_execution,
|
51
53
|
:illegal_workflow_calls,
|
52
54
|
:workflow_failure_exception_types,
|
53
55
|
:workflow_payload_codec_thread_pool,
|
56
|
+
:unsafe_workflow_io_enabled,
|
57
|
+
:deployment_options,
|
58
|
+
:workflow_task_poller_behavior,
|
59
|
+
:activity_task_poller_behavior,
|
54
60
|
:debug_mode
|
55
61
|
)
|
56
62
|
|
57
63
|
# Options as returned from {options} for `**to_h` splat use in {initialize}. See {initialize} for details.
|
64
|
+
#
|
65
|
+
# Note, the `client` within can be replaced via client setter.
|
58
66
|
class Options; end # rubocop:disable Lint/EmptyClass
|
59
67
|
|
60
68
|
# @return [String] Memoized default build ID. This default value is built as a checksum of all of the loaded Ruby
|
@@ -85,6 +93,14 @@ module Temporalio
|
|
85
93
|
build_id
|
86
94
|
end
|
87
95
|
|
96
|
+
# @return [DeploymentOptions] Default deployment options, which does not use worker versioning
|
97
|
+
# or a deployment name, and sets the build id to the one from {self.default_build_id}.
|
98
|
+
def self.default_deployment_options
|
99
|
+
@default_deployment_options ||= DeploymentOptions.new(
|
100
|
+
version: WorkerDeploymentVersion.new(deployment_name: '', build_id: Worker.default_build_id)
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
88
104
|
# Run all workers until cancellation or optional block completes. When the cancellation or block is complete, the
|
89
105
|
# workers are shut down. This will return the block result if everything successful or raise an error if not. See
|
90
106
|
# {run} for details on how worker shutdown works.
|
@@ -228,8 +244,9 @@ module Temporalio
|
|
228
244
|
end
|
229
245
|
end
|
230
246
|
|
231
|
-
# @return [Hash<String, [:all, Array<Symbol
|
232
|
-
# `illegal_workflow_calls` worker option. See the documentation of that
|
247
|
+
# @return [Hash<String, [:all, Array<Symbol, IllegalWorkflowCallValidator>, IllegalWorkflowCallValidator]>] Default,
|
248
|
+
# immutable set illegal calls used for the `illegal_workflow_calls` worker option. See the documentation of that
|
249
|
+
# option for more details.
|
233
250
|
def self.default_illegal_workflow_calls
|
234
251
|
@default_illegal_workflow_calls ||= begin
|
235
252
|
hash = {
|
@@ -268,7 +285,7 @@ module Temporalio
|
|
268
285
|
'Thread' => %i[abort_on_exception= exit fork handle_interrupt ignore_deadlock= kill new pass
|
269
286
|
pending_interrupt? report_on_exception= start stop initialize join name= priority= raise run
|
270
287
|
terminate thread_variable_set wakeup],
|
271
|
-
'Time' =>
|
288
|
+
'Time' => IllegalWorkflowCallValidator.default_time_validators
|
272
289
|
} #: Hash[String, :all | Array[Symbol]]
|
273
290
|
hash.each_value(&:freeze)
|
274
291
|
hash.freeze
|
@@ -292,9 +309,6 @@ module Temporalio
|
|
292
309
|
# @param interceptors [Array<Interceptor::Activity, Interceptor::Workflow>] Interceptors specific to this worker.
|
293
310
|
# Note, interceptors set on the client that include the {Interceptor::Activity} or {Interceptor::Workflow} module
|
294
311
|
# are automatically included here, so no need to specify them again.
|
295
|
-
# @param build_id [String] Unique identifier for the current runtime. This is best set as a unique value
|
296
|
-
# representing all code and should change only when code does. This can be something like a git commit hash. If
|
297
|
-
# unset, default is hash of known Ruby code.
|
298
312
|
# @param identity [String, nil] Override the identity for this worker. If unset, client identity is used.
|
299
313
|
# @param logger [Logger] Logger to override client logger with. Default is the client logger.
|
300
314
|
# @param max_cached_workflows [Integer] Number of workflows held in cache for use by sticky task queue. If set to 0,
|
@@ -323,19 +337,19 @@ module Temporalio
|
|
323
337
|
# multiple workers on the same queue have different values set, they will thrash with the last poller winning.
|
324
338
|
# @param graceful_shutdown_period [Float] Amount of time after shutdown is called that activities are given to
|
325
339
|
# complete before their tasks are canceled.
|
326
|
-
# @param use_worker_versioning [Boolean] If true, the `build_id` argument must be specified, and this worker opts
|
327
|
-
# into the worker versioning feature. This ensures it only receives workflow tasks for workflows which it claims
|
328
|
-
# to be compatible with. For more information, see https://docs.temporal.io/workers#worker-versioning.
|
329
340
|
# @param disable_eager_activity_execution [Boolean] If true, disables eager activity execution. Eager activity
|
330
341
|
# execution is an optimization on some servers that sends activities back to the same worker as the calling
|
331
342
|
# workflow if they can run there. This should be set to true for `max_task_queue_activities_per_second` to work
|
332
343
|
# and in a future version of this API may be implied as such (i.e. this setting will be ignored if that setting is
|
333
344
|
# set).
|
334
|
-
# @param illegal_workflow_calls [Hash<String,
|
335
|
-
#
|
336
|
-
#
|
337
|
-
#
|
338
|
-
#
|
345
|
+
# @param illegal_workflow_calls [Hash<String,
|
346
|
+
# [:all, Array<Symbol, IllegalWorkflowCallValidator>, IllegalWorkflowCallValidator]>] Set of illegal workflow
|
347
|
+
# calls that are considered unsafe/non-deterministic and will raise if seen. The key of the hash is the fully
|
348
|
+
# qualified string class name (no leading `::`). The value can be `:all` which means any use of the class is
|
349
|
+
# illegal. The value can be an array of symbols/validators for methods on the class that cannot be used. The
|
350
|
+
# methods refer to either instance or class methods, there is no way to differentiate at this time. Symbol method
|
351
|
+
# names are the normal way to say the method cannot be used, validators are only for advanced situations. Finally,
|
352
|
+
# for advanced situations, the hash value can be a class-level validator that is not tied to a specific method.
|
339
353
|
# @param workflow_failure_exception_types [Array<Class<Exception>>] Workflow failure exception types. This is the
|
340
354
|
# set of exception types that, if a workflow-thrown exception extends, will cause the workflow/update to fail
|
341
355
|
# instead of suspending the workflow via task failure. These are applied in addition to the
|
@@ -344,6 +358,15 @@ module Temporalio
|
|
344
358
|
# @param workflow_payload_codec_thread_pool [ThreadPool, nil] Thread pool to run payload codec encode/decode within.
|
345
359
|
# This is required if a payload codec exists and the worker is not fiber based. Codecs can potentially block
|
346
360
|
# execution which is why they need to be run in the background.
|
361
|
+
# @param unsafe_workflow_io_enabled [Boolean] If false, the default, workflow code that invokes io_wait on the fiber
|
362
|
+
# scheduler will fail. Instead of setting this to true, users are encouraged to use {Workflow::Unsafe.io_enabled}
|
363
|
+
# with a block for narrower enabling of IO.
|
364
|
+
# @param deployment_options [DeploymentOptions, nil] Deployment options for the worker.
|
365
|
+
# WARNING: This is an experimental feature and may change in the future.
|
366
|
+
# @param workflow_task_poller_behavior [PollerBehavior] Specify the behavior of workflow task
|
367
|
+
# polling. Defaults to a 5-poller maximum.
|
368
|
+
# @param activity_task_poller_behavior [PollerBehavior] Specify the behavior of activity task
|
369
|
+
# polling. Defaults to a 5-poller maximum.
|
347
370
|
# @param debug_mode [Boolean] If true, deadlock detection is disabled. Deadlock detection will fail workflow tasks
|
348
371
|
# if they block the thread for too long. This defaults to true if the `TEMPORAL_DEBUG` environment variable is
|
349
372
|
# `true` or `1`.
|
@@ -356,7 +379,6 @@ module Temporalio
|
|
356
379
|
activity_executors: ActivityExecutor.defaults,
|
357
380
|
workflow_executor: WorkflowExecutor::ThreadPool.default,
|
358
381
|
interceptors: [],
|
359
|
-
build_id: Worker.default_build_id,
|
360
382
|
identity: nil,
|
361
383
|
logger: client.options.logger,
|
362
384
|
max_cached_workflows: 1000,
|
@@ -370,15 +392,20 @@ module Temporalio
|
|
370
392
|
max_activities_per_second: nil,
|
371
393
|
max_task_queue_activities_per_second: nil,
|
372
394
|
graceful_shutdown_period: 0,
|
373
|
-
use_worker_versioning: false,
|
374
395
|
disable_eager_activity_execution: false,
|
375
396
|
illegal_workflow_calls: Worker.default_illegal_workflow_calls,
|
376
397
|
workflow_failure_exception_types: [],
|
377
398
|
workflow_payload_codec_thread_pool: nil,
|
399
|
+
unsafe_workflow_io_enabled: false,
|
400
|
+
deployment_options: Worker.default_deployment_options,
|
401
|
+
workflow_task_poller_behavior: PollerBehavior::SimpleMaximum.new(max_concurrent_workflow_task_polls),
|
402
|
+
activity_task_poller_behavior: PollerBehavior::SimpleMaximum.new(max_concurrent_activity_task_polls),
|
378
403
|
debug_mode: %w[true 1].include?(ENV['TEMPORAL_DEBUG'].to_s.downcase)
|
379
404
|
)
|
380
405
|
raise ArgumentError, 'Must have at least one activity or workflow' if activities.empty? && workflows.empty?
|
381
406
|
|
407
|
+
Internal::ProtoUtils.assert_non_reserved_name(task_queue)
|
408
|
+
|
382
409
|
@options = Options.new(
|
383
410
|
client:,
|
384
411
|
task_queue:,
|
@@ -388,7 +415,6 @@ module Temporalio
|
|
388
415
|
activity_executors:,
|
389
416
|
workflow_executor:,
|
390
417
|
interceptors:,
|
391
|
-
build_id:,
|
392
418
|
identity:,
|
393
419
|
logger:,
|
394
420
|
max_cached_workflows:,
|
@@ -402,16 +428,25 @@ module Temporalio
|
|
402
428
|
max_activities_per_second:,
|
403
429
|
max_task_queue_activities_per_second:,
|
404
430
|
graceful_shutdown_period:,
|
405
|
-
use_worker_versioning:,
|
406
431
|
disable_eager_activity_execution:,
|
407
432
|
illegal_workflow_calls:,
|
408
433
|
workflow_failure_exception_types:,
|
409
434
|
workflow_payload_codec_thread_pool:,
|
435
|
+
unsafe_workflow_io_enabled:,
|
436
|
+
deployment_options:,
|
437
|
+
workflow_task_poller_behavior:,
|
438
|
+
activity_task_poller_behavior:,
|
410
439
|
debug_mode:
|
411
440
|
).freeze
|
412
441
|
|
442
|
+
should_enforce_versioning_behavior =
|
443
|
+
deployment_options.use_worker_versioning &&
|
444
|
+
deployment_options.default_versioning_behavior == VersioningBehavior::UNSPECIFIED
|
413
445
|
# Preload workflow definitions and some workflow settings for the bridge
|
414
|
-
workflow_definitions = Internal::Worker::WorkflowWorker.workflow_definitions(
|
446
|
+
workflow_definitions = Internal::Worker::WorkflowWorker.workflow_definitions(
|
447
|
+
workflows,
|
448
|
+
should_enforce_versioning_behavior: should_enforce_versioning_behavior
|
449
|
+
)
|
415
450
|
nondeterminism_as_workflow_fail, nondeterminism_as_workflow_fail_for_types =
|
416
451
|
Internal::Worker::WorkflowWorker.bridge_workflow_failure_exception_type_options(
|
417
452
|
workflow_failure_exception_types:, workflow_definitions:
|
@@ -426,12 +461,11 @@ module Temporalio
|
|
426
461
|
namespace: client.namespace,
|
427
462
|
task_queue:,
|
428
463
|
tuner: tuner._to_bridge_options,
|
429
|
-
build_id:,
|
430
464
|
identity_override: identity,
|
431
465
|
max_cached_workflows:,
|
432
|
-
|
466
|
+
workflow_task_poller_behavior: workflow_task_poller_behavior._to_bridge_options,
|
433
467
|
nonsticky_to_sticky_poll_ratio:,
|
434
|
-
|
468
|
+
activity_task_poller_behavior: activity_task_poller_behavior._to_bridge_options,
|
435
469
|
# For shutdown to work properly, we must disable remote activities
|
436
470
|
# ourselves if there are no activities
|
437
471
|
no_remote_activities: no_remote_activities || activities.empty?,
|
@@ -441,9 +475,9 @@ module Temporalio
|
|
441
475
|
max_worker_activities_per_second: max_activities_per_second,
|
442
476
|
max_task_queue_activities_per_second:,
|
443
477
|
graceful_shutdown_period:,
|
444
|
-
use_worker_versioning:,
|
445
478
|
nondeterminism_as_workflow_fail:,
|
446
|
-
nondeterminism_as_workflow_fail_for_types
|
479
|
+
nondeterminism_as_workflow_fail_for_types:,
|
480
|
+
deployment_options: deployment_options._to_bridge_options
|
447
481
|
)
|
448
482
|
)
|
449
483
|
|
@@ -478,12 +512,17 @@ module Temporalio
|
|
478
512
|
illegal_workflow_calls:,
|
479
513
|
workflow_failure_exception_types:,
|
480
514
|
workflow_payload_codec_thread_pool:,
|
481
|
-
|
515
|
+
unsafe_workflow_io_enabled:,
|
516
|
+
debug_mode:,
|
517
|
+
assert_valid_local_activity: ->(activity) { _assert_valid_local_activity(activity) }
|
482
518
|
)
|
483
519
|
end
|
484
520
|
|
485
521
|
# Validate worker
|
486
522
|
@bridge_worker.validate
|
523
|
+
|
524
|
+
# Mutex needed for accessing and replacing a client
|
525
|
+
@client_mutex = Mutex.new
|
487
526
|
end
|
488
527
|
|
489
528
|
# @return [String] Task queue set on the worker options.
|
@@ -491,6 +530,25 @@ module Temporalio
|
|
491
530
|
@options.task_queue
|
492
531
|
end
|
493
532
|
|
533
|
+
# @return [Client] Client for this worker. This is the same as {Options.client} in {options}, but surrounded by a
|
534
|
+
# mutex to be safe for client replacement in {client=}.
|
535
|
+
def client
|
536
|
+
@client_mutex.synchronize { @options.client }
|
537
|
+
end
|
538
|
+
|
539
|
+
# Replace the worker's client. When this is called, the client is replaced on the internal worker which means any
|
540
|
+
# new calls will be made on the new client (but existing calls will still complete on the previous one). This is
|
541
|
+
# commonly used for providing a new client with updated authentication credentials.
|
542
|
+
#
|
543
|
+
# @param new_client [Client] New client to use for new calls.
|
544
|
+
def client=(new_client)
|
545
|
+
@client_mutex.synchronize do
|
546
|
+
@bridge_worker.replace_client(new_client.connection._core_client)
|
547
|
+
@options = @options.with(client: new_client)
|
548
|
+
new_client
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
494
552
|
# Run this worker until cancellation or optional block completes. When the cancellation or block is complete, the
|
495
553
|
# worker is shut down. This will return the block result if everything successful or raise an error if not.
|
496
554
|
#
|
@@ -565,5 +623,17 @@ module Temporalio
|
|
565
623
|
@workflow_worker&.on_shutdown_complete
|
566
624
|
@workflow_worker = nil
|
567
625
|
end
|
626
|
+
|
627
|
+
# @!visibility private
|
628
|
+
def _assert_valid_local_activity(activity)
|
629
|
+
unless @activity_worker.nil?
|
630
|
+
@activity_worker.assert_valid_activity(activity)
|
631
|
+
return
|
632
|
+
end
|
633
|
+
|
634
|
+
raise ArgumentError,
|
635
|
+
"Activity #{activity} " \
|
636
|
+
'is not registered on this worker, no available activities.'
|
637
|
+
end
|
568
638
|
end
|
569
639
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporalio/internal/bridge/worker'
|
4
|
+
|
5
|
+
module Temporalio
|
6
|
+
WorkerDeploymentVersion = Data.define(
|
7
|
+
:deployment_name,
|
8
|
+
:build_id
|
9
|
+
)
|
10
|
+
|
11
|
+
# Represents the version of a specific worker deployment.
|
12
|
+
#
|
13
|
+
# WARNING: Experimental API.
|
14
|
+
class WorkerDeploymentVersion
|
15
|
+
# Parse a version from a canonical string, which must be in the format
|
16
|
+
# `<deployment_name>.<build_id>`. Deployment name must not have a `.` in it.
|
17
|
+
#
|
18
|
+
# @param canonical [String] The canonical string representation of the version.
|
19
|
+
# @return [WorkerDeploymentVersion] The parsed version.
|
20
|
+
def self.from_canonical_string(canonical)
|
21
|
+
parts = canonical.split('.', 2)
|
22
|
+
if parts.length != 2
|
23
|
+
raise ArgumentError,
|
24
|
+
"Cannot parse version string: #{canonical}, must be in format <deployment_name>.<build_id>"
|
25
|
+
end
|
26
|
+
new(deployment_name: parts[0], build_id: parts[1])
|
27
|
+
end
|
28
|
+
|
29
|
+
# @!visibility private
|
30
|
+
def self._from_bridge(bridge)
|
31
|
+
return nil if bridge.nil?
|
32
|
+
|
33
|
+
new(deployment_name: bridge.deployment_name, build_id: bridge.build_id)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Create WorkerDeploymentVersion.
|
37
|
+
#
|
38
|
+
# @param deployment_name [String] The name of the deployment.
|
39
|
+
# @param build_id [String] The build identifier specific to this worker build.
|
40
|
+
def initialize(deployment_name:, build_id:) # rubocop:disable Lint/UselessMethodDefinition
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the canonical string representation of the version.
|
45
|
+
#
|
46
|
+
# @return [String]
|
47
|
+
def to_canonical_string
|
48
|
+
"#{deployment_name}.#{build_id}"
|
49
|
+
end
|
50
|
+
|
51
|
+
# @!visibility private
|
52
|
+
def _to_bridge_options
|
53
|
+
Internal::Bridge::Worker::WorkerDeploymentVersion.new(
|
54
|
+
deployment_name: deployment_name,
|
55
|
+
build_id: build_id
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
# @!visibility private
|
60
|
+
def _to_proto
|
61
|
+
Api::Deployment::V1::WorkerDeploymentVersion.new(
|
62
|
+
deployment_name: deployment_name,
|
63
|
+
build_id: build_id
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|