temporalio 0.4.0 → 0.5.0
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/Cargo.lock +679 -437
- data/Cargo.toml +5 -5
- data/README.md +98 -34
- data/ext/Cargo.toml +3 -3
- data/lib/temporalio/activity/cancellation_details.rb +58 -0
- data/lib/temporalio/activity/context.rb +10 -1
- data/lib/temporalio/activity/definition.rb +41 -3
- data/lib/temporalio/activity/info.rb +25 -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 +4 -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 +3 -2
- data/lib/temporalio/api/deployment/v1/message.rb +3 -2
- data/lib/temporalio/api/enums/v1/batch_operation.rb +1 -1
- 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 +3 -2
- 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 +1 -1
- data/lib/temporalio/api/enums/v1/query.rb +1 -1
- data/lib/temporalio/api/enums/v1/reset.rb +1 -1
- 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 +2 -2
- data/lib/temporalio/api/errordetails/v1/message.rb +1 -1
- data/lib/temporalio/api/export/v1/message.rb +1 -1
- data/lib/temporalio/api/failure/v1/message.rb +3 -2
- data/lib/temporalio/api/filter/v1/message.rb +1 -1
- data/lib/temporalio/api/history/v1/message.rb +4 -2
- data/lib/temporalio/api/namespace/v1/message.rb +1 -1
- data/lib/temporalio/api/nexus/v1/message.rb +2 -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 +87 -0
- data/lib/temporalio/api/protocol/v1/message.rb +1 -1
- data/lib/temporalio/api/query/v1/message.rb +1 -1
- 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 +2 -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 +14 -2
- data/lib/temporalio/api/workflowservice/v1/request_response.rb +19 -2
- data/lib/temporalio/api/workflowservice/v1/service.rb +2 -2
- 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 +105 -0
- data/lib/temporalio/client/interceptor.rb +25 -7
- data/lib/temporalio/client/schedule.rb +10 -2
- data/lib/temporalio/client/with_start_workflow_operation.rb +9 -1
- data/lib/temporalio/client/workflow_handle.rb +50 -10
- data/lib/temporalio/client/workflow_update_handle.rb +9 -3
- data/lib/temporalio/client.rb +110 -6
- data/lib/temporalio/common_enums.rb +14 -0
- data/lib/temporalio/contrib/open_telemetry.rb +13 -9
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- data/lib/temporalio/internal/bridge/worker.rb +28 -4
- data/lib/temporalio/internal/bridge.rb +1 -1
- data/lib/temporalio/internal/client/implementation.rb +60 -52
- data/lib/temporalio/internal/proto_utils.rb +4 -4
- data/lib/temporalio/internal/worker/activity_worker.rb +93 -20
- data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +8 -6
- data/lib/temporalio/internal/worker/workflow_instance/context.rb +65 -24
- data/lib/temporalio/internal/worker/workflow_instance/details.rb +5 -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 +28 -14
- data/lib/temporalio/internal/worker/workflow_instance.rb +58 -23
- data/lib/temporalio/internal/worker/workflow_worker.rb +16 -6
- data/lib/temporalio/priority.rb +59 -0
- data/lib/temporalio/testing/activity_environment.rb +17 -2
- data/lib/temporalio/testing/workflow_environment.rb +3 -3
- 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 +13 -1
- data/lib/temporalio/worker/poller_behavior.rb +61 -0
- data/lib/temporalio/worker/thread_pool.rb +1 -1
- data/lib/temporalio/worker/workflow_executor/thread_pool.rb +2 -1
- data/lib/temporalio/worker/workflow_replayer.rb +12 -13
- data/lib/temporalio/worker.rb +63 -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 +183 -33
- data/lib/temporalio/workflow/external_workflow_handle.rb +3 -1
- data/lib/temporalio/workflow/info.rb +4 -1
- data/lib/temporalio/workflow.rb +61 -9
- data/lib/temporalio.rb +1 -0
- data/temporalio.gemspec +1 -0
- metadata +12 -3
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporalio/common_enums'
|
4
|
+
require 'temporalio/worker_deployment_version'
|
5
|
+
|
6
|
+
module Temporalio
|
7
|
+
class Worker
|
8
|
+
DeploymentOptions = Data.define(
|
9
|
+
:version,
|
10
|
+
:use_worker_versioning,
|
11
|
+
:default_versioning_behavior
|
12
|
+
)
|
13
|
+
|
14
|
+
# Options for configuring the Worker Versioning feature.
|
15
|
+
#
|
16
|
+
# WARNING: Deployment-based versioning is experimental and APIs may change.
|
17
|
+
#
|
18
|
+
# @!attribute version
|
19
|
+
# @return [WorkerDeploymentVersion] The worker deployment version.
|
20
|
+
# @!attribute use_worker_versioning
|
21
|
+
# @return [Boolean] Whether worker versioning is enabled.
|
22
|
+
# @!attribute default_versioning_behavior
|
23
|
+
# @return [VersioningBehavior] The default versioning behavior.
|
24
|
+
class DeploymentOptions
|
25
|
+
def initialize(
|
26
|
+
version:,
|
27
|
+
use_worker_versioning: false,
|
28
|
+
default_versioning_behavior: VersioningBehavior::UNSPECIFIED
|
29
|
+
)
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
# @!visibility private
|
34
|
+
def _to_bridge_options
|
35
|
+
Internal::Bridge::Worker::DeploymentOptions.new(
|
36
|
+
version: Internal::Bridge::Worker::WorkerDeploymentVersion.new(
|
37
|
+
deployment_name: version.deployment_name, build_id: version.build_id
|
38
|
+
),
|
39
|
+
use_worker_versioning: use_worker_versioning,
|
40
|
+
default_versioning_behavior: default_versioning_behavior
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Temporalio
|
4
|
+
class Worker
|
5
|
+
# Custom validator for validating illegal workflow calls.
|
6
|
+
class IllegalWorkflowCallValidator
|
7
|
+
CallInfo = Data.define(
|
8
|
+
:class_name,
|
9
|
+
:method_name,
|
10
|
+
:trace_point
|
11
|
+
)
|
12
|
+
|
13
|
+
# Call info passed to the validation block for each validation.
|
14
|
+
#
|
15
|
+
# @!attribute class_name
|
16
|
+
# @return [String] Class name the method is on.
|
17
|
+
# @!attribute method_name
|
18
|
+
# @return [String] Method name being called.
|
19
|
+
# @!attribute trace_point
|
20
|
+
# @return [TracePoint] TracePoint instance for the call.
|
21
|
+
class CallInfo; end # rubocop:disable Lint/EmptyClass
|
22
|
+
|
23
|
+
# @return [Array<IllegalWorkflowCallValidator>] Set of advanced validators for Time calls.
|
24
|
+
def self.default_time_validators
|
25
|
+
@default_time_validators ||= [
|
26
|
+
# Do not consider initialize as invalid if year is present and not "true"
|
27
|
+
IllegalWorkflowCallValidator.new(method_name: :initialize) do |info|
|
28
|
+
year_val = info.trace_point.binding&.local_variable_get(:year)
|
29
|
+
raise 'can only use if passing string or explicit time info' unless year_val && year_val != true
|
30
|
+
end,
|
31
|
+
IllegalWorkflowCallValidator.new(method_name: :now) do
|
32
|
+
# When the xmlschema (aliased as iso8601) call is made, zone_offset is called which has a default parameter
|
33
|
+
# of Time.now.year. We want to prevent failing in that specific case. It is expensive to access the caller
|
34
|
+
# stack, but this is only done in the rare case they are calling this safely.
|
35
|
+
next if caller_locations&.any? { |loc| loc.label == 'zone_offset' || loc.label == 'Time.zone_offset' }
|
36
|
+
|
37
|
+
raise 'Invalid Time.now call'
|
38
|
+
end
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [String, nil] Method name if this validator is specific to a method.
|
43
|
+
attr_reader :method_name
|
44
|
+
|
45
|
+
# @return [Proc] Block provided in constructor to invoke. See constructor for more details.
|
46
|
+
attr_reader :block
|
47
|
+
|
48
|
+
# Create a call validator.
|
49
|
+
#
|
50
|
+
# @param method_name [String, nil] Method name to check. This must be provided if the validator is in an illegal
|
51
|
+
# call array, this cannot be provided if it is a top-level class validator.
|
52
|
+
# @yield Required block that is called each time validation is needed. If the call raises, the exception message
|
53
|
+
# is used as the reason why the call is considered invalid. Return value is ignored.
|
54
|
+
# @yieldparam info [CallInfo] Information about the current call.
|
55
|
+
def initialize(method_name: nil, &block)
|
56
|
+
raise 'Block required' unless block_given?
|
57
|
+
raise TypeError, 'Method name must be Symbol' unless method_name.nil? || method_name.is_a?(Symbol)
|
58
|
+
|
59
|
+
@method_name = method_name
|
60
|
+
@block = block
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -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
|
@@ -216,6 +218,9 @@ module Temporalio
|
|
216
218
|
:cancellation_type,
|
217
219
|
:activity_id,
|
218
220
|
:disable_eager_execution,
|
221
|
+
:priority,
|
222
|
+
:arg_hints,
|
223
|
+
:result_hint,
|
219
224
|
:headers
|
220
225
|
)
|
221
226
|
|
@@ -231,6 +236,8 @@ module Temporalio
|
|
231
236
|
:cancellation,
|
232
237
|
:cancellation_type,
|
233
238
|
:activity_id,
|
239
|
+
:arg_hints,
|
240
|
+
:result_hint,
|
234
241
|
:headers
|
235
242
|
)
|
236
243
|
|
@@ -245,6 +252,7 @@ module Temporalio
|
|
245
252
|
:signal,
|
246
253
|
:args,
|
247
254
|
:cancellation,
|
255
|
+
:arg_hints,
|
248
256
|
:headers
|
249
257
|
)
|
250
258
|
|
@@ -255,6 +263,7 @@ module Temporalio
|
|
255
263
|
:signal,
|
256
264
|
:args,
|
257
265
|
:cancellation,
|
266
|
+
:arg_hints,
|
258
267
|
:headers
|
259
268
|
)
|
260
269
|
|
@@ -284,6 +293,9 @@ module Temporalio
|
|
284
293
|
:cron_schedule,
|
285
294
|
:memo,
|
286
295
|
:search_attributes,
|
296
|
+
:priority,
|
297
|
+
:arg_hints,
|
298
|
+
:result_hint,
|
287
299
|
:headers
|
288
300
|
)
|
289
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
|
@@ -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
|
@@ -214,7 +214,8 @@ module Temporalio
|
|
214
214
|
disable_eager_activity_execution: worker_state.disable_eager_activity_execution,
|
215
215
|
illegal_calls: worker_state.illegal_calls,
|
216
216
|
workflow_failure_exception_types: worker_state.workflow_failure_exception_types,
|
217
|
-
unsafe_workflow_io_enabled: worker_state.unsafe_workflow_io_enabled
|
217
|
+
unsafe_workflow_io_enabled: worker_state.unsafe_workflow_io_enabled,
|
218
|
+
assert_valid_local_activity: worker_state.assert_valid_local_activity
|
218
219
|
)
|
219
220
|
)
|
220
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,7 +25,6 @@ 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,
|
@@ -51,9 +51,6 @@ module Temporalio
|
|
51
51
|
# @param workflow_executor [WorkflowExecutor] Workflow executor that workflow tasks run within. This must be a
|
52
52
|
# {WorkflowExecutor::ThreadPool} currently.
|
53
53
|
# @param interceptors [Array<Interceptor::Workflow>] Workflow interceptors.
|
54
|
-
# @param build_id [String] Unique identifier for the current runtime. This is best set as a unique value
|
55
|
-
# representing all code and should change only when code does. This can be something like a git commit hash. If
|
56
|
-
# unset, default is hash of known Ruby code.
|
57
54
|
# @param identity [String, nil] Override the identity for this replater.
|
58
55
|
# @param logger [Logger] Logger to use. Defaults to stdout with warn level. Callers setting this logger are
|
59
56
|
# responsible for closing it.
|
@@ -87,7 +84,6 @@ module Temporalio
|
|
87
84
|
data_converter: Converters::DataConverter.default,
|
88
85
|
workflow_executor: WorkflowExecutor::ThreadPool.default,
|
89
86
|
interceptors: [],
|
90
|
-
build_id: Worker.default_build_id,
|
91
87
|
identity: nil,
|
92
88
|
logger: Logger.new($stdout, level: Logger::WARN),
|
93
89
|
illegal_workflow_calls: Worker.default_illegal_workflow_calls,
|
@@ -105,7 +101,6 @@ module Temporalio
|
|
105
101
|
data_converter:,
|
106
102
|
workflow_executor:,
|
107
103
|
interceptors:,
|
108
|
-
build_id:,
|
109
104
|
identity:,
|
110
105
|
logger:,
|
111
106
|
illegal_workflow_calls:,
|
@@ -116,7 +111,9 @@ module Temporalio
|
|
116
111
|
runtime:
|
117
112
|
).freeze
|
118
113
|
# Preload definitions and other settings
|
119
|
-
@workflow_definitions = Internal::Worker::WorkflowWorker.workflow_definitions(
|
114
|
+
@workflow_definitions = Internal::Worker::WorkflowWorker.workflow_definitions(
|
115
|
+
workflows, should_enforce_versioning_behavior: false
|
116
|
+
)
|
120
117
|
@nondeterminism_as_workflow_fail, @nondeterminism_as_workflow_fail_for_types =
|
121
118
|
Internal::Worker::WorkflowWorker.bridge_workflow_failure_exception_type_options(
|
122
119
|
workflow_failure_exception_types:, workflow_definitions: @workflow_definitions
|
@@ -207,12 +204,13 @@ module Temporalio
|
|
207
204
|
tuner: Tuner.create_fixed(
|
208
205
|
workflow_slots: 2, activity_slots: 1, local_activity_slots: 1
|
209
206
|
)._to_bridge_options,
|
210
|
-
build_id: options.build_id,
|
211
207
|
identity_override: options.identity,
|
212
208
|
max_cached_workflows: 2,
|
213
|
-
|
209
|
+
workflow_task_poller_behavior:
|
210
|
+
Temporalio::Worker::PollerBehavior::SimpleMaximum.new(2)._to_bridge_options,
|
214
211
|
nonsticky_to_sticky_poll_ratio: 1.0,
|
215
|
-
|
212
|
+
activity_task_poller_behavior:
|
213
|
+
Temporalio::Worker::PollerBehavior::SimpleMaximum.new(1)._to_bridge_options,
|
216
214
|
no_remote_activities: true,
|
217
215
|
sticky_queue_schedule_to_start_timeout: 1.0,
|
218
216
|
max_heartbeat_throttle_interval: 1.0,
|
@@ -220,9 +218,9 @@ module Temporalio
|
|
220
218
|
max_worker_activities_per_second: nil,
|
221
219
|
max_task_queue_activities_per_second: nil,
|
222
220
|
graceful_shutdown_period: 0.0,
|
223
|
-
use_worker_versioning: false,
|
224
221
|
nondeterminism_as_workflow_fail:,
|
225
|
-
nondeterminism_as_workflow_fail_for_types
|
222
|
+
nondeterminism_as_workflow_fail_for_types:,
|
223
|
+
deployment_options: Worker.default_deployment_options._to_bridge_options
|
226
224
|
)
|
227
225
|
)
|
228
226
|
|
@@ -245,7 +243,8 @@ module Temporalio
|
|
245
243
|
workflow_payload_codec_thread_pool: options.workflow_payload_codec_thread_pool,
|
246
244
|
unsafe_workflow_io_enabled: options.unsafe_workflow_io_enabled,
|
247
245
|
debug_mode: options.debug_mode,
|
248
|
-
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: ->(_) {}
|
249
248
|
)
|
250
249
|
|
251
250
|
# Create the runner
|
data/lib/temporalio/worker.rb
CHANGED
@@ -12,7 +12,10 @@ require 'temporalio/internal/worker/multi_runner'
|
|
12
12
|
require 'temporalio/internal/worker/workflow_instance'
|
13
13
|
require 'temporalio/internal/worker/workflow_worker'
|
14
14
|
require 'temporalio/worker/activity_executor'
|
15
|
+
require 'temporalio/worker/deployment_options'
|
16
|
+
require 'temporalio/worker/illegal_workflow_call_validator'
|
15
17
|
require 'temporalio/worker/interceptor'
|
18
|
+
require 'temporalio/worker/poller_behavior'
|
16
19
|
require 'temporalio/worker/thread_pool'
|
17
20
|
require 'temporalio/worker/tuner'
|
18
21
|
require 'temporalio/worker/workflow_executor'
|
@@ -33,7 +36,6 @@ module Temporalio
|
|
33
36
|
:activity_executors,
|
34
37
|
:workflow_executor,
|
35
38
|
:interceptors,
|
36
|
-
:build_id,
|
37
39
|
:identity,
|
38
40
|
:logger,
|
39
41
|
:max_cached_workflows,
|
@@ -47,12 +49,14 @@ module Temporalio
|
|
47
49
|
:max_activities_per_second,
|
48
50
|
:max_task_queue_activities_per_second,
|
49
51
|
:graceful_shutdown_period,
|
50
|
-
:use_worker_versioning,
|
51
52
|
:disable_eager_activity_execution,
|
52
53
|
:illegal_workflow_calls,
|
53
54
|
:workflow_failure_exception_types,
|
54
55
|
:workflow_payload_codec_thread_pool,
|
55
56
|
:unsafe_workflow_io_enabled,
|
57
|
+
:deployment_options,
|
58
|
+
:workflow_task_poller_behavior,
|
59
|
+
:activity_task_poller_behavior,
|
56
60
|
:debug_mode
|
57
61
|
)
|
58
62
|
|
@@ -89,6 +93,14 @@ module Temporalio
|
|
89
93
|
build_id
|
90
94
|
end
|
91
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
|
+
|
92
104
|
# Run all workers until cancellation or optional block completes. When the cancellation or block is complete, the
|
93
105
|
# workers are shut down. This will return the block result if everything successful or raise an error if not. See
|
94
106
|
# {run} for details on how worker shutdown works.
|
@@ -232,8 +244,9 @@ module Temporalio
|
|
232
244
|
end
|
233
245
|
end
|
234
246
|
|
235
|
-
# @return [Hash<String, [:all, Array<Symbol
|
236
|
-
# `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.
|
237
250
|
def self.default_illegal_workflow_calls
|
238
251
|
@default_illegal_workflow_calls ||= begin
|
239
252
|
hash = {
|
@@ -272,7 +285,7 @@ module Temporalio
|
|
272
285
|
'Thread' => %i[abort_on_exception= exit fork handle_interrupt ignore_deadlock= kill new pass
|
273
286
|
pending_interrupt? report_on_exception= start stop initialize join name= priority= raise run
|
274
287
|
terminate thread_variable_set wakeup],
|
275
|
-
'Time' =>
|
288
|
+
'Time' => IllegalWorkflowCallValidator.default_time_validators
|
276
289
|
} #: Hash[String, :all | Array[Symbol]]
|
277
290
|
hash.each_value(&:freeze)
|
278
291
|
hash.freeze
|
@@ -296,9 +309,6 @@ module Temporalio
|
|
296
309
|
# @param interceptors [Array<Interceptor::Activity, Interceptor::Workflow>] Interceptors specific to this worker.
|
297
310
|
# Note, interceptors set on the client that include the {Interceptor::Activity} or {Interceptor::Workflow} module
|
298
311
|
# are automatically included here, so no need to specify them again.
|
299
|
-
# @param build_id [String] Unique identifier for the current runtime. This is best set as a unique value
|
300
|
-
# representing all code and should change only when code does. This can be something like a git commit hash. If
|
301
|
-
# unset, default is hash of known Ruby code.
|
302
312
|
# @param identity [String, nil] Override the identity for this worker. If unset, client identity is used.
|
303
313
|
# @param logger [Logger] Logger to override client logger with. Default is the client logger.
|
304
314
|
# @param max_cached_workflows [Integer] Number of workflows held in cache for use by sticky task queue. If set to 0,
|
@@ -327,19 +337,19 @@ module Temporalio
|
|
327
337
|
# multiple workers on the same queue have different values set, they will thrash with the last poller winning.
|
328
338
|
# @param graceful_shutdown_period [Float] Amount of time after shutdown is called that activities are given to
|
329
339
|
# complete before their tasks are canceled.
|
330
|
-
# @param use_worker_versioning [Boolean] If true, the `build_id` argument must be specified, and this worker opts
|
331
|
-
# into the worker versioning feature. This ensures it only receives workflow tasks for workflows which it claims
|
332
|
-
# to be compatible with. For more information, see https://docs.temporal.io/workers#worker-versioning.
|
333
340
|
# @param disable_eager_activity_execution [Boolean] If true, disables eager activity execution. Eager activity
|
334
341
|
# execution is an optimization on some servers that sends activities back to the same worker as the calling
|
335
342
|
# workflow if they can run there. This should be set to true for `max_task_queue_activities_per_second` to work
|
336
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
|
337
344
|
# set).
|
338
|
-
# @param illegal_workflow_calls [Hash<String,
|
339
|
-
#
|
340
|
-
#
|
341
|
-
#
|
342
|
-
#
|
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.
|
343
353
|
# @param workflow_failure_exception_types [Array<Class<Exception>>] Workflow failure exception types. This is the
|
344
354
|
# set of exception types that, if a workflow-thrown exception extends, will cause the workflow/update to fail
|
345
355
|
# instead of suspending the workflow via task failure. These are applied in addition to the
|
@@ -351,6 +361,12 @@ module Temporalio
|
|
351
361
|
# @param unsafe_workflow_io_enabled [Boolean] If false, the default, workflow code that invokes io_wait on the fiber
|
352
362
|
# scheduler will fail. Instead of setting this to true, users are encouraged to use {Workflow::Unsafe.io_enabled}
|
353
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.
|
354
370
|
# @param debug_mode [Boolean] If true, deadlock detection is disabled. Deadlock detection will fail workflow tasks
|
355
371
|
# if they block the thread for too long. This defaults to true if the `TEMPORAL_DEBUG` environment variable is
|
356
372
|
# `true` or `1`.
|
@@ -363,7 +379,6 @@ module Temporalio
|
|
363
379
|
activity_executors: ActivityExecutor.defaults,
|
364
380
|
workflow_executor: WorkflowExecutor::ThreadPool.default,
|
365
381
|
interceptors: [],
|
366
|
-
build_id: Worker.default_build_id,
|
367
382
|
identity: nil,
|
368
383
|
logger: client.options.logger,
|
369
384
|
max_cached_workflows: 1000,
|
@@ -377,12 +392,14 @@ module Temporalio
|
|
377
392
|
max_activities_per_second: nil,
|
378
393
|
max_task_queue_activities_per_second: nil,
|
379
394
|
graceful_shutdown_period: 0,
|
380
|
-
use_worker_versioning: false,
|
381
395
|
disable_eager_activity_execution: false,
|
382
396
|
illegal_workflow_calls: Worker.default_illegal_workflow_calls,
|
383
397
|
workflow_failure_exception_types: [],
|
384
398
|
workflow_payload_codec_thread_pool: nil,
|
385
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),
|
386
403
|
debug_mode: %w[true 1].include?(ENV['TEMPORAL_DEBUG'].to_s.downcase)
|
387
404
|
)
|
388
405
|
raise ArgumentError, 'Must have at least one activity or workflow' if activities.empty? && workflows.empty?
|
@@ -398,7 +415,6 @@ module Temporalio
|
|
398
415
|
activity_executors:,
|
399
416
|
workflow_executor:,
|
400
417
|
interceptors:,
|
401
|
-
build_id:,
|
402
418
|
identity:,
|
403
419
|
logger:,
|
404
420
|
max_cached_workflows:,
|
@@ -412,17 +428,25 @@ module Temporalio
|
|
412
428
|
max_activities_per_second:,
|
413
429
|
max_task_queue_activities_per_second:,
|
414
430
|
graceful_shutdown_period:,
|
415
|
-
use_worker_versioning:,
|
416
431
|
disable_eager_activity_execution:,
|
417
432
|
illegal_workflow_calls:,
|
418
433
|
workflow_failure_exception_types:,
|
419
434
|
workflow_payload_codec_thread_pool:,
|
420
435
|
unsafe_workflow_io_enabled:,
|
436
|
+
deployment_options:,
|
437
|
+
workflow_task_poller_behavior:,
|
438
|
+
activity_task_poller_behavior:,
|
421
439
|
debug_mode:
|
422
440
|
).freeze
|
423
441
|
|
442
|
+
should_enforce_versioning_behavior =
|
443
|
+
deployment_options.use_worker_versioning &&
|
444
|
+
deployment_options.default_versioning_behavior == VersioningBehavior::UNSPECIFIED
|
424
445
|
# Preload workflow definitions and some workflow settings for the bridge
|
425
|
-
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
|
+
)
|
426
450
|
nondeterminism_as_workflow_fail, nondeterminism_as_workflow_fail_for_types =
|
427
451
|
Internal::Worker::WorkflowWorker.bridge_workflow_failure_exception_type_options(
|
428
452
|
workflow_failure_exception_types:, workflow_definitions:
|
@@ -437,12 +461,11 @@ module Temporalio
|
|
437
461
|
namespace: client.namespace,
|
438
462
|
task_queue:,
|
439
463
|
tuner: tuner._to_bridge_options,
|
440
|
-
build_id:,
|
441
464
|
identity_override: identity,
|
442
465
|
max_cached_workflows:,
|
443
|
-
|
466
|
+
workflow_task_poller_behavior: workflow_task_poller_behavior._to_bridge_options,
|
444
467
|
nonsticky_to_sticky_poll_ratio:,
|
445
|
-
|
468
|
+
activity_task_poller_behavior: activity_task_poller_behavior._to_bridge_options,
|
446
469
|
# For shutdown to work properly, we must disable remote activities
|
447
470
|
# ourselves if there are no activities
|
448
471
|
no_remote_activities: no_remote_activities || activities.empty?,
|
@@ -452,9 +475,9 @@ module Temporalio
|
|
452
475
|
max_worker_activities_per_second: max_activities_per_second,
|
453
476
|
max_task_queue_activities_per_second:,
|
454
477
|
graceful_shutdown_period:,
|
455
|
-
use_worker_versioning:,
|
456
478
|
nondeterminism_as_workflow_fail:,
|
457
|
-
nondeterminism_as_workflow_fail_for_types
|
479
|
+
nondeterminism_as_workflow_fail_for_types:,
|
480
|
+
deployment_options: deployment_options._to_bridge_options
|
458
481
|
)
|
459
482
|
)
|
460
483
|
|
@@ -490,7 +513,8 @@ module Temporalio
|
|
490
513
|
workflow_failure_exception_types:,
|
491
514
|
workflow_payload_codec_thread_pool:,
|
492
515
|
unsafe_workflow_io_enabled:,
|
493
|
-
debug_mode
|
516
|
+
debug_mode:,
|
517
|
+
assert_valid_local_activity: ->(activity) { _assert_valid_local_activity(activity) }
|
494
518
|
)
|
495
519
|
end
|
496
520
|
|
@@ -599,5 +623,17 @@ module Temporalio
|
|
599
623
|
@workflow_worker&.on_shutdown_complete
|
600
624
|
@workflow_worker = nil
|
601
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
|
602
638
|
end
|
603
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
|
@@ -21,12 +21,18 @@ module Temporalio
|
|
21
21
|
raise NotImplementedError
|
22
22
|
end
|
23
23
|
|
24
|
+
# @return [Object, nil] Hint for the result if any.
|
25
|
+
def result_hint
|
26
|
+
raise NotImplementedError
|
27
|
+
end
|
28
|
+
|
24
29
|
# Wait for the result.
|
25
30
|
#
|
31
|
+
# @param result_hint [Object, nil] Override the result hint, or if nil uses the one on the handle.
|
26
32
|
# @return [Object] Result of the child workflow.
|
27
33
|
#
|
28
34
|
# @raise [Error::ChildWorkflowError] Workflow failed with +cause+ as the cause.
|
29
|
-
def result
|
35
|
+
def result(result_hint: nil)
|
30
36
|
raise NotImplementedError
|
31
37
|
end
|
32
38
|
|
@@ -35,7 +41,9 @@ module Temporalio
|
|
35
41
|
# @param signal [Workflow::Definition::Signal, Symbol, String] Signal definition or name.
|
36
42
|
# @param args [Array<Object>] Signal args.
|
37
43
|
# @param cancellation [Cancellation] Cancellation for canceling the signalling.
|
38
|
-
|
44
|
+
# @param arg_hints [Array<Object>, nil] Overrides converter hints for arguments if any. If unset/nil and the
|
45
|
+
# signal definition has arg hints, those are used by default.
|
46
|
+
def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil)
|
39
47
|
raise NotImplementedError
|
40
48
|
end
|
41
49
|
end
|