temporalio 0.3.0-x86_64-linux → 0.4.0-x86_64-linux
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/Gemfile +4 -0
- data/Rakefile +1 -1
- data/lib/temporalio/activity/context.rb +13 -0
- data/lib/temporalio/activity/definition.rb +22 -5
- data/lib/temporalio/activity/info.rb +3 -0
- data/lib/temporalio/api/batch/v1/message.rb +6 -1
- data/lib/temporalio/api/command/v1/message.rb +1 -1
- data/lib/temporalio/api/common/v1/message.rb +2 -1
- data/lib/temporalio/api/deployment/v1/message.rb +38 -0
- data/lib/temporalio/api/enums/v1/batch_operation.rb +1 -1
- data/lib/temporalio/api/enums/v1/common.rb +1 -1
- data/lib/temporalio/api/enums/v1/deployment.rb +23 -0
- data/lib/temporalio/api/enums/v1/event_type.rb +1 -1
- data/lib/temporalio/api/enums/v1/failed_cause.rb +1 -1
- data/lib/temporalio/api/enums/v1/nexus.rb +21 -0
- data/lib/temporalio/api/enums/v1/reset.rb +1 -1
- data/lib/temporalio/api/enums/v1/workflow.rb +2 -1
- data/lib/temporalio/api/errordetails/v1/message.rb +3 -1
- data/lib/temporalio/api/failure/v1/message.rb +3 -1
- data/lib/temporalio/api/history/v1/message.rb +3 -1
- data/lib/temporalio/api/nexus/v1/message.rb +2 -1
- data/lib/temporalio/api/payload_visitor.rb +75 -7
- data/lib/temporalio/api/query/v1/message.rb +2 -1
- data/lib/temporalio/api/taskqueue/v1/message.rb +4 -1
- data/lib/temporalio/api/workflow/v1/message.rb +9 -1
- data/lib/temporalio/api/workflowservice/v1/request_response.rb +40 -11
- data/lib/temporalio/api/workflowservice/v1/service.rb +1 -1
- data/lib/temporalio/api.rb +1 -0
- data/lib/temporalio/client/connection/workflow_service.rb +238 -28
- data/lib/temporalio/client/interceptor.rb +39 -0
- data/lib/temporalio/client/schedule.rb +25 -1
- data/lib/temporalio/client/with_start_workflow_operation.rb +115 -0
- data/lib/temporalio/client/workflow_execution.rb +19 -0
- data/lib/temporalio/client/workflow_handle.rb +3 -3
- data/lib/temporalio/client.rb +125 -2
- data/lib/temporalio/contrib/open_telemetry.rb +470 -0
- data/lib/temporalio/error.rb +1 -0
- 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_task/activity_task.rb +1 -1
- data/lib/temporalio/internal/bridge/api/common/common.rb +2 -1
- data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +1 -1
- data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +1 -1
- data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +2 -1
- data/lib/temporalio/internal/bridge/runtime.rb +3 -0
- data/lib/temporalio/internal/bridge/testing.rb +3 -0
- data/lib/temporalio/internal/client/implementation.rb +232 -10
- data/lib/temporalio/internal/proto_utils.rb +34 -2
- data/lib/temporalio/internal/worker/activity_worker.rb +20 -8
- data/lib/temporalio/internal/worker/multi_runner.rb +2 -2
- data/lib/temporalio/internal/worker/workflow_instance/context.rb +57 -3
- data/lib/temporalio/internal/worker/workflow_instance/details.rb +4 -2
- data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +11 -26
- data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +22 -2
- data/lib/temporalio/internal/worker/workflow_instance.rb +76 -32
- data/lib/temporalio/internal/worker/workflow_worker.rb +62 -19
- 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 +42 -14
- data/lib/temporalio/testing/workflow_environment.rb +26 -3
- data/lib/temporalio/version.rb +1 -1
- data/lib/temporalio/worker/interceptor.rb +3 -0
- data/lib/temporalio/worker/thread_pool.rb +5 -5
- data/lib/temporalio/worker/tuner.rb +38 -0
- data/lib/temporalio/worker/workflow_executor/thread_pool.rb +13 -8
- data/lib/temporalio/worker/workflow_executor.rb +1 -1
- data/lib/temporalio/worker/workflow_replayer.rb +350 -0
- data/lib/temporalio/worker.rb +58 -52
- data/lib/temporalio/workflow/definition.rb +40 -8
- data/lib/temporalio/workflow/future.rb +2 -2
- data/lib/temporalio/workflow/info.rb +22 -0
- data/lib/temporalio/workflow.rb +60 -8
- data/lib/temporalio/workflow_history.rb +26 -1
- data/temporalio.gemspec +2 -1
- metadata +25 -4
data/lib/temporalio/worker.rb
CHANGED
@@ -6,6 +6,7 @@ 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'
|
@@ -51,10 +52,13 @@ module Temporalio
|
|
51
52
|
:illegal_workflow_calls,
|
52
53
|
:workflow_failure_exception_types,
|
53
54
|
:workflow_payload_codec_thread_pool,
|
55
|
+
:unsafe_workflow_io_enabled,
|
54
56
|
:debug_mode
|
55
57
|
)
|
56
58
|
|
57
59
|
# Options as returned from {options} for `**to_h` splat use in {initialize}. See {initialize} for details.
|
60
|
+
#
|
61
|
+
# Note, the `client` within can be replaced via client setter.
|
58
62
|
class Options; end # rubocop:disable Lint/EmptyClass
|
59
63
|
|
60
64
|
# @return [String] Memoized default build ID. This default value is built as a checksum of all of the loaded Ruby
|
@@ -137,7 +141,8 @@ module Temporalio
|
|
137
141
|
case event
|
138
142
|
when Internal::Worker::MultiRunner::Event::PollSuccess
|
139
143
|
# Successful poll
|
140
|
-
event.worker
|
144
|
+
event.worker #: Worker
|
145
|
+
._on_poll_bytes(runner, event.worker_type, event.bytes)
|
141
146
|
when Internal::Worker::MultiRunner::Event::PollFailure
|
142
147
|
# Poll failure, this causes shutdown of all workers
|
143
148
|
logger.error('Poll failure (beginning worker shutdown if not already occurring)')
|
@@ -274,7 +279,7 @@ module Temporalio
|
|
274
279
|
end
|
275
280
|
end
|
276
281
|
|
277
|
-
# @return [Options]
|
282
|
+
# @return [Options] Options for this worker which has the same attributes as {initialize}.
|
278
283
|
attr_reader :options
|
279
284
|
|
280
285
|
# Create a new worker. At least one activity or workflow must be present.
|
@@ -343,6 +348,9 @@ module Temporalio
|
|
343
348
|
# @param workflow_payload_codec_thread_pool [ThreadPool, nil] Thread pool to run payload codec encode/decode within.
|
344
349
|
# This is required if a payload codec exists and the worker is not fiber based. Codecs can potentially block
|
345
350
|
# execution which is why they need to be run in the background.
|
351
|
+
# @param unsafe_workflow_io_enabled [Boolean] If false, the default, workflow code that invokes io_wait on the fiber
|
352
|
+
# scheduler will fail. Instead of setting this to true, users are encouraged to use {Workflow::Unsafe.io_enabled}
|
353
|
+
# with a block for narrower enabling of IO.
|
346
354
|
# @param debug_mode [Boolean] If true, deadlock detection is disabled. Deadlock detection will fail workflow tasks
|
347
355
|
# if they block the thread for too long. This defaults to true if the `TEMPORAL_DEBUG` environment variable is
|
348
356
|
# `true` or `1`.
|
@@ -374,10 +382,13 @@ module Temporalio
|
|
374
382
|
illegal_workflow_calls: Worker.default_illegal_workflow_calls,
|
375
383
|
workflow_failure_exception_types: [],
|
376
384
|
workflow_payload_codec_thread_pool: nil,
|
385
|
+
unsafe_workflow_io_enabled: false,
|
377
386
|
debug_mode: %w[true 1].include?(ENV['TEMPORAL_DEBUG'].to_s.downcase)
|
378
387
|
)
|
379
388
|
raise ArgumentError, 'Must have at least one activity or workflow' if activities.empty? && workflows.empty?
|
380
389
|
|
390
|
+
Internal::ProtoUtils.assert_non_reserved_name(task_queue)
|
391
|
+
|
381
392
|
@options = Options.new(
|
382
393
|
client:,
|
383
394
|
task_queue:,
|
@@ -406,24 +417,16 @@ module Temporalio
|
|
406
417
|
illegal_workflow_calls:,
|
407
418
|
workflow_failure_exception_types:,
|
408
419
|
workflow_payload_codec_thread_pool:,
|
420
|
+
unsafe_workflow_io_enabled:,
|
409
421
|
debug_mode:
|
410
422
|
).freeze
|
411
423
|
|
412
424
|
# Preload workflow definitions and some workflow settings for the bridge
|
413
425
|
workflow_definitions = Internal::Worker::WorkflowWorker.workflow_definitions(workflows)
|
414
|
-
nondeterminism_as_workflow_fail =
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
next unless defn.failure_exception_types.any? { |t| t.is_a?(Class) && t >= Workflow::NondeterminismError }
|
419
|
-
|
420
|
-
# If they tried to do this on a dynamic workflow and haven't already set worker-level option, warn
|
421
|
-
unless defn.name || nondeterminism_as_workflow_fail
|
422
|
-
warn('Note, dynamic workflows cannot trap non-determinism errors, so worker-level ' \
|
423
|
-
'workflow_failure_exception_types should be set to capture that if that is the intention')
|
424
|
-
end
|
425
|
-
defn.name
|
426
|
-
end.compact
|
426
|
+
nondeterminism_as_workflow_fail, nondeterminism_as_workflow_fail_for_types =
|
427
|
+
Internal::Worker::WorkflowWorker.bridge_workflow_failure_exception_type_options(
|
428
|
+
workflow_failure_exception_types:, workflow_definitions:
|
429
|
+
)
|
427
430
|
|
428
431
|
# Create the bridge worker
|
429
432
|
@bridge_worker = Internal::Bridge::Worker.new(
|
@@ -433,11 +436,7 @@ module Temporalio
|
|
433
436
|
workflow: !workflows.empty?,
|
434
437
|
namespace: client.namespace,
|
435
438
|
task_queue:,
|
436
|
-
tuner:
|
437
|
-
workflow_slot_supplier: to_bridge_slot_supplier_options(tuner.workflow_slot_supplier),
|
438
|
-
activity_slot_supplier: to_bridge_slot_supplier_options(tuner.activity_slot_supplier),
|
439
|
-
local_activity_slot_supplier: to_bridge_slot_supplier_options(tuner.local_activity_slot_supplier)
|
440
|
-
),
|
439
|
+
tuner: tuner._to_bridge_options,
|
441
440
|
build_id:,
|
442
441
|
identity_override: identity,
|
443
442
|
max_cached_workflows:,
|
@@ -476,13 +475,30 @@ module Temporalio
|
|
476
475
|
bridge_worker: @bridge_worker)
|
477
476
|
end
|
478
477
|
unless workflows.empty?
|
479
|
-
@workflow_worker = Internal::Worker::WorkflowWorker.new(
|
480
|
-
|
481
|
-
|
478
|
+
@workflow_worker = Internal::Worker::WorkflowWorker.new(
|
479
|
+
bridge_worker: @bridge_worker,
|
480
|
+
namespace: client.namespace,
|
481
|
+
task_queue:,
|
482
|
+
workflow_definitions:,
|
483
|
+
workflow_executor:,
|
484
|
+
logger:,
|
485
|
+
data_converter: client.data_converter,
|
486
|
+
metric_meter: client.connection.options.runtime.metric_meter,
|
487
|
+
workflow_interceptors: @workflow_interceptors,
|
488
|
+
disable_eager_activity_execution:,
|
489
|
+
illegal_workflow_calls:,
|
490
|
+
workflow_failure_exception_types:,
|
491
|
+
workflow_payload_codec_thread_pool:,
|
492
|
+
unsafe_workflow_io_enabled:,
|
493
|
+
debug_mode:
|
494
|
+
)
|
482
495
|
end
|
483
496
|
|
484
497
|
# Validate worker
|
485
498
|
@bridge_worker.validate
|
499
|
+
|
500
|
+
# Mutex needed for accessing and replacing a client
|
501
|
+
@client_mutex = Mutex.new
|
486
502
|
end
|
487
503
|
|
488
504
|
# @return [String] Task queue set on the worker options.
|
@@ -490,6 +506,25 @@ module Temporalio
|
|
490
506
|
@options.task_queue
|
491
507
|
end
|
492
508
|
|
509
|
+
# @return [Client] Client for this worker. This is the same as {Options.client} in {options}, but surrounded by a
|
510
|
+
# mutex to be safe for client replacement in {client=}.
|
511
|
+
def client
|
512
|
+
@client_mutex.synchronize { @options.client }
|
513
|
+
end
|
514
|
+
|
515
|
+
# Replace the worker's client. When this is called, the client is replaced on the internal worker which means any
|
516
|
+
# new calls will be made on the new client (but existing calls will still complete on the previous one). This is
|
517
|
+
# commonly used for providing a new client with updated authentication credentials.
|
518
|
+
#
|
519
|
+
# @param new_client [Client] New client to use for new calls.
|
520
|
+
def client=(new_client)
|
521
|
+
@client_mutex.synchronize do
|
522
|
+
@bridge_worker.replace_client(new_client.connection._core_client)
|
523
|
+
@options = @options.with(client: new_client)
|
524
|
+
new_client
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
493
528
|
# Run this worker until cancellation or optional block completes. When the cancellation or block is complete, the
|
494
529
|
# worker is shut down. This will return the block result if everything successful or raise an error if not.
|
495
530
|
#
|
@@ -543,11 +578,6 @@ module Temporalio
|
|
543
578
|
@activity_interceptors
|
544
579
|
end
|
545
580
|
|
546
|
-
# @!visibility private
|
547
|
-
def _workflow_interceptors
|
548
|
-
@workflow_interceptors
|
549
|
-
end
|
550
|
-
|
551
581
|
# @!visibility private
|
552
582
|
def _on_poll_bytes(runner, worker_type, bytes)
|
553
583
|
case worker_type
|
@@ -569,29 +599,5 @@ module Temporalio
|
|
569
599
|
@workflow_worker&.on_shutdown_complete
|
570
600
|
@workflow_worker = nil
|
571
601
|
end
|
572
|
-
|
573
|
-
private
|
574
|
-
|
575
|
-
def to_bridge_slot_supplier_options(slot_supplier)
|
576
|
-
if slot_supplier.is_a?(Tuner::SlotSupplier::Fixed)
|
577
|
-
Internal::Bridge::Worker::TunerSlotSupplierOptions.new(
|
578
|
-
fixed_size: slot_supplier.slots,
|
579
|
-
resource_based: nil
|
580
|
-
)
|
581
|
-
elsif slot_supplier.is_a?(Tuner::SlotSupplier::ResourceBased)
|
582
|
-
Internal::Bridge::Worker::TunerSlotSupplierOptions.new(
|
583
|
-
fixed_size: nil,
|
584
|
-
resource_based: Internal::Bridge::Worker::TunerResourceBasedSlotSupplierOptions.new(
|
585
|
-
target_mem_usage: slot_supplier.tuner_options.target_memory_usage,
|
586
|
-
target_cpu_usage: slot_supplier.tuner_options.target_cpu_usage,
|
587
|
-
min_slots: slot_supplier.slot_options.min_slots,
|
588
|
-
max_slots: slot_supplier.slot_options.max_slots,
|
589
|
-
ramp_throttle: slot_supplier.slot_options.ramp_throttle
|
590
|
-
)
|
591
|
-
)
|
592
|
-
else
|
593
|
-
raise ArgumentError, 'Tuner slot suppliers must be instances of Fixed or ResourceBased'
|
594
|
-
end
|
595
|
-
end
|
596
602
|
end
|
597
603
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'temporalio/internal/proto_utils'
|
3
4
|
require 'temporalio/workflow'
|
4
5
|
require 'temporalio/workflow/handler_unfinished_policy'
|
5
6
|
|
@@ -71,7 +72,9 @@ module Temporalio
|
|
71
72
|
# `attr_accessor`. If a writer is needed alongside this, use `attr_writer`.
|
72
73
|
#
|
73
74
|
# @param attr_names [Array<Symbol>] Attributes to expose.
|
74
|
-
|
75
|
+
# @param description [String, nil] Description that may appear in CLI/UI, applied to each query handler
|
76
|
+
# implicitly created. This is currently experimental.
|
77
|
+
def workflow_query_attr_reader(*attr_names, description: nil)
|
75
78
|
@workflow_queries ||= {}
|
76
79
|
attr_names.each do |attr_name|
|
77
80
|
raise 'Expected attr to be a symbol' unless attr_name.is_a?(Symbol)
|
@@ -83,7 +86,7 @@ module Temporalio
|
|
83
86
|
end
|
84
87
|
|
85
88
|
# Just run this as if done manually
|
86
|
-
workflow_query
|
89
|
+
workflow_query(description:)
|
87
90
|
define_method(attr_name) { instance_variable_get("@#{attr_name}") }
|
88
91
|
end
|
89
92
|
end
|
@@ -100,6 +103,8 @@ module Temporalio
|
|
100
103
|
# values.
|
101
104
|
#
|
102
105
|
# @param name [String, Symbol, nil] Override the default name.
|
106
|
+
# @param description [String, nil] Description for this handler that may appear in CLI/UI. This is currently
|
107
|
+
# experimental.
|
103
108
|
# @param dynamic [Boolean] If true, make the signal dynamic. This means it receives all other signals without
|
104
109
|
# handlers. This cannot have a name override since it is nameless. The first parameter will be the name. Often
|
105
110
|
# it is useful to have the second parameter be `*args` and `raw_args` be true.
|
@@ -109,19 +114,22 @@ module Temporalio
|
|
109
114
|
# when the workflow ends. The default warns, but this can be disabled.
|
110
115
|
def workflow_signal(
|
111
116
|
name: nil,
|
117
|
+
description: nil,
|
112
118
|
dynamic: false,
|
113
119
|
raw_args: false,
|
114
120
|
unfinished_policy: HandlerUnfinishedPolicy::WARN_AND_ABANDON
|
115
121
|
)
|
116
122
|
raise 'Cannot provide name if dynamic is true' if name && dynamic
|
117
123
|
|
118
|
-
self.pending_handler_details = { type: :signal, name:, dynamic:, raw_args:, unfinished_policy: }
|
124
|
+
self.pending_handler_details = { type: :signal, name:, description:, dynamic:, raw_args:, unfinished_policy: }
|
119
125
|
end
|
120
126
|
|
121
127
|
# Mark the next method as a workflow query with a default name as the name of the method. Queries can not have
|
122
128
|
# any side effects, meaning they should never mutate state or try to wait on anything.
|
123
129
|
#
|
124
130
|
# @param name [String, Symbol, nil] Override the default name.
|
131
|
+
# @param description [String, nil] Description for this handler that may appear in CLI/UI. This is currently
|
132
|
+
# experimental.
|
125
133
|
# @param dynamic [Boolean] If true, make the query dynamic. This means it receives all other queries without
|
126
134
|
# handlers. This cannot have a name override since it is nameless. The first parameter will be the name. Often
|
127
135
|
# it is useful to have the second parameter be `*args` and `raw_args` be true.
|
@@ -129,18 +137,21 @@ module Temporalio
|
|
129
137
|
# {Converters::RawValue} which is a raw payload wrapper, convertible with {Workflow.payload_converter}.
|
130
138
|
def workflow_query(
|
131
139
|
name: nil,
|
140
|
+
description: nil,
|
132
141
|
dynamic: false,
|
133
142
|
raw_args: false
|
134
143
|
)
|
135
144
|
raise 'Cannot provide name if dynamic is true' if name && dynamic
|
136
145
|
|
137
|
-
self.pending_handler_details = { type: :query, name:, dynamic:, raw_args: }
|
146
|
+
self.pending_handler_details = { type: :query, name:, description:, dynamic:, raw_args: }
|
138
147
|
end
|
139
148
|
|
140
149
|
# Mark the next method as a workflow update with a default name as the name of the method. Updates can return
|
141
150
|
# values. Separate validation methods can be provided via {workflow_update_validator}.
|
142
151
|
#
|
143
152
|
# @param name [String, Symbol, nil] Override the default name.
|
153
|
+
# @param description [String, nil] Description for this handler that may appear in CLI/UI. This is currently
|
154
|
+
# experimental.
|
144
155
|
# @param dynamic [Boolean] If true, make the update dynamic. This means it receives all other updates without
|
145
156
|
# handlers. This cannot have a name override since it is nameless. The first parameter will be the name. Often
|
146
157
|
# it is useful to have the second parameter be `*args` and `raw_args` be true.
|
@@ -150,13 +161,14 @@ module Temporalio
|
|
150
161
|
# when the workflow ends. The default warns, but this can be disabled.
|
151
162
|
def workflow_update(
|
152
163
|
name: nil,
|
164
|
+
description: nil,
|
153
165
|
dynamic: false,
|
154
166
|
raw_args: false,
|
155
167
|
unfinished_policy: HandlerUnfinishedPolicy::WARN_AND_ABANDON
|
156
168
|
)
|
157
169
|
raise 'Cannot provide name if dynamic is true' if name && dynamic
|
158
170
|
|
159
|
-
self.pending_handler_details = { type: :update, name:, dynamic:, raw_args:, unfinished_policy: }
|
171
|
+
self.pending_handler_details = { type: :update, name:, description:, dynamic:, raw_args:, unfinished_policy: }
|
160
172
|
end
|
161
173
|
|
162
174
|
# Mark the next method as a workflow update validator to the given update method. The validator is expected to
|
@@ -225,6 +237,7 @@ module Temporalio
|
|
225
237
|
[Signal.new(
|
226
238
|
name: handler[:dynamic] ? nil : (handler[:name] || method_name).to_s,
|
227
239
|
to_invoke: method_name,
|
240
|
+
description: handler[:description],
|
228
241
|
raw_args: handler[:raw_args],
|
229
242
|
unfinished_policy: handler[:unfinished_policy]
|
230
243
|
), @workflow_signals, [@workflow_queries, @workflow_updates]]
|
@@ -232,12 +245,14 @@ module Temporalio
|
|
232
245
|
[Query.new(
|
233
246
|
name: handler[:dynamic] ? nil : (handler[:name] || method_name).to_s,
|
234
247
|
to_invoke: method_name,
|
248
|
+
description: handler[:description],
|
235
249
|
raw_args: handler[:raw_args]
|
236
250
|
), @workflow_queries, [@workflow_signals, @workflow_updates]]
|
237
251
|
when :update
|
238
252
|
[Update.new(
|
239
253
|
name: handler[:dynamic] ? nil : (handler[:name] || method_name).to_s,
|
240
254
|
to_invoke: method_name,
|
255
|
+
description: handler[:description],
|
241
256
|
raw_args: handler[:raw_args],
|
242
257
|
unfinished_policy: handler[:unfinished_policy]
|
243
258
|
), @workflow_updates, [@workflow_signals, @workflow_queries]]
|
@@ -430,6 +445,7 @@ module Temporalio
|
|
430
445
|
@signals = signals.dup.freeze
|
431
446
|
@queries = queries.dup.freeze
|
432
447
|
@updates = updates.dup.freeze
|
448
|
+
Internal::ProtoUtils.assert_non_reserved_name(name)
|
433
449
|
end
|
434
450
|
|
435
451
|
# @return [String] Workflow name.
|
@@ -441,7 +457,7 @@ module Temporalio
|
|
441
457
|
# A signal definition. This is usually built as a result of a {Definition.workflow_signal} method, but can be
|
442
458
|
# manually created to set at runtime on {Workflow.signal_handlers}.
|
443
459
|
class Signal
|
444
|
-
attr_reader :name, :to_invoke, :raw_args, :unfinished_policy
|
460
|
+
attr_reader :name, :to_invoke, :description, :raw_args, :unfinished_policy
|
445
461
|
|
446
462
|
# @!visibility private
|
447
463
|
def self._name_from_parameter(signal)
|
@@ -460,26 +476,31 @@ module Temporalio
|
|
460
476
|
#
|
461
477
|
# @param name [String, nil] Name or nil if dynamic.
|
462
478
|
# @param to_invoke [Symbol, Proc] Method name or proc to invoke.
|
479
|
+
# @param description [String, nil] Description for this handler that may appear in CLI/UI. This is currently
|
480
|
+
# experimental.
|
463
481
|
# @param raw_args [Boolean] Whether the parameters should be raw values.
|
464
482
|
# @param unfinished_policy [HandlerUnfinishedPolicy] How the workflow reacts when this handler is still running
|
465
483
|
# on workflow completion.
|
466
484
|
def initialize(
|
467
485
|
name:,
|
468
486
|
to_invoke:,
|
487
|
+
description: nil,
|
469
488
|
raw_args: false,
|
470
489
|
unfinished_policy: HandlerUnfinishedPolicy::WARN_AND_ABANDON
|
471
490
|
)
|
472
491
|
@name = name
|
473
492
|
@to_invoke = to_invoke
|
493
|
+
@description = description
|
474
494
|
@raw_args = raw_args
|
475
495
|
@unfinished_policy = unfinished_policy
|
496
|
+
Internal::ProtoUtils.assert_non_reserved_name(name)
|
476
497
|
end
|
477
498
|
end
|
478
499
|
|
479
500
|
# A query definition. This is usually built as a result of a {Definition.workflow_query} method, but can be
|
480
501
|
# manually created to set at runtime on {Workflow.query_handlers}.
|
481
502
|
class Query
|
482
|
-
attr_reader :name, :to_invoke, :raw_args
|
503
|
+
attr_reader :name, :to_invoke, :description, :raw_args
|
483
504
|
|
484
505
|
# @!visibility private
|
485
506
|
def self._name_from_parameter(query)
|
@@ -498,22 +519,27 @@ module Temporalio
|
|
498
519
|
#
|
499
520
|
# @param name [String, nil] Name or nil if dynamic.
|
500
521
|
# @param to_invoke [Symbol, Proc] Method name or proc to invoke.
|
522
|
+
# @param description [String, nil] Description for this handler that may appear in CLI/UI. This is currently
|
523
|
+
# experimental.
|
501
524
|
# @param raw_args [Boolean] Whether the parameters should be raw values.
|
502
525
|
def initialize(
|
503
526
|
name:,
|
504
527
|
to_invoke:,
|
528
|
+
description: nil,
|
505
529
|
raw_args: false
|
506
530
|
)
|
507
531
|
@name = name
|
508
532
|
@to_invoke = to_invoke
|
533
|
+
@description = description
|
509
534
|
@raw_args = raw_args
|
535
|
+
Internal::ProtoUtils.assert_non_reserved_name(name)
|
510
536
|
end
|
511
537
|
end
|
512
538
|
|
513
539
|
# An update definition. This is usually built as a result of a {Definition.workflow_update} method, but can be
|
514
540
|
# manually created to set at runtime on {Workflow.update_handlers}.
|
515
541
|
class Update
|
516
|
-
attr_reader :name, :to_invoke, :raw_args, :unfinished_policy, :validator_to_invoke
|
542
|
+
attr_reader :name, :to_invoke, :description, :raw_args, :unfinished_policy, :validator_to_invoke
|
517
543
|
|
518
544
|
# @!visibility private
|
519
545
|
def self._name_from_parameter(update)
|
@@ -532,6 +558,8 @@ module Temporalio
|
|
532
558
|
#
|
533
559
|
# @param name [String, nil] Name or nil if dynamic.
|
534
560
|
# @param to_invoke [Symbol, Proc] Method name or proc to invoke.
|
561
|
+
# @param description [String, nil] Description for this handler that may appear in CLI/UI. This is currently
|
562
|
+
# experimental.
|
535
563
|
# @param raw_args [Boolean] Whether the parameters should be raw values.
|
536
564
|
# @param unfinished_policy [HandlerUnfinishedPolicy] How the workflow reacts when this handler is still running
|
537
565
|
# on workflow completion.
|
@@ -539,15 +567,18 @@ module Temporalio
|
|
539
567
|
def initialize(
|
540
568
|
name:,
|
541
569
|
to_invoke:,
|
570
|
+
description: nil,
|
542
571
|
raw_args: false,
|
543
572
|
unfinished_policy: HandlerUnfinishedPolicy::WARN_AND_ABANDON,
|
544
573
|
validator_to_invoke: nil
|
545
574
|
)
|
546
575
|
@name = name
|
547
576
|
@to_invoke = to_invoke
|
577
|
+
@description = description
|
548
578
|
@raw_args = raw_args
|
549
579
|
@unfinished_policy = unfinished_policy
|
550
580
|
@validator_to_invoke = validator_to_invoke
|
581
|
+
Internal::ProtoUtils.assert_non_reserved_name(name)
|
551
582
|
end
|
552
583
|
|
553
584
|
# @!visibility private
|
@@ -555,6 +586,7 @@ module Temporalio
|
|
555
586
|
Update.new(
|
556
587
|
name:,
|
557
588
|
to_invoke:,
|
589
|
+
description:,
|
558
590
|
raw_args:,
|
559
591
|
unfinished_policy:,
|
560
592
|
validator_to_invoke:
|
@@ -8,7 +8,7 @@ module Temporalio
|
|
8
8
|
# workflows.
|
9
9
|
class Future
|
10
10
|
# Return a future that completes when any of the given futures complete. The returned future will return the first
|
11
|
-
# completed
|
11
|
+
# completed future's value or raise the first completed future's exception. To not raise the exception, see
|
12
12
|
# {try_any_of}.
|
13
13
|
#
|
14
14
|
# @param futures [Array<Future<Object>>] Futures to wait for the first to complete.
|
@@ -16,7 +16,7 @@ module Temporalio
|
|
16
16
|
def self.any_of(*futures)
|
17
17
|
Future.new do
|
18
18
|
Workflow.wait_condition(cancellation: nil) { futures.any?(&:done?) }
|
19
|
-
# We know a future is always returned from find, the
|
19
|
+
# We know a future is always returned from find, the || just helps type checker
|
20
20
|
(futures.find(&:done?) || raise).wait
|
21
21
|
end
|
22
22
|
end
|
@@ -7,11 +7,13 @@ module Temporalio
|
|
7
7
|
:continued_run_id,
|
8
8
|
:cron_schedule,
|
9
9
|
:execution_timeout,
|
10
|
+
:headers,
|
10
11
|
:last_failure,
|
11
12
|
:last_result,
|
12
13
|
:namespace,
|
13
14
|
:parent,
|
14
15
|
:retry_policy,
|
16
|
+
:root,
|
15
17
|
:run_id,
|
16
18
|
:run_timeout,
|
17
19
|
:start_time,
|
@@ -32,6 +34,8 @@ module Temporalio
|
|
32
34
|
# @return [String, nil] Cron schedule if applicable.
|
33
35
|
# @!attribute execution_timeout
|
34
36
|
# @return [Float, nil] Execution timeout for the workflow.
|
37
|
+
# @!attribute headers
|
38
|
+
# @return [Hash<String, Api::Common::V1::Payload>] Headers.
|
35
39
|
# @!attribute last_failure
|
36
40
|
# @return [Exception, nil] Failure if this workflow run is a continuation of a failure.
|
37
41
|
# @!attribute last_result
|
@@ -42,6 +46,9 @@ module Temporalio
|
|
42
46
|
# @return [ParentInfo, nil] Parent information for the workflow if this is a child.
|
43
47
|
# @!attribute retry_policy
|
44
48
|
# @return [RetryPolicy, nil] Retry policy for the workflow.
|
49
|
+
# @!attribute root
|
50
|
+
# @return [RootInfo, nil] Root information for the workflow. This is nil in pre-1.27.0 server versions or if there
|
51
|
+
# is no root (i.e. the root is itself).
|
45
52
|
# @!attribute run_id
|
46
53
|
# @return [String] Run ID for the workflow.
|
47
54
|
# @!attribute run_timeout
|
@@ -77,6 +84,21 @@ module Temporalio
|
|
77
84
|
:workflow_id,
|
78
85
|
keyword_init: true
|
79
86
|
)
|
87
|
+
|
88
|
+
# Information about a root of a workflow.
|
89
|
+
#
|
90
|
+
# @!attribute run_id
|
91
|
+
# @return [String] Run ID for the root.
|
92
|
+
# @!attribute workflow_id
|
93
|
+
# @return [String] Workflow ID for the root.
|
94
|
+
#
|
95
|
+
# @note WARNING: This class may have required parameters added to its constructor. Users should not instantiate
|
96
|
+
# this class or it may break in incompatible ways.
|
97
|
+
RootInfo = Struct.new(
|
98
|
+
:run_id,
|
99
|
+
:workflow_id,
|
100
|
+
keyword_init: true
|
101
|
+
)
|
80
102
|
end
|
81
103
|
end
|
82
104
|
end
|
data/lib/temporalio/workflow.rb
CHANGED
@@ -38,6 +38,24 @@ module Temporalio
|
|
38
38
|
_current.continue_as_new_suggested
|
39
39
|
end
|
40
40
|
|
41
|
+
# Get current details for this workflow that may appear in UI/CLI. Unlike static details set at start, this value
|
42
|
+
# can be updated throughout the life of the workflow. This can be in Temporal markdown format and can span multiple
|
43
|
+
# lines. This is currently experimental.
|
44
|
+
#
|
45
|
+
# @return [String] Current details. Default is empty string.
|
46
|
+
def self.current_details
|
47
|
+
_current.current_details
|
48
|
+
end
|
49
|
+
|
50
|
+
# Set current details for this workflow that may appear in UI/CLI. Unlike static details set at start, this value
|
51
|
+
# can be updated throughout the life of the workflow. This can be in Temporal markdown format and can span multiple
|
52
|
+
# lines. This is currently experimental.
|
53
|
+
#
|
54
|
+
# @param details [String] Current details. Can use empty string to unset.
|
55
|
+
def self.current_details=(details)
|
56
|
+
_current.current_details = details
|
57
|
+
end
|
58
|
+
|
41
59
|
# @return [Integer] Current number of events in history. This value is the current history event count up until the
|
42
60
|
# current task. Note, this value may not be up to date when accessed in a query.
|
43
61
|
def self.current_history_length
|
@@ -77,6 +95,8 @@ module Temporalio
|
|
77
95
|
# @param activity [Class<Activity::Definition>, Symbol, String] Activity definition class or activity name.
|
78
96
|
# @param args [Array<Object>] Arguments to the activity.
|
79
97
|
# @param task_queue [String] Task queue to run the activity on. Defaults to the current workflow's task queue.
|
98
|
+
# @param summary [String, nil] Single-line summary for this activity that may appear in CLI/UI. This can be in
|
99
|
+
# single-line Temporal markdown format. This is currently experimental.
|
80
100
|
# @param schedule_to_close_timeout [Float, nil] Max amount of time the activity can take from first being scheduled
|
81
101
|
# to being completed before it times out. This is inclusive of all retries.
|
82
102
|
# @param schedule_to_start_timeout [Float, nil] Max amount of time the activity can take to be started from first
|
@@ -107,6 +127,7 @@ module Temporalio
|
|
107
127
|
activity,
|
108
128
|
*args,
|
109
129
|
task_queue: info.task_queue,
|
130
|
+
summary: nil,
|
110
131
|
schedule_to_close_timeout: nil,
|
111
132
|
schedule_to_start_timeout: nil,
|
112
133
|
start_to_close_timeout: nil,
|
@@ -119,7 +140,7 @@ module Temporalio
|
|
119
140
|
)
|
120
141
|
_current.execute_activity(
|
121
142
|
activity, *args,
|
122
|
-
task_queue:, schedule_to_close_timeout:, schedule_to_start_timeout:, start_to_close_timeout:,
|
143
|
+
task_queue:, summary:, schedule_to_close_timeout:, schedule_to_start_timeout:, start_to_close_timeout:,
|
123
144
|
heartbeat_timeout:, retry_policy:, cancellation:, cancellation_type:, activity_id:, disable_eager_execution:
|
124
145
|
)
|
125
146
|
end
|
@@ -130,6 +151,8 @@ module Temporalio
|
|
130
151
|
*args,
|
131
152
|
id: random.uuid,
|
132
153
|
task_queue: info.task_queue,
|
154
|
+
static_summary: nil,
|
155
|
+
static_details: nil,
|
133
156
|
cancellation: Workflow.cancellation,
|
134
157
|
cancellation_type: ChildWorkflowCancellationType::WAIT_CANCELLATION_COMPLETED,
|
135
158
|
parent_close_policy: ParentClosePolicy::TERMINATE,
|
@@ -144,8 +167,9 @@ module Temporalio
|
|
144
167
|
)
|
145
168
|
start_child_workflow(
|
146
169
|
workflow, *args,
|
147
|
-
id:, task_queue:,
|
148
|
-
|
170
|
+
id:, task_queue:, static_summary:, static_details:, cancellation:, cancellation_type:,
|
171
|
+
parent_close_policy:, execution_timeout:, run_timeout:, task_timeout:, id_reuse_policy:,
|
172
|
+
retry_policy:, cron_schedule:, memo:, search_attributes:
|
149
173
|
).result
|
150
174
|
end
|
151
175
|
|
@@ -220,6 +244,12 @@ module Temporalio
|
|
220
244
|
_current.info
|
221
245
|
end
|
222
246
|
|
247
|
+
# @return [Definition, nil] Workflow class instance. This should always be present except in
|
248
|
+
# {Worker::Interceptor::Workflow::Inbound.init} where it will be nil.
|
249
|
+
def self.instance
|
250
|
+
_current.instance
|
251
|
+
end
|
252
|
+
|
223
253
|
# @return [Logger] Logger for the workflow. This is a scoped logger that automatically appends workflow details to
|
224
254
|
# every log and takes care not to log during replay.
|
225
255
|
def self.logger
|
@@ -298,7 +328,7 @@ module Temporalio
|
|
298
328
|
# value cannot be negative. Since Temporal timers are server-side, timer resolution may not end up as precise as
|
299
329
|
# system timers.
|
300
330
|
# @param summary [String, nil] A simple string identifying this timer that may be visible in UI/CLI. While it can be
|
301
|
-
# normal text, it is best to treat as a timer ID.
|
331
|
+
# normal text, it is best to treat as a timer ID. This is currently experimental.
|
302
332
|
# @param cancellation [Cancellation] Cancellation for this timer.
|
303
333
|
# @raise [Error::CanceledError] Sleep canceled.
|
304
334
|
def self.sleep(duration, summary: nil, cancellation: Workflow.cancellation)
|
@@ -311,6 +341,12 @@ module Temporalio
|
|
311
341
|
# @param args [Array<Object>] Arguments to the workflow.
|
312
342
|
# @param id [String] Unique identifier for the workflow execution. Defaults to a new UUID from {random}.
|
313
343
|
# @param task_queue [String] Task queue to run the workflow on. Defaults to the current workflow's task queue.
|
344
|
+
# @param static_summary [String, nil] Fixed single-line summary for this workflow execution that may appear in
|
345
|
+
# CLI/UI. This can be in single-line Temporal markdown format. This is currently experimental.
|
346
|
+
# @param static_details [String, nil] Fixed details for this workflow execution that may appear in CLI/UI. This can
|
347
|
+
# be in Temporal markdown format and can be multiple lines. This is a fixed value on the workflow that cannot be
|
348
|
+
# updated. For details that can be updated, use {Workflow.current_details=} within the workflow. This is currently
|
349
|
+
# experimental.
|
314
350
|
# @param cancellation [Cancellation] Cancellation to apply to the child workflow. How cancellation is treated is
|
315
351
|
# based on `cancellation_type`. This defaults to the workflow's cancellation.
|
316
352
|
# @param cancellation_type [ChildWorkflowCancellationType] How the child workflow will react to cancellation.
|
@@ -333,6 +369,8 @@ module Temporalio
|
|
333
369
|
*args,
|
334
370
|
id: random.uuid,
|
335
371
|
task_queue: info.task_queue,
|
372
|
+
static_summary: nil,
|
373
|
+
static_details: nil,
|
336
374
|
cancellation: Workflow.cancellation,
|
337
375
|
cancellation_type: ChildWorkflowCancellationType::WAIT_CANCELLATION_COMPLETED,
|
338
376
|
parent_close_policy: ParentClosePolicy::TERMINATE,
|
@@ -347,11 +385,18 @@ module Temporalio
|
|
347
385
|
)
|
348
386
|
_current.start_child_workflow(
|
349
387
|
workflow, *args,
|
350
|
-
id:, task_queue:,
|
351
|
-
|
388
|
+
id:, task_queue:, static_summary:, static_details:, cancellation:, cancellation_type:,
|
389
|
+
parent_close_policy:, execution_timeout:, run_timeout:, task_timeout:, id_reuse_policy:,
|
390
|
+
retry_policy:, cron_schedule:, memo:, search_attributes:
|
352
391
|
)
|
353
392
|
end
|
354
393
|
|
394
|
+
# @return [Hash<Object, Object>] General in-workflow storage. Most users will store state on the workflow class
|
395
|
+
# instance instead, this is only for utilities without access to the class instance.
|
396
|
+
def self.storage
|
397
|
+
_current.storage
|
398
|
+
end
|
399
|
+
|
355
400
|
# Run the block until the timeout is reached. This is backed by {sleep}. This does not accept cancellation because
|
356
401
|
# it is expected the block within will properly handle/bubble cancellation.
|
357
402
|
#
|
@@ -361,8 +406,8 @@ module Temporalio
|
|
361
406
|
# exception.
|
362
407
|
# @param message [String] Message to use for timeout exception. Defaults to "execution expired" like
|
363
408
|
# {::Timeout.timeout}.
|
364
|
-
# @param summary [String] Timer
|
365
|
-
# method for details.
|
409
|
+
# @param summary [String] Timer summary for the timer created by this timeout. This is backed by {sleep} so see that
|
410
|
+
# method for details. This is currently experimental.
|
366
411
|
#
|
367
412
|
# @yield Block to run with a timeout.
|
368
413
|
# @return [Object] The result of the block.
|
@@ -458,6 +503,13 @@ module Temporalio
|
|
458
503
|
def self.illegal_call_tracing_disabled(&)
|
459
504
|
Workflow._current.illegal_call_tracing_disabled(&)
|
460
505
|
end
|
506
|
+
|
507
|
+
# Run a block of code with IO enabled. Specifically this allows the `io_wait` call of the fiber scheduler to work.
|
508
|
+
# Users should be cautious about using this as it can often signify unsafe code. Note, this is often only
|
509
|
+
# applicable to network code as file IO and most process-based IO does not go through scheduler `io_wait`.
|
510
|
+
def self.io_enabled(&)
|
511
|
+
Workflow._current.io_enabled(&)
|
512
|
+
end
|
461
513
|
end
|
462
514
|
|
463
515
|
# Error that is raised by a workflow out of the primary workflow method to issue a continue-as-new.
|