temporalio 0.4.0-x86_64-darwin → 0.5.0-x86_64-darwin
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/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/3.2/temporalio_bridge.bundle +0 -0
- data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.bundle +0 -0
- data/lib/temporalio/internal/bridge/3.4/temporalio_bridge.bundle +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 +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 +11 -2
@@ -24,6 +24,7 @@ require 'temporalio/internal/worker/workflow_instance/scheduler'
|
|
24
24
|
require 'temporalio/retry_policy'
|
25
25
|
require 'temporalio/scoped_logger'
|
26
26
|
require 'temporalio/worker/interceptor'
|
27
|
+
require 'temporalio/worker_deployment_version'
|
27
28
|
require 'temporalio/workflow/info'
|
28
29
|
require 'temporalio/workflow/update_info'
|
29
30
|
require 'timeout'
|
@@ -54,9 +55,9 @@ module Temporalio
|
|
54
55
|
attr_reader :context, :logger, :info, :scheduler, :disable_eager_activity_execution, :pending_activities,
|
55
56
|
:pending_timers, :pending_child_workflow_starts, :pending_child_workflows,
|
56
57
|
:pending_external_signals, :pending_external_cancels, :in_progress_handlers, :payload_converter,
|
57
|
-
:failure_converter, :cancellation, :continue_as_new_suggested, :
|
58
|
-
:current_history_size, :replaying, :random,
|
59
|
-
:context_frozen
|
58
|
+
:failure_converter, :cancellation, :continue_as_new_suggested, :current_deployment_version,
|
59
|
+
:current_history_length, :current_history_size, :replaying, :random,
|
60
|
+
:signal_handlers, :query_handlers, :update_handlers, :context_frozen, :assert_valid_local_activity
|
60
61
|
attr_accessor :io_enabled, :current_details
|
61
62
|
|
62
63
|
def initialize(details)
|
@@ -90,7 +91,7 @@ module Temporalio
|
|
90
91
|
@current_history_length = 0
|
91
92
|
@current_history_size = 0
|
92
93
|
@replaying = false
|
93
|
-
@
|
94
|
+
@workflow_failure_exception_types = details.workflow_failure_exception_types
|
94
95
|
@signal_handlers = HandlerHash.new(
|
95
96
|
details.definition.signals,
|
96
97
|
Workflow::Definition::Signal
|
@@ -107,6 +108,12 @@ module Temporalio
|
|
107
108
|
end
|
108
109
|
@query_handlers = HandlerHash.new(details.definition.queries, Workflow::Definition::Query)
|
109
110
|
@update_handlers = HandlerHash.new(details.definition.updates, Workflow::Definition::Update)
|
111
|
+
@definition_options = Workflow::DefinitionOptions.new(
|
112
|
+
failure_exception_types: details.definition.failure_exception_types,
|
113
|
+
versioning_behavior: details.definition.versioning_behavior
|
114
|
+
)
|
115
|
+
|
116
|
+
@assert_valid_local_activity = details.assert_valid_local_activity
|
110
117
|
|
111
118
|
# Create all things needed from initial job
|
112
119
|
@init_job = details.initial_activation.jobs.find { |j| !j.initialize_workflow.nil? }&.initialize_workflow
|
@@ -133,6 +140,7 @@ module Temporalio
|
|
133
140
|
workflow_id: @init_job.parent_workflow_info.workflow_id
|
134
141
|
)
|
135
142
|
end,
|
143
|
+
priority: Priority._from_proto(@init_job.priority),
|
136
144
|
retry_policy: (RetryPolicy._from_proto(@init_job.retry_policy) if @init_job.retry_policy),
|
137
145
|
root: if @init_job.root_workflow
|
138
146
|
Workflow::Info::RootInfo.new(
|
@@ -142,7 +150,7 @@ module Temporalio
|
|
142
150
|
end,
|
143
151
|
run_id: details.initial_activation.run_id,
|
144
152
|
run_timeout: ProtoUtils.duration_to_seconds(@init_job.workflow_run_timeout),
|
145
|
-
start_time: ProtoUtils.timestamp_to_time(
|
153
|
+
start_time: ProtoUtils.timestamp_to_time(@init_job.start_time) || raise,
|
146
154
|
task_queue: details.task_queue,
|
147
155
|
task_timeout: ProtoUtils.duration_to_seconds(@init_job.workflow_task_timeout) || raise,
|
148
156
|
workflow_id: @init_job.workflow_id,
|
@@ -238,6 +246,9 @@ module Temporalio
|
|
238
246
|
@commands = []
|
239
247
|
@current_activation_error = nil
|
240
248
|
@continue_as_new_suggested = activation.continue_as_new_suggested
|
249
|
+
@current_deployment_version = WorkerDeploymentVersion._from_bridge(
|
250
|
+
activation.deployment_version_for_current_task
|
251
|
+
)
|
241
252
|
@current_history_length = activation.history_length
|
242
253
|
@current_history_size = activation.history_size_bytes
|
243
254
|
@replaying = activation.is_replaying
|
@@ -287,7 +298,9 @@ module Temporalio
|
|
287
298
|
else
|
288
299
|
Bridge::Api::WorkflowCompletion::WorkflowActivationCompletion.new(
|
289
300
|
run_id: activation.run_id,
|
290
|
-
successful: Bridge::Api::WorkflowCompletion::Success.new(
|
301
|
+
successful: Bridge::Api::WorkflowCompletion::Success.new(
|
302
|
+
commands: @commands, versioning_behavior: @definition_options.versioning_behavior
|
303
|
+
)
|
291
304
|
)
|
292
305
|
end
|
293
306
|
ensure
|
@@ -299,7 +312,8 @@ module Temporalio
|
|
299
312
|
# Convert workflow arguments
|
300
313
|
@workflow_arguments = convert_args(payload_array: @init_job.arguments,
|
301
314
|
method_name: :execute,
|
302
|
-
raw_args: @definition.raw_args
|
315
|
+
raw_args: @definition.raw_args,
|
316
|
+
arg_hints: @definition.arg_hints)
|
303
317
|
|
304
318
|
# Initialize interceptors
|
305
319
|
@inbound = @interceptors.reverse_each.reduce(InboundImplementation.new(self)) do |acc, int|
|
@@ -308,11 +322,24 @@ module Temporalio
|
|
308
322
|
@inbound.init(OutboundImplementation.new(self))
|
309
323
|
|
310
324
|
# Create the user instance
|
311
|
-
if @definition.init
|
312
|
-
|
313
|
-
|
314
|
-
|
325
|
+
instance = if @definition.init
|
326
|
+
@definition.workflow_class.new(*@workflow_arguments)
|
327
|
+
else
|
328
|
+
@definition.workflow_class.new
|
329
|
+
end
|
330
|
+
|
331
|
+
# Run Dynamic config getter
|
332
|
+
if @definition.dynamic_options_method
|
333
|
+
dynamic_options = instance.send(@definition.dynamic_options_method)
|
334
|
+
if dynamic_options&.versioning_behavior
|
335
|
+
@definition_options.versioning_behavior = dynamic_options.versioning_behavior
|
336
|
+
end
|
337
|
+
if dynamic_options&.failure_exception_types
|
338
|
+
@definition_options.failure_exception_types = dynamic_options.failure_exception_types
|
339
|
+
end
|
315
340
|
end
|
341
|
+
|
342
|
+
instance
|
316
343
|
end
|
317
344
|
|
318
345
|
def apply(job)
|
@@ -394,6 +421,7 @@ module Temporalio
|
|
394
421
|
end
|
395
422
|
|
396
423
|
def apply_query(job)
|
424
|
+
result_hint = nil
|
397
425
|
schedule do
|
398
426
|
# If it's a built-in, run it without interceptors, otherwise do normal behavior
|
399
427
|
result = if job.query_type == '__stack_trace'
|
@@ -411,6 +439,7 @@ module Temporalio
|
|
411
439
|
raise "Query handler for #{job.query_type} expected but not found, " \
|
412
440
|
"known queries: [#{query_handlers.keys.compact.sort.join(', ')}]"
|
413
441
|
end
|
442
|
+
result_hint = defn.result_hint
|
414
443
|
|
415
444
|
with_context_frozen do
|
416
445
|
@inbound.handle_query(
|
@@ -434,7 +463,7 @@ module Temporalio
|
|
434
463
|
respond_to_query: Bridge::Api::WorkflowCommands::QueryResult.new(
|
435
464
|
query_id: job.query_id,
|
436
465
|
succeeded: Bridge::Api::WorkflowCommands::QuerySuccess.new(
|
437
|
-
response: @payload_converter.to_payload(result)
|
466
|
+
response: @payload_converter.to_payload(result, hint: result_hint)
|
438
467
|
)
|
439
468
|
)
|
440
469
|
)
|
@@ -523,7 +552,7 @@ module Temporalio
|
|
523
552
|
Bridge::Api::WorkflowCommands::WorkflowCommand.new(
|
524
553
|
update_response: Bridge::Api::WorkflowCommands::UpdateResponse.new(
|
525
554
|
protocol_instance_id: job.protocol_instance_id,
|
526
|
-
completed: @payload_converter.to_payload(result)
|
555
|
+
completed: @payload_converter.to_payload(result, hint: defn.result_hint)
|
527
556
|
)
|
528
557
|
)
|
529
558
|
)
|
@@ -553,7 +582,7 @@ module Temporalio
|
|
553
582
|
add_command(
|
554
583
|
Bridge::Api::WorkflowCommands::WorkflowCommand.new(
|
555
584
|
complete_workflow_execution: Bridge::Api::WorkflowCommands::CompleteWorkflowExecution.new(
|
556
|
-
result: @payload_converter.to_payload(result)
|
585
|
+
result: @payload_converter.to_payload(result, hint: @definition.result_hint)
|
557
586
|
)
|
558
587
|
)
|
559
588
|
)
|
@@ -581,14 +610,19 @@ module Temporalio
|
|
581
610
|
def on_top_level_exception(err)
|
582
611
|
if err.is_a?(Workflow::ContinueAsNewError)
|
583
612
|
@logger.debug('Workflow requested continue as new')
|
613
|
+
workflow_type, defn_arg_hints, =
|
614
|
+
if err.workflow
|
615
|
+
Workflow::Definition._workflow_type_and_hints_from_workflow_parameter(err.workflow)
|
616
|
+
else
|
617
|
+
[nil, @definition.arg_hints, nil]
|
618
|
+
end
|
584
619
|
add_command(
|
585
620
|
Bridge::Api::WorkflowCommands::WorkflowCommand.new(
|
586
621
|
continue_as_new_workflow_execution: Bridge::Api::WorkflowCommands::ContinueAsNewWorkflowExecution.new(
|
587
|
-
workflow_type
|
588
|
-
Workflow::Definition._workflow_type_from_workflow_parameter(err.workflow)
|
589
|
-
end,
|
622
|
+
workflow_type:,
|
590
623
|
task_queue: err.task_queue,
|
591
|
-
arguments: ProtoUtils.convert_to_payload_array(payload_converter, err.args
|
624
|
+
arguments: ProtoUtils.convert_to_payload_array(payload_converter, err.args,
|
625
|
+
hints: err.arg_hints || defn_arg_hints),
|
592
626
|
workflow_run_timeout: ProtoUtils.seconds_to_duration(err.run_timeout),
|
593
627
|
workflow_task_timeout: ProtoUtils.seconds_to_duration(err.task_timeout),
|
594
628
|
memo: ProtoUtils.memo_to_proto_hash(err.memo, payload_converter),
|
@@ -626,9 +660,9 @@ module Temporalio
|
|
626
660
|
end
|
627
661
|
|
628
662
|
def failure_exception?(err)
|
629
|
-
err.is_a?(Error::Failure) || err.is_a?(Timeout::Error) ||
|
630
|
-
err.is_a?(cls)
|
631
|
-
|
663
|
+
err.is_a?(Error::Failure) || err.is_a?(Timeout::Error) ||
|
664
|
+
@workflow_failure_exception_types&.any? { |cls| err.is_a?(cls) } ||
|
665
|
+
@definition_options.failure_exception_types&.any? { |cls| err.is_a?(cls) }
|
632
666
|
end
|
633
667
|
|
634
668
|
def with_context_frozen(&)
|
@@ -643,11 +677,12 @@ module Temporalio
|
|
643
677
|
payload_array:,
|
644
678
|
method_name: defn.to_invoke.is_a?(Symbol) ? defn.to_invoke : nil,
|
645
679
|
raw_args: defn.raw_args,
|
680
|
+
arg_hints: defn.arg_hints,
|
646
681
|
ignore_first_param: defn.name.nil? # Dynamic
|
647
682
|
)
|
648
683
|
end
|
649
684
|
|
650
|
-
def convert_args(payload_array:, method_name:, raw_args:, ignore_first_param: false)
|
685
|
+
def convert_args(payload_array:, method_name:, raw_args:, arg_hints:, ignore_first_param: false)
|
651
686
|
# Just in case it is not an array
|
652
687
|
payload_array = payload_array.to_ary
|
653
688
|
|
@@ -687,7 +722,7 @@ module Temporalio
|
|
687
722
|
if raw_args
|
688
723
|
payload_array.map { |p| Converters::RawValue.new(p) }
|
689
724
|
else
|
690
|
-
ProtoUtils.convert_from_payload_array(@payload_converter, payload_array)
|
725
|
+
ProtoUtils.convert_from_payload_array(@payload_converter, payload_array, hints: arg_hints)
|
691
726
|
end
|
692
727
|
end
|
693
728
|
|
@@ -13,7 +13,7 @@ module Temporalio
|
|
13
13
|
module Worker
|
14
14
|
# Worker for handling workflow activations. Most activation work is delegated to the workflow executor.
|
15
15
|
class WorkflowWorker
|
16
|
-
def self.workflow_definitions(workflows)
|
16
|
+
def self.workflow_definitions(workflows, should_enforce_versioning_behavior:)
|
17
17
|
workflows.each_with_object({}) do |workflow, hash|
|
18
18
|
# Load definition
|
19
19
|
defn = begin
|
@@ -29,6 +29,12 @@ module Temporalio
|
|
29
29
|
# Confirm name not in use
|
30
30
|
raise ArgumentError, "Multiple workflows named #{defn.name || '<dynamic>'}" if hash.key?(defn.name)
|
31
31
|
|
32
|
+
# Enforce versioning behavior is set when versioning is on
|
33
|
+
if should_enforce_versioning_behavior &&
|
34
|
+
defn.versioning_behavior == VersioningBehavior::UNSPECIFIED && !defn.dynamic_options_method
|
35
|
+
raise ArgumentError, "Workflow #{defn.name} must specify a versioning behavior"
|
36
|
+
end
|
37
|
+
|
32
38
|
hash[defn.name] = defn
|
33
39
|
end
|
34
40
|
end
|
@@ -69,7 +75,7 @@ module Temporalio
|
|
69
75
|
workflow_payload_codec_thread_pool:,
|
70
76
|
unsafe_workflow_io_enabled:,
|
71
77
|
debug_mode:,
|
72
|
-
on_eviction: nil
|
78
|
+
assert_valid_local_activity:, on_eviction: nil
|
73
79
|
)
|
74
80
|
@executor = workflow_executor
|
75
81
|
|
@@ -105,13 +111,14 @@ module Temporalio
|
|
105
111
|
disable_eager_activity_execution:,
|
106
112
|
workflow_interceptors:,
|
107
113
|
workflow_failure_exception_types: workflow_failure_exception_types.map do |t|
|
108
|
-
unless t.is_a?(Class) && t
|
114
|
+
unless t.is_a?(Class) && t <= Exception
|
109
115
|
raise ArgumentError, 'All failure types must classes inheriting Exception'
|
110
116
|
end
|
111
117
|
|
112
118
|
t
|
113
119
|
end.freeze,
|
114
|
-
unsafe_workflow_io_enabled
|
120
|
+
unsafe_workflow_io_enabled:,
|
121
|
+
assert_valid_local_activity:
|
115
122
|
)
|
116
123
|
@state.on_eviction = on_eviction if on_eviction
|
117
124
|
|
@@ -186,14 +193,16 @@ module Temporalio
|
|
186
193
|
class State
|
187
194
|
attr_reader :workflow_definitions, :bridge_worker, :logger, :metric_meter, :data_converter, :deadlock_timeout,
|
188
195
|
:illegal_calls, :namespace, :task_queue, :disable_eager_activity_execution,
|
189
|
-
:workflow_interceptors, :workflow_failure_exception_types, :unsafe_workflow_io_enabled
|
196
|
+
:workflow_interceptors, :workflow_failure_exception_types, :unsafe_workflow_io_enabled,
|
197
|
+
:assert_valid_local_activity
|
190
198
|
|
191
199
|
attr_writer :on_eviction
|
192
200
|
|
193
201
|
def initialize(
|
194
202
|
workflow_definitions:, bridge_worker:, logger:, metric_meter:, data_converter:, deadlock_timeout:,
|
195
203
|
illegal_calls:, namespace:, task_queue:, disable_eager_activity_execution:,
|
196
|
-
workflow_interceptors:, workflow_failure_exception_types:, unsafe_workflow_io_enabled
|
204
|
+
workflow_interceptors:, workflow_failure_exception_types:, unsafe_workflow_io_enabled:,
|
205
|
+
assert_valid_local_activity:
|
197
206
|
)
|
198
207
|
@workflow_definitions = workflow_definitions
|
199
208
|
@bridge_worker = bridge_worker
|
@@ -208,6 +217,7 @@ module Temporalio
|
|
208
217
|
@workflow_interceptors = workflow_interceptors
|
209
218
|
@workflow_failure_exception_types = workflow_failure_exception_types
|
210
219
|
@unsafe_workflow_io_enabled = unsafe_workflow_io_enabled
|
220
|
+
@assert_valid_local_activity = assert_valid_local_activity
|
211
221
|
|
212
222
|
@running_workflows = {}
|
213
223
|
@running_workflows_mutex = Mutex.new
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporalio/api'
|
4
|
+
|
5
|
+
module Temporalio
|
6
|
+
Priority = Data.define(
|
7
|
+
:priority_key
|
8
|
+
)
|
9
|
+
|
10
|
+
# Priority contains metadata that controls relative ordering of task processing when tasks are
|
11
|
+
# backlogged in a queue. Initially, Priority will be used in activity and workflow task
|
12
|
+
# queues, which are typically where backlogs exist. Priority is (for now) attached to
|
13
|
+
# workflows and activities. Activities and child workflows inherit Priority from the workflow
|
14
|
+
# that created them, but may override fields when they are started or modified. For each field
|
15
|
+
# of a Priority on an activity/workflow, not present or equal to zero/empty string means to
|
16
|
+
# inherit the value from the calling workflow, or if there is no calling workflow, then use
|
17
|
+
# the default (documented on the field).
|
18
|
+
#
|
19
|
+
# The overall semantics of Priority are:
|
20
|
+
# 1. First, consider "priority_key": lower number goes first.
|
21
|
+
# (more will be added here later).
|
22
|
+
#
|
23
|
+
# @!attribute priority_key
|
24
|
+
# @return [Integer, nil] The priority key, which is a positive integer from 1 to n, where
|
25
|
+
# smaller integers correspond to higher priorities (tasks run sooner). In general, tasks in a
|
26
|
+
# queue should be processed in close to priority order, although small deviations are possible.
|
27
|
+
# The maximum priority value (minimum priority) is determined by server configuration, and
|
28
|
+
# defaults to 5.
|
29
|
+
#
|
30
|
+
# The default priority is (min+max)/2. With the default max of 5 and min of 1, that comes
|
31
|
+
# out to 3.
|
32
|
+
class Priority
|
33
|
+
# @!visibility private
|
34
|
+
def self._from_proto(priority)
|
35
|
+
return default if priority.nil?
|
36
|
+
|
37
|
+
new(priority_key: priority.priority_key.zero? ? nil : priority.priority_key)
|
38
|
+
end
|
39
|
+
|
40
|
+
# The default priority instance.
|
41
|
+
#
|
42
|
+
# @return [Priority] The default priority
|
43
|
+
def self.default
|
44
|
+
@default ||= new(priority_key: nil)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @!visibility private
|
48
|
+
def _to_proto
|
49
|
+
return nil if priority_key.nil?
|
50
|
+
|
51
|
+
Temporalio::Api::Common::V1::Priority.new(priority_key: priority_key || 0)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Boolean] True if this priority is empty/default
|
55
|
+
def empty?
|
56
|
+
priority_key.nil?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -21,9 +21,10 @@ module Temporalio
|
|
21
21
|
activity_type: 'unknown',
|
22
22
|
attempt: 1,
|
23
23
|
current_attempt_scheduled_time: Time.at(0),
|
24
|
-
heartbeat_details: [],
|
25
24
|
heartbeat_timeout: nil,
|
26
25
|
local?: false,
|
26
|
+
priority: Temporalio::Priority.default,
|
27
|
+
raw_heartbeat_details: [],
|
27
28
|
schedule_to_close_timeout: 1.0,
|
28
29
|
scheduled_time: Time.at(0),
|
29
30
|
start_to_close_timeout: 1.0,
|
@@ -42,8 +43,10 @@ module Temporalio
|
|
42
43
|
# @param info [Activity::Info] Value for {Activity::Context#info}. Users should not try to instantiate this
|
43
44
|
# themselves, but rather use `with` on {default_info}.
|
44
45
|
# @param on_heartbeat [Proc(Array), nil] Proc that is called with all heartbeat details when
|
45
|
-
# {Activity::Context#heartbeat} is called.
|
46
|
+
# {Activity::Context#heartbeat} is called. Should return a value
|
46
47
|
# @param cancellation [Cancellation] Value for {Activity::Context#cancellation}.
|
48
|
+
# @param on_cancellation_details [Proc, nil] Proc that is called when {Activity::Context#cancellation_details} is
|
49
|
+
# called. Defaults to a proc that returns an instance if canceled with `cancel_requested` as true.
|
47
50
|
# @param worker_shutdown_cancellation [Cancellation] Value for {Activity::Context#worker_shutdown_cancellation}.
|
48
51
|
# @param payload_converter [Converters::PayloadConverter] Value for {Activity::Context#payload_converter}.
|
49
52
|
# @param logger [Logger] Value for {Activity::Context#logger}.
|
@@ -55,6 +58,7 @@ module Temporalio
|
|
55
58
|
info: ActivityEnvironment.default_info,
|
56
59
|
on_heartbeat: nil,
|
57
60
|
cancellation: Cancellation.new,
|
61
|
+
on_cancellation_details: nil,
|
58
62
|
worker_shutdown_cancellation: Cancellation.new,
|
59
63
|
payload_converter: Converters::PayloadConverter.default,
|
60
64
|
logger: Logger.new(nil),
|
@@ -65,6 +69,9 @@ module Temporalio
|
|
65
69
|
@info = info
|
66
70
|
@on_heartbeat = on_heartbeat
|
67
71
|
@cancellation = cancellation
|
72
|
+
@on_cancellation_details = on_cancellation_details || proc do
|
73
|
+
@_cancellation_details ||= Activity::CancellationDetails.new if @cancellation.canceled?
|
74
|
+
end
|
68
75
|
@worker_shutdown_cancellation = worker_shutdown_cancellation
|
69
76
|
@payload_converter = payload_converter
|
70
77
|
@logger = logger
|
@@ -92,6 +99,7 @@ module Temporalio
|
|
92
99
|
defn.instance.is_a?(Proc) ? defn.instance.call : defn.instance,
|
93
100
|
on_heartbeat: @on_heartbeat,
|
94
101
|
cancellation: @cancellation,
|
102
|
+
on_cancellation_details: @on_cancellation_details,
|
95
103
|
worker_shutdown_cancellation: @worker_shutdown_cancellation,
|
96
104
|
payload_converter: @payload_converter,
|
97
105
|
logger: @logger,
|
@@ -121,6 +129,7 @@ module Temporalio
|
|
121
129
|
instance:,
|
122
130
|
on_heartbeat:,
|
123
131
|
cancellation:,
|
132
|
+
on_cancellation_details:,
|
124
133
|
worker_shutdown_cancellation:,
|
125
134
|
payload_converter:,
|
126
135
|
logger:,
|
@@ -131,6 +140,7 @@ module Temporalio
|
|
131
140
|
@instance = instance
|
132
141
|
@on_heartbeat = on_heartbeat
|
133
142
|
@cancellation = cancellation
|
143
|
+
@on_cancellation_details = on_cancellation_details
|
134
144
|
@worker_shutdown_cancellation = worker_shutdown_cancellation
|
135
145
|
@payload_converter = payload_converter
|
136
146
|
@logger = logger
|
@@ -152,6 +162,11 @@ module Temporalio
|
|
152
162
|
def client
|
153
163
|
@client or raise 'No client configured in this test environment'
|
154
164
|
end
|
165
|
+
|
166
|
+
# @!visibility private
|
167
|
+
def cancellation_details
|
168
|
+
@on_cancellation_details.call
|
169
|
+
end
|
155
170
|
end
|
156
171
|
|
157
172
|
private_constant :Context
|
@@ -322,7 +322,7 @@ module Temporalio
|
|
322
322
|
raise 'Block required' unless block_given?
|
323
323
|
return super unless supports_time_skipping?
|
324
324
|
|
325
|
-
already_disabled =
|
325
|
+
already_disabled = !@auto_time_skipping
|
326
326
|
@auto_time_skipping = false
|
327
327
|
begin
|
328
328
|
yield
|
@@ -394,8 +394,8 @@ module Temporalio
|
|
394
394
|
end
|
395
395
|
|
396
396
|
# @!visibility private
|
397
|
-
def result(follow_runs: true, rpc_options: nil)
|
398
|
-
@env.time_skipping_unlocked { super(follow_runs:, rpc_options:) }
|
397
|
+
def result(follow_runs: true, result_hint: nil, rpc_options: nil)
|
398
|
+
@env.time_skipping_unlocked { super(follow_runs:, result_hint:, rpc_options:) }
|
399
399
|
end
|
400
400
|
end
|
401
401
|
end
|
data/lib/temporalio/version.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporalio/worker_deployment_version'
|
4
|
+
|
5
|
+
module Temporalio
|
6
|
+
# Base class for version overrides that can be provided in start workflow options.
|
7
|
+
# Used to control the versioning behavior of workflows started with this override.
|
8
|
+
#
|
9
|
+
# WARNING: Experimental API.
|
10
|
+
class VersioningOverride
|
11
|
+
# @!visibility private
|
12
|
+
def _to_proto
|
13
|
+
raise NotImplementedError, 'Subclasses must implement this method'
|
14
|
+
end
|
15
|
+
|
16
|
+
# Represents a versioning override to pin a workflow to a specific version
|
17
|
+
class Pinned < VersioningOverride
|
18
|
+
# The worker deployment version to pin to
|
19
|
+
# @return [WorkerDeploymentVersion]
|
20
|
+
attr_reader :version
|
21
|
+
|
22
|
+
# Create a new pinned versioning override
|
23
|
+
#
|
24
|
+
# @param version [WorkerDeploymentVersion] The worker deployment version to pin to
|
25
|
+
def initialize(version)
|
26
|
+
@version = version
|
27
|
+
super()
|
28
|
+
end
|
29
|
+
|
30
|
+
# TODO: Remove deprecated field setting once removed from server
|
31
|
+
|
32
|
+
# @!visibility private
|
33
|
+
def _to_proto
|
34
|
+
Api::Workflow::V1::VersioningOverride.new(
|
35
|
+
behavior: Api::Enums::V1::VersioningBehavior::VERSIONING_BEHAVIOR_PINNED,
|
36
|
+
pinned_version: @version.to_canonical_string,
|
37
|
+
pinned: Api::Workflow::V1::VersioningOverride::PinnedOverride.new(
|
38
|
+
behavior: Api::Workflow::V1::VersioningOverride::PinnedOverrideBehavior::PINNED_OVERRIDE_BEHAVIOR_PINNED,
|
39
|
+
version: @version._to_proto
|
40
|
+
)
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Represents a versioning override to auto-upgrade a workflow
|
46
|
+
class AutoUpgrade < VersioningOverride
|
47
|
+
# @!visibility private
|
48
|
+
def _to_proto
|
49
|
+
Api::Workflow::V1::VersioningOverride.new(
|
50
|
+
behavior: Api::Enums::V1::VersioningBehavior::VERSIONING_BEHAVIOR_AUTO_UPGRADE,
|
51
|
+
auto_upgrade: true
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -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
|