temporalio 0.3.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 +1019 -669
- data/Cargo.toml +5 -5
- data/Gemfile +4 -0
- data/README.md +281 -44
- data/Rakefile +1 -1
- data/ext/Cargo.toml +4 -3
- data/lib/temporalio/activity/cancellation_details.rb +58 -0
- data/lib/temporalio/activity/context.rb +23 -1
- data/lib/temporalio/activity/definition.rb +63 -8
- data/lib/temporalio/activity/info.rb +28 -4
- data/lib/temporalio/activity.rb +2 -0
- data/lib/temporalio/api/activity/v1/message.rb +1 -1
- data/lib/temporalio/api/batch/v1/message.rb +9 -2
- data/lib/temporalio/api/cloud/account/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +11 -2
- data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +2 -2
- data/lib/temporalio/api/cloud/identity/v1/message.rb +7 -2
- data/lib/temporalio/api/cloud/namespace/v1/message.rb +6 -2
- data/lib/temporalio/api/cloud/nexus/v1/message.rb +3 -2
- data/lib/temporalio/api/cloud/operation/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/region/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/resource/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/sink/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/usage/v1/message.rb +1 -1
- data/lib/temporalio/api/command/v1/message.rb +2 -2
- data/lib/temporalio/api/common/v1/grpc_status.rb +1 -1
- data/lib/temporalio/api/common/v1/message.rb +4 -2
- data/lib/temporalio/api/deployment/v1/message.rb +39 -0
- data/lib/temporalio/api/enums/v1/batch_operation.rb +2 -2
- data/lib/temporalio/api/enums/v1/command_type.rb +1 -1
- data/lib/temporalio/api/enums/v1/common.rb +5 -2
- data/lib/temporalio/api/enums/v1/deployment.rb +24 -0
- data/lib/temporalio/api/enums/v1/event_type.rb +2 -2
- data/lib/temporalio/api/enums/v1/failed_cause.rb +2 -2
- data/lib/temporalio/api/enums/v1/namespace.rb +1 -1
- data/lib/temporalio/api/enums/v1/nexus.rb +21 -0
- data/lib/temporalio/api/enums/v1/query.rb +1 -1
- data/lib/temporalio/api/enums/v1/reset.rb +2 -2
- data/lib/temporalio/api/enums/v1/schedule.rb +1 -1
- data/lib/temporalio/api/enums/v1/task_queue.rb +1 -1
- data/lib/temporalio/api/enums/v1/update.rb +1 -1
- data/lib/temporalio/api/enums/v1/workflow.rb +3 -2
- data/lib/temporalio/api/errordetails/v1/message.rb +4 -2
- data/lib/temporalio/api/export/v1/message.rb +1 -1
- data/lib/temporalio/api/failure/v1/message.rb +5 -2
- data/lib/temporalio/api/filter/v1/message.rb +1 -1
- data/lib/temporalio/api/history/v1/message.rb +6 -2
- data/lib/temporalio/api/namespace/v1/message.rb +1 -1
- data/lib/temporalio/api/nexus/v1/message.rb +3 -2
- data/lib/temporalio/api/operatorservice/v1/request_response.rb +1 -1
- data/lib/temporalio/api/operatorservice/v1/service.rb +1 -1
- data/lib/temporalio/api/payload_visitor.rb +162 -7
- data/lib/temporalio/api/protocol/v1/message.rb +1 -1
- data/lib/temporalio/api/query/v1/message.rb +3 -2
- data/lib/temporalio/api/replication/v1/message.rb +1 -1
- data/lib/temporalio/api/rules/v1/message.rb +27 -0
- data/lib/temporalio/api/schedule/v1/message.rb +2 -2
- data/lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb +1 -1
- data/lib/temporalio/api/sdk/v1/task_complete_metadata.rb +1 -1
- data/lib/temporalio/api/sdk/v1/user_metadata.rb +1 -1
- data/lib/temporalio/api/sdk/v1/workflow_metadata.rb +1 -1
- data/lib/temporalio/api/taskqueue/v1/message.rb +5 -2
- data/lib/temporalio/api/testservice/v1/request_response.rb +1 -1
- data/lib/temporalio/api/testservice/v1/service.rb +1 -1
- data/lib/temporalio/api/update/v1/message.rb +1 -1
- data/lib/temporalio/api/version/v1/message.rb +1 -1
- data/lib/temporalio/api/worker/v1/message.rb +30 -0
- data/lib/temporalio/api/workflow/v1/message.rb +22 -2
- data/lib/temporalio/api/workflowservice/v1/request_response.rb +58 -12
- data/lib/temporalio/api/workflowservice/v1/service.rb +2 -2
- data/lib/temporalio/api.rb +1 -0
- data/lib/temporalio/client/async_activity_handle.rb +12 -4
- data/lib/temporalio/client/connection/cloud_service.rb +60 -0
- data/lib/temporalio/client/connection/workflow_service.rb +343 -28
- data/lib/temporalio/client/interceptor.rb +64 -7
- data/lib/temporalio/client/schedule.rb +35 -3
- data/lib/temporalio/client/with_start_workflow_operation.rb +123 -0
- data/lib/temporalio/client/workflow_execution.rb +19 -0
- data/lib/temporalio/client/workflow_handle.rb +47 -7
- data/lib/temporalio/client/workflow_update_handle.rb +9 -3
- data/lib/temporalio/client.rb +231 -4
- data/lib/temporalio/common_enums.rb +14 -0
- data/lib/temporalio/contrib/open_telemetry.rb +474 -0
- data/lib/temporalio/converters/data_converter.rb +18 -8
- data/lib/temporalio/converters/failure_converter.rb +6 -3
- data/lib/temporalio/converters/payload_converter/binary_null.rb +2 -2
- data/lib/temporalio/converters/payload_converter/binary_plain.rb +2 -2
- data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +2 -2
- data/lib/temporalio/converters/payload_converter/composite.rb +6 -4
- data/lib/temporalio/converters/payload_converter/encoding.rb +4 -2
- data/lib/temporalio/converters/payload_converter/json_plain.rb +2 -2
- data/lib/temporalio/converters/payload_converter/json_protobuf.rb +2 -2
- data/lib/temporalio/converters/payload_converter.rb +16 -6
- data/lib/temporalio/error/failure.rb +19 -1
- data/lib/temporalio/error.rb +2 -1
- data/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +1 -1
- data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +3 -2
- data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +1 -1
- data/lib/temporalio/internal/bridge/api/common/common.rb +3 -2
- data/lib/temporalio/internal/bridge/api/core_interface.rb +1 -1
- data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +1 -1
- data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +3 -2
- data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +2 -2
- data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +3 -2
- data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +3 -2
- data/lib/temporalio/internal/bridge/runtime.rb +3 -0
- data/lib/temporalio/internal/bridge/testing.rb +3 -0
- data/lib/temporalio/internal/bridge/worker.rb +28 -4
- data/lib/temporalio/internal/bridge.rb +1 -1
- data/lib/temporalio/internal/client/implementation.rb +281 -51
- data/lib/temporalio/internal/proto_utils.rb +38 -6
- data/lib/temporalio/internal/worker/activity_worker.rb +112 -27
- data/lib/temporalio/internal/worker/multi_runner.rb +2 -2
- data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +8 -6
- data/lib/temporalio/internal/worker/workflow_instance/context.rb +100 -5
- data/lib/temporalio/internal/worker/workflow_instance/details.rb +7 -2
- data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +2 -2
- data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +64 -18
- data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +39 -40
- data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +22 -2
- data/lib/temporalio/internal/worker/workflow_instance.rb +134 -55
- data/lib/temporalio/internal/worker/workflow_worker.rb +74 -21
- data/lib/temporalio/priority.rb +59 -0
- data/lib/temporalio/runtime/metric_buffer.rb +94 -0
- data/lib/temporalio/runtime.rb +48 -10
- data/lib/temporalio/search_attributes.rb +13 -0
- data/lib/temporalio/testing/activity_environment.rb +59 -16
- data/lib/temporalio/testing/workflow_environment.rb +29 -6
- data/lib/temporalio/version.rb +1 -1
- data/lib/temporalio/versioning_override.rb +56 -0
- data/lib/temporalio/worker/deployment_options.rb +45 -0
- data/lib/temporalio/worker/illegal_workflow_call_validator.rb +64 -0
- data/lib/temporalio/worker/interceptor.rb +16 -1
- data/lib/temporalio/worker/poller_behavior.rb +61 -0
- data/lib/temporalio/worker/thread_pool.rb +6 -6
- data/lib/temporalio/worker/tuner.rb +38 -0
- data/lib/temporalio/worker/workflow_executor/thread_pool.rb +14 -8
- data/lib/temporalio/worker/workflow_executor.rb +1 -1
- data/lib/temporalio/worker/workflow_replayer.rb +349 -0
- data/lib/temporalio/worker.rb +117 -75
- data/lib/temporalio/worker_deployment_version.rb +67 -0
- data/lib/temporalio/workflow/child_workflow_handle.rb +10 -2
- data/lib/temporalio/workflow/definition.rb +217 -35
- data/lib/temporalio/workflow/external_workflow_handle.rb +3 -1
- data/lib/temporalio/workflow/future.rb +2 -2
- data/lib/temporalio/workflow/info.rb +26 -1
- data/lib/temporalio/workflow.rb +119 -15
- data/lib/temporalio/workflow_history.rb +26 -1
- data/lib/temporalio.rb +1 -0
- data/temporalio.gemspec +3 -1
- metadata +36 -6
@@ -93,8 +93,10 @@ module Temporalio
|
|
93
93
|
def handle_start_task(task_token, start)
|
94
94
|
set_running_activity(task_token, nil)
|
95
95
|
|
96
|
-
# Find activity definition, falling back to dynamic if
|
97
|
-
defn = @activities[start.activity_type]
|
96
|
+
# Find activity definition, falling back to dynamic if not found and not reserved name
|
97
|
+
defn = @activities[start.activity_type]
|
98
|
+
defn = @activities[nil] if !defn && !Internal::ProtoUtils.reserved_name?(start.activity_type)
|
99
|
+
|
98
100
|
if defn.nil?
|
99
101
|
raise Error::ApplicationError.new(
|
100
102
|
"Activity #{start.activity_type} for workflow #{start.workflow_execution.workflow_id} " \
|
@@ -114,7 +116,7 @@ module Temporalio
|
|
114
116
|
# Unset at the end
|
115
117
|
Activity::Context._current_executor = nil
|
116
118
|
end
|
117
|
-
rescue Exception => e # rubocop:disable Lint/RescueException We are intending to catch everything here
|
119
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- We are intending to catch everything here
|
118
120
|
remove_running_activity(task_token)
|
119
121
|
@scoped_logger.warn("Failed starting activity #{start.activity_type}")
|
120
122
|
@scoped_logger.warn(e)
|
@@ -146,10 +148,18 @@ module Temporalio
|
|
146
148
|
@scoped_logger.warn("Cannot find activity to cancel for token #{task_token}")
|
147
149
|
return
|
148
150
|
end
|
149
|
-
activity._server_requested_cancel = true
|
150
|
-
_, cancel_proc = activity.cancellation
|
151
151
|
begin
|
152
|
-
|
152
|
+
activity._cancel(
|
153
|
+
reason: cancel.reason.to_s,
|
154
|
+
details: Activity::CancellationDetails.new(
|
155
|
+
gone_from_server: cancel.details.is_not_found,
|
156
|
+
cancel_requested: cancel.details.is_cancelled,
|
157
|
+
timed_out: cancel.details.is_timed_out,
|
158
|
+
worker_shutdown: cancel.details.is_worker_shutdown,
|
159
|
+
paused: cancel.details.is_paused,
|
160
|
+
reset: cancel.details.is_reset
|
161
|
+
)
|
162
|
+
)
|
153
163
|
rescue StandardError => e
|
154
164
|
@scoped_logger.warn("Failed cancelling activity #{activity.info.activity_type} \
|
155
165
|
with ID #{activity.info.activity_id}")
|
@@ -166,12 +176,15 @@ module Temporalio
|
|
166
176
|
current_attempt_scheduled_time: Internal::ProtoUtils.timestamp_to_time(
|
167
177
|
start.current_attempt_scheduled_time
|
168
178
|
) || raise, # Never nil
|
169
|
-
heartbeat_details: ProtoUtils.convert_from_payload_array(
|
170
|
-
@worker.options.client.data_converter,
|
171
|
-
start.heartbeat_details.to_ary
|
172
|
-
),
|
173
179
|
heartbeat_timeout: Internal::ProtoUtils.duration_to_seconds(start.heartbeat_timeout),
|
174
180
|
local?: start.is_local,
|
181
|
+
priority: Priority._from_proto(start.priority),
|
182
|
+
raw_heartbeat_details: begin
|
183
|
+
payloads = start.heartbeat_details.to_ary
|
184
|
+
codec = @worker.options.client.data_converter.payload_codec
|
185
|
+
payloads = codec.decode(payloads) if codec
|
186
|
+
payloads.map { |p| Temporalio::Converters::RawValue.new(p) }
|
187
|
+
end,
|
175
188
|
schedule_to_close_timeout: Internal::ProtoUtils.duration_to_seconds(start.schedule_to_close_timeout),
|
176
189
|
scheduled_time: Internal::ProtoUtils.timestamp_to_time(start.scheduled_time) || raise, # Never nil
|
177
190
|
start_to_close_timeout: Internal::ProtoUtils.duration_to_seconds(start.start_to_close_timeout),
|
@@ -182,7 +195,7 @@ module Temporalio
|
|
182
195
|
workflow_namespace: start.workflow_namespace,
|
183
196
|
workflow_run_id: start.workflow_execution.run_id,
|
184
197
|
workflow_type: start.workflow_type
|
185
|
-
)
|
198
|
+
)
|
186
199
|
|
187
200
|
# Build input
|
188
201
|
input = Temporalio::Worker::Interceptor::Activity::ExecuteInput.new(
|
@@ -194,13 +207,19 @@ module Temporalio
|
|
194
207
|
payloads = codec.decode(payloads) if codec
|
195
208
|
payloads.map { |p| Temporalio::Converters::RawValue.new(p) }
|
196
209
|
else
|
197
|
-
ProtoUtils.convert_from_payload_array(
|
210
|
+
ProtoUtils.convert_from_payload_array(
|
211
|
+
@worker.options.client.data_converter,
|
212
|
+
start.input.to_ary,
|
213
|
+
hints: defn.arg_hints
|
214
|
+
)
|
198
215
|
end,
|
216
|
+
result_hint: defn.result_hint,
|
199
217
|
headers: ProtoUtils.headers_from_proto_map(start.header_fields, @worker.options.client.data_converter) || {}
|
200
218
|
)
|
201
219
|
|
202
220
|
# Run
|
203
221
|
activity = RunningActivity.new(
|
222
|
+
worker: @worker,
|
204
223
|
info:,
|
205
224
|
cancellation: Cancellation.new,
|
206
225
|
worker_shutdown_cancellation: @worker._worker_shutdown_cancellation,
|
@@ -210,8 +229,8 @@ module Temporalio
|
|
210
229
|
)
|
211
230
|
Activity::Context._current_executor&.set_activity_context(defn, activity)
|
212
231
|
set_running_activity(task_token, activity)
|
213
|
-
run_activity(activity, input)
|
214
|
-
rescue Exception => e # rubocop:disable Lint/RescueException We are intending to catch everything here
|
232
|
+
run_activity(defn, activity, input)
|
233
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- We are intending to catch everything here
|
215
234
|
@scoped_logger.warn("Failed starting or sending completion for activity #{start.activity_type}")
|
216
235
|
@scoped_logger.warn(e)
|
217
236
|
# This means that the activity couldn't start or send completion (run
|
@@ -236,15 +255,18 @@ module Temporalio
|
|
236
255
|
remove_running_activity(task_token)
|
237
256
|
end
|
238
257
|
|
239
|
-
def run_activity(activity, input)
|
258
|
+
def run_activity(defn, activity, input)
|
240
259
|
result = begin
|
260
|
+
# Create the instance. We choose to do this before interceptors so that it is available in the interceptor.
|
261
|
+
activity.instance = defn.instance.is_a?(Proc) ? defn.instance.call : defn.instance # steep:ignore
|
262
|
+
|
241
263
|
# Build impl with interceptors
|
242
264
|
# @type var impl: Temporalio::Worker::Interceptor::Activity::Inbound
|
243
265
|
impl = InboundImplementation.new(self)
|
244
266
|
impl = @worker._activity_interceptors.reverse_each.reduce(impl) do |acc, int|
|
245
267
|
int.intercept_activity(acc)
|
246
268
|
end
|
247
|
-
impl.init(OutboundImplementation.new(self))
|
269
|
+
impl.init(OutboundImplementation.new(self, activity.info.task_token))
|
248
270
|
|
249
271
|
# Execute
|
250
272
|
result = impl.execute(input)
|
@@ -252,16 +274,40 @@ module Temporalio
|
|
252
274
|
# Success
|
253
275
|
Bridge::Api::ActivityResult::ActivityExecutionResult.new(
|
254
276
|
completed: Bridge::Api::ActivityResult::Success.new(
|
255
|
-
result: @worker.options.client.data_converter.to_payload(result)
|
277
|
+
result: @worker.options.client.data_converter.to_payload(result, hint: input.result_hint)
|
256
278
|
)
|
257
279
|
)
|
258
|
-
rescue Exception => e # rubocop:disable Lint/RescueException We are intending to catch everything here
|
280
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- We are intending to catch everything here
|
259
281
|
if e.is_a?(Activity::CompleteAsyncError)
|
260
282
|
# Wanting to complete async
|
261
283
|
@scoped_logger.debug('Completing activity asynchronously')
|
262
284
|
Bridge::Api::ActivityResult::ActivityExecutionResult.new(
|
263
285
|
will_complete_async: Bridge::Api::ActivityResult::WillCompleteAsync.new
|
264
286
|
)
|
287
|
+
elsif e.is_a?(Error::CanceledError) && activity.cancellation_details&.paused?
|
288
|
+
# Server requested pause
|
289
|
+
@scoped_logger.debug('Completing activity as failed due to exception caused by pause')
|
290
|
+
Bridge::Api::ActivityResult::ActivityExecutionResult.new(
|
291
|
+
failed: Bridge::Api::ActivityResult::Failure.new(
|
292
|
+
failure: @worker.options.client.data_converter.to_failure(
|
293
|
+
Error._with_backtrace_and_cause(
|
294
|
+
Error::ApplicationError.new('Activity paused', type: 'ActivityPause'), backtrace: nil, cause: e
|
295
|
+
)
|
296
|
+
)
|
297
|
+
)
|
298
|
+
)
|
299
|
+
elsif e.is_a?(Error::CanceledError) && activity.cancellation_details&.reset?
|
300
|
+
# Server requested reset
|
301
|
+
@scoped_logger.debug('Completing activity as failed due to exception caused by reset')
|
302
|
+
Bridge::Api::ActivityResult::ActivityExecutionResult.new(
|
303
|
+
failed: Bridge::Api::ActivityResult::Failure.new(
|
304
|
+
failure: @worker.options.client.data_converter.to_failure(
|
305
|
+
Error._with_backtrace_and_cause(
|
306
|
+
Error::ApplicationError.new('Activity reset', type: 'ActivityReset'), backtrace: nil, cause: e
|
307
|
+
)
|
308
|
+
)
|
309
|
+
)
|
310
|
+
)
|
265
311
|
elsif e.is_a?(Error::CanceledError) && activity._server_requested_cancel
|
266
312
|
# Server requested cancel
|
267
313
|
@scoped_logger.debug('Completing activity as canceled')
|
@@ -272,8 +318,13 @@ module Temporalio
|
|
272
318
|
)
|
273
319
|
else
|
274
320
|
# General failure
|
275
|
-
|
276
|
-
|
321
|
+
log_level = if e.is_a?(Error::ApplicationError) && e.category == Error::ApplicationError::Category::BENIGN
|
322
|
+
Logger::DEBUG
|
323
|
+
else
|
324
|
+
Logger::WARN
|
325
|
+
end
|
326
|
+
@scoped_logger.add(log_level, 'Completing activity as failed')
|
327
|
+
@scoped_logger.add(log_level, e)
|
277
328
|
Bridge::Api::ActivityResult::ActivityExecutionResult.new(
|
278
329
|
failed: Bridge::Api::ActivityResult::Failure.new(
|
279
330
|
failure: @worker.options.client.data_converter.to_failure(e)
|
@@ -291,11 +342,24 @@ module Temporalio
|
|
291
342
|
)
|
292
343
|
end
|
293
344
|
|
345
|
+
def assert_valid_activity(activity)
|
346
|
+
defn = @activities[activity]
|
347
|
+
defn = @activities[nil] if !defn && !Internal::ProtoUtils.reserved_name?(activity)
|
348
|
+
|
349
|
+
return unless defn.nil?
|
350
|
+
|
351
|
+
raise ArgumentError,
|
352
|
+
"Activity #{activity} " \
|
353
|
+
"is not registered on this worker, available activities: #{@activities.keys.sort.join(', ')}"
|
354
|
+
end
|
355
|
+
|
294
356
|
class RunningActivity < Activity::Context
|
295
|
-
attr_reader :info, :cancellation, :
|
296
|
-
|
357
|
+
attr_reader :info, :cancellation, :cancellation_details, :worker_shutdown_cancellation,
|
358
|
+
:payload_converter, :logger, :_server_requested_cancel
|
359
|
+
attr_accessor :instance, :_outbound_impl
|
297
360
|
|
298
361
|
def initialize( # rubocop:disable Lint/MissingSuper
|
362
|
+
worker:,
|
299
363
|
info:,
|
300
364
|
cancellation:,
|
301
365
|
worker_shutdown_cancellation:,
|
@@ -303,8 +367,10 @@ module Temporalio
|
|
303
367
|
logger:,
|
304
368
|
runtime_metric_meter:
|
305
369
|
)
|
370
|
+
@worker = worker
|
306
371
|
@info = info
|
307
372
|
@cancellation = cancellation
|
373
|
+
@cancellation_details = nil
|
308
374
|
@worker_shutdown_cancellation = worker_shutdown_cancellation
|
309
375
|
@payload_converter = payload_converter
|
310
376
|
@logger = logger
|
@@ -313,13 +379,15 @@ module Temporalio
|
|
313
379
|
@_server_requested_cancel = false
|
314
380
|
end
|
315
381
|
|
316
|
-
def heartbeat(*details)
|
382
|
+
def heartbeat(*details, detail_hints: nil)
|
317
383
|
raise 'Implementation not set yet' if _outbound_impl.nil?
|
318
384
|
|
319
385
|
# No-op if local
|
320
386
|
return if info.local?
|
321
387
|
|
322
|
-
_outbound_impl.heartbeat(
|
388
|
+
_outbound_impl.heartbeat(
|
389
|
+
Temporalio::Worker::Interceptor::Activity::HeartbeatInput.new(details:, detail_hints:)
|
390
|
+
)
|
323
391
|
end
|
324
392
|
|
325
393
|
def metric_meter
|
@@ -331,6 +399,21 @@ module Temporalio
|
|
331
399
|
}
|
332
400
|
)
|
333
401
|
end
|
402
|
+
|
403
|
+
def client
|
404
|
+
@worker.client
|
405
|
+
end
|
406
|
+
|
407
|
+
def _cancel(reason:, details:)
|
408
|
+
# Do not issue cancel if already canceled
|
409
|
+
return if @cancellation_details
|
410
|
+
|
411
|
+
@_server_requested_cancel = true
|
412
|
+
# Set the cancellation details _before_ issuing the cancel itself
|
413
|
+
@cancellation_details = details
|
414
|
+
_, cancel_proc = cancellation
|
415
|
+
cancel_proc.call(reason:)
|
416
|
+
end
|
334
417
|
end
|
335
418
|
|
336
419
|
class InboundImplementation < Temporalio::Worker::Interceptor::Activity::Inbound
|
@@ -352,17 +435,19 @@ module Temporalio
|
|
352
435
|
end
|
353
436
|
|
354
437
|
class OutboundImplementation < Temporalio::Worker::Interceptor::Activity::Outbound
|
355
|
-
def initialize(worker)
|
438
|
+
def initialize(worker, task_token)
|
356
439
|
super(nil) # steep:ignore
|
357
440
|
@worker = worker
|
441
|
+
@task_token = task_token
|
358
442
|
end
|
359
443
|
|
360
444
|
def heartbeat(input)
|
361
445
|
@worker.bridge_worker.record_activity_heartbeat(
|
362
446
|
Bridge::Api::CoreInterface::ActivityHeartbeat.new(
|
363
|
-
task_token:
|
447
|
+
task_token: @task_token,
|
364
448
|
details: ProtoUtils.convert_to_payload_array(@worker.worker.options.client.data_converter,
|
365
|
-
input.details
|
449
|
+
input.details,
|
450
|
+
hints: input.detail_hints)
|
366
451
|
).to_proto
|
367
452
|
)
|
368
453
|
end
|
@@ -34,7 +34,7 @@ module Temporalio
|
|
34
34
|
rescue InjectEventForTesting => e
|
35
35
|
@queue.push(e.event)
|
36
36
|
@queue.push(Event::BlockSuccess.new(result: e))
|
37
|
-
rescue Exception => e # rubocop:disable Lint/RescueException Intentionally catch all
|
37
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- Intentionally catch all
|
38
38
|
@queue.push(Event::BlockFailure.new(error: e))
|
39
39
|
end
|
40
40
|
else
|
@@ -43,7 +43,7 @@ module Temporalio
|
|
43
43
|
rescue InjectEventForTesting => e
|
44
44
|
@queue.push(e.event)
|
45
45
|
@queue.push(Event::BlockSuccess.new(result: e))
|
46
|
-
rescue Exception => e # rubocop:disable Lint/RescueException Intentionally catch all
|
46
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- Intentionally catch all
|
47
47
|
@queue.push(Event::BlockFailure.new(error: e))
|
48
48
|
end
|
49
49
|
end
|
@@ -10,18 +10,20 @@ module Temporalio
|
|
10
10
|
class WorkflowInstance
|
11
11
|
# Implementation of the child workflow handle.
|
12
12
|
class ChildWorkflowHandle < Workflow::ChildWorkflowHandle
|
13
|
-
attr_reader :id, :first_execution_run_id
|
13
|
+
attr_reader :id, :first_execution_run_id, :result_hint
|
14
14
|
|
15
|
-
def initialize(id:, first_execution_run_id:, instance:,
|
15
|
+
def initialize(id:, first_execution_run_id:, instance:, # rubocop:disable Lint/MissingSuper
|
16
|
+
cancellation:, cancel_callback_key:, result_hint:)
|
16
17
|
@id = id
|
17
18
|
@first_execution_run_id = first_execution_run_id
|
18
19
|
@instance = instance
|
19
20
|
@cancellation = cancellation
|
20
21
|
@cancel_callback_key = cancel_callback_key
|
22
|
+
@result_hint = result_hint
|
21
23
|
@resolution = nil
|
22
24
|
end
|
23
25
|
|
24
|
-
def result
|
26
|
+
def result(result_hint: nil)
|
25
27
|
# Notice that we actually provide a detached cancellation here instead of defaulting to workflow
|
26
28
|
# cancellation because we don't want workflow cancellation (or a user-provided cancellation to this result
|
27
29
|
# call) to be able to interrupt waiting on a child that may be processing the cancellation.
|
@@ -29,7 +31,7 @@ module Temporalio
|
|
29
31
|
|
30
32
|
case @resolution.status
|
31
33
|
when :completed
|
32
|
-
@instance.payload_converter.from_payload(@resolution.completed.result)
|
34
|
+
@instance.payload_converter.from_payload(@resolution.completed.result, hint: result_hint || @result_hint)
|
33
35
|
when :failed
|
34
36
|
raise @instance.failure_converter.from_failure(@resolution.failed.failure, @instance.payload_converter)
|
35
37
|
when :cancelled
|
@@ -44,8 +46,8 @@ module Temporalio
|
|
44
46
|
@resolution = resolution
|
45
47
|
end
|
46
48
|
|
47
|
-
def signal(signal, *args, cancellation: Workflow.cancellation)
|
48
|
-
@instance.context._signal_child_workflow(id:, signal:, args:, cancellation:)
|
49
|
+
def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil)
|
50
|
+
@instance.context._signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:)
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
@@ -32,6 +32,20 @@ module Temporalio
|
|
32
32
|
@instance.continue_as_new_suggested
|
33
33
|
end
|
34
34
|
|
35
|
+
def current_details
|
36
|
+
@instance.current_details || ''
|
37
|
+
end
|
38
|
+
|
39
|
+
def current_details=(details)
|
40
|
+
raise 'Details must be a String' unless details.nil? || details.is_a?(String)
|
41
|
+
|
42
|
+
@instance.current_details = (details || '')
|
43
|
+
end
|
44
|
+
|
45
|
+
def current_deployment_version
|
46
|
+
@instance.current_deployment_version
|
47
|
+
end
|
48
|
+
|
35
49
|
def current_history_length
|
36
50
|
@instance.current_history_length
|
37
51
|
end
|
@@ -48,10 +62,21 @@ module Temporalio
|
|
48
62
|
@instance.patch(patch_id:, deprecated: true)
|
49
63
|
end
|
50
64
|
|
65
|
+
def durable_scheduler_disabled(&)
|
66
|
+
prev = Fiber.current_scheduler
|
67
|
+
illegal_call_tracing_disabled { Fiber.set_scheduler(nil) }
|
68
|
+
begin
|
69
|
+
yield
|
70
|
+
ensure
|
71
|
+
illegal_call_tracing_disabled { Fiber.set_scheduler(prev) }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
51
75
|
def execute_activity(
|
52
76
|
activity,
|
53
77
|
*args,
|
54
78
|
task_queue:,
|
79
|
+
summary:,
|
55
80
|
schedule_to_close_timeout:,
|
56
81
|
schedule_to_start_timeout:,
|
57
82
|
start_to_close_timeout:,
|
@@ -60,13 +85,30 @@ module Temporalio
|
|
60
85
|
cancellation:,
|
61
86
|
cancellation_type:,
|
62
87
|
activity_id:,
|
63
|
-
disable_eager_execution
|
88
|
+
disable_eager_execution:,
|
89
|
+
priority:,
|
90
|
+
arg_hints:,
|
91
|
+
result_hint:
|
64
92
|
)
|
93
|
+
activity, defn_arg_hints, defn_result_hint =
|
94
|
+
case activity
|
95
|
+
when Class
|
96
|
+
defn = Activity::Definition::Info.from_activity(activity)
|
97
|
+
[defn.name&.to_s, defn.arg_hints, defn.result_hint]
|
98
|
+
when Symbol, String
|
99
|
+
[activity.to_s, nil, nil]
|
100
|
+
else
|
101
|
+
raise ArgumentError,
|
102
|
+
'Activity must be a definition class, or a symbol/string'
|
103
|
+
end
|
104
|
+
raise 'Cannot invoke dynamic activities' unless activity
|
105
|
+
|
65
106
|
@outbound.execute_activity(
|
66
107
|
Temporalio::Worker::Interceptor::Workflow::ExecuteActivityInput.new(
|
67
108
|
activity:,
|
68
109
|
args:,
|
69
110
|
task_queue: task_queue || info.task_queue,
|
111
|
+
summary:,
|
70
112
|
schedule_to_close_timeout:,
|
71
113
|
schedule_to_start_timeout:,
|
72
114
|
start_to_close_timeout:,
|
@@ -76,6 +118,9 @@ module Temporalio
|
|
76
118
|
cancellation_type:,
|
77
119
|
activity_id:,
|
78
120
|
disable_eager_execution: disable_eager_execution || @instance.disable_eager_activity_execution,
|
121
|
+
priority:,
|
122
|
+
arg_hints: arg_hints || defn_arg_hints,
|
123
|
+
result_hint: result_hint || defn_result_hint,
|
79
124
|
headers: {}
|
80
125
|
)
|
81
126
|
)
|
@@ -91,8 +136,22 @@ module Temporalio
|
|
91
136
|
local_retry_threshold:,
|
92
137
|
cancellation:,
|
93
138
|
cancellation_type:,
|
94
|
-
activity_id
|
139
|
+
activity_id:,
|
140
|
+
arg_hints:,
|
141
|
+
result_hint:
|
95
142
|
)
|
143
|
+
activity, defn_arg_hints, defn_result_hint =
|
144
|
+
case activity
|
145
|
+
when Class
|
146
|
+
defn = Activity::Definition::Info.from_activity(activity)
|
147
|
+
[defn.name&.to_s, defn.arg_hints, defn.result_hint]
|
148
|
+
when Symbol, String
|
149
|
+
[activity.to_s, nil, nil]
|
150
|
+
else
|
151
|
+
raise ArgumentError, 'Activity must be a definition class, or a symbol/string'
|
152
|
+
end
|
153
|
+
raise 'Cannot invoke dynamic activities' unless activity
|
154
|
+
|
96
155
|
@outbound.execute_local_activity(
|
97
156
|
Temporalio::Worker::Interceptor::Workflow::ExecuteLocalActivityInput.new(
|
98
157
|
activity:,
|
@@ -105,6 +164,8 @@ module Temporalio
|
|
105
164
|
cancellation:,
|
106
165
|
cancellation_type:,
|
107
166
|
activity_id:,
|
167
|
+
arg_hints: arg_hints || defn_arg_hints,
|
168
|
+
result_hint: result_hint || defn_result_hint,
|
108
169
|
headers: {}
|
109
170
|
)
|
110
171
|
)
|
@@ -122,12 +183,26 @@ module Temporalio
|
|
122
183
|
@instance.info
|
123
184
|
end
|
124
185
|
|
186
|
+
def instance
|
187
|
+
@instance.instance
|
188
|
+
end
|
189
|
+
|
125
190
|
def initialize_continue_as_new_error(error)
|
126
191
|
@outbound.initialize_continue_as_new_error(
|
127
192
|
Temporalio::Worker::Interceptor::Workflow::InitializeContinueAsNewErrorInput.new(error:)
|
128
193
|
)
|
129
194
|
end
|
130
195
|
|
196
|
+
def io_enabled(&)
|
197
|
+
prev = @instance.io_enabled
|
198
|
+
@instance.io_enabled = true
|
199
|
+
begin
|
200
|
+
yield
|
201
|
+
ensure
|
202
|
+
@instance.io_enabled = prev
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
131
206
|
def logger
|
132
207
|
@instance.logger
|
133
208
|
end
|
@@ -187,6 +262,8 @@ module Temporalio
|
|
187
262
|
*args,
|
188
263
|
id:,
|
189
264
|
task_queue:,
|
265
|
+
static_summary:,
|
266
|
+
static_details:,
|
190
267
|
cancellation:,
|
191
268
|
cancellation_type:,
|
192
269
|
parent_close_policy:,
|
@@ -197,14 +274,21 @@ module Temporalio
|
|
197
274
|
retry_policy:,
|
198
275
|
cron_schedule:,
|
199
276
|
memo:,
|
200
|
-
search_attributes
|
277
|
+
search_attributes:,
|
278
|
+
priority:,
|
279
|
+
arg_hints:,
|
280
|
+
result_hint:
|
201
281
|
)
|
282
|
+
workflow, defn_arg_hints, defn_result_hint =
|
283
|
+
Workflow::Definition._workflow_type_and_hints_from_workflow_parameter(workflow)
|
202
284
|
@outbound.start_child_workflow(
|
203
285
|
Temporalio::Worker::Interceptor::Workflow::StartChildWorkflowInput.new(
|
204
286
|
workflow:,
|
205
287
|
args:,
|
206
288
|
id:,
|
207
289
|
task_queue:,
|
290
|
+
static_summary:,
|
291
|
+
static_details:,
|
208
292
|
cancellation:,
|
209
293
|
cancellation_type:,
|
210
294
|
parent_close_policy:,
|
@@ -216,11 +300,18 @@ module Temporalio
|
|
216
300
|
cron_schedule:,
|
217
301
|
memo:,
|
218
302
|
search_attributes:,
|
303
|
+
priority:,
|
304
|
+
arg_hints: arg_hints || defn_arg_hints,
|
305
|
+
result_hint: result_hint || defn_result_hint,
|
219
306
|
headers: {}
|
220
307
|
)
|
221
308
|
)
|
222
309
|
end
|
223
310
|
|
311
|
+
def storage
|
312
|
+
@storage ||= {}
|
313
|
+
end
|
314
|
+
|
224
315
|
def timeout(duration, exception_class, *exception_args, summary:, &)
|
225
316
|
raise 'Block required for timeout' unless block_given?
|
226
317
|
|
@@ -298,19 +389,22 @@ module Temporalio
|
|
298
389
|
@outbound = outbound
|
299
390
|
end
|
300
391
|
|
301
|
-
def _signal_child_workflow(id:, signal:, args:, cancellation:)
|
392
|
+
def _signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:)
|
393
|
+
signal, defn_arg_hints = Workflow::Definition::Signal._name_and_hints_from_parameter(signal)
|
302
394
|
@outbound.signal_child_workflow(
|
303
395
|
Temporalio::Worker::Interceptor::Workflow::SignalChildWorkflowInput.new(
|
304
396
|
id:,
|
305
397
|
signal:,
|
306
398
|
args:,
|
307
399
|
cancellation:,
|
400
|
+
arg_hints: arg_hints || defn_arg_hints,
|
308
401
|
headers: {}
|
309
402
|
)
|
310
403
|
)
|
311
404
|
end
|
312
405
|
|
313
|
-
def _signal_external_workflow(id:, run_id:, signal:, args:, cancellation:)
|
406
|
+
def _signal_external_workflow(id:, run_id:, signal:, args:, cancellation:, arg_hints:)
|
407
|
+
signal, defn_arg_hints = Workflow::Definition::Signal._name_and_hints_from_parameter(signal)
|
314
408
|
@outbound.signal_external_workflow(
|
315
409
|
Temporalio::Worker::Interceptor::Workflow::SignalExternalWorkflowInput.new(
|
316
410
|
id:,
|
@@ -318,6 +412,7 @@ module Temporalio
|
|
318
412
|
signal:,
|
319
413
|
args:,
|
320
414
|
cancellation:,
|
415
|
+
arg_hints: arg_hints || defn_arg_hints,
|
321
416
|
headers: {}
|
322
417
|
)
|
323
418
|
)
|
@@ -8,7 +8,8 @@ module Temporalio
|
|
8
8
|
class Details
|
9
9
|
attr_reader :namespace, :task_queue, :definition, :initial_activation, :logger, :metric_meter,
|
10
10
|
:payload_converter, :failure_converter, :interceptors, :disable_eager_activity_execution,
|
11
|
-
:illegal_calls, :workflow_failure_exception_types
|
11
|
+
:illegal_calls, :workflow_failure_exception_types, :unsafe_workflow_io_enabled,
|
12
|
+
:assert_valid_local_activity
|
12
13
|
|
13
14
|
def initialize(
|
14
15
|
namespace:,
|
@@ -22,7 +23,9 @@ module Temporalio
|
|
22
23
|
interceptors:,
|
23
24
|
disable_eager_activity_execution:,
|
24
25
|
illegal_calls:,
|
25
|
-
workflow_failure_exception_types
|
26
|
+
workflow_failure_exception_types:,
|
27
|
+
unsafe_workflow_io_enabled:,
|
28
|
+
assert_valid_local_activity:
|
26
29
|
)
|
27
30
|
@namespace = namespace
|
28
31
|
@task_queue = task_queue
|
@@ -36,6 +39,8 @@ module Temporalio
|
|
36
39
|
@disable_eager_activity_execution = disable_eager_activity_execution
|
37
40
|
@illegal_calls = illegal_calls
|
38
41
|
@workflow_failure_exception_types = workflow_failure_exception_types
|
42
|
+
@unsafe_workflow_io_enabled = unsafe_workflow_io_enabled
|
43
|
+
@assert_valid_local_activity = assert_valid_local_activity
|
39
44
|
end
|
40
45
|
end
|
41
46
|
end
|
@@ -18,8 +18,8 @@ module Temporalio
|
|
18
18
|
@instance = instance
|
19
19
|
end
|
20
20
|
|
21
|
-
def signal(signal, *args, cancellation: Workflow.cancellation)
|
22
|
-
@instance.context._signal_external_workflow(id:, run_id:, signal:, args:, cancellation:)
|
21
|
+
def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil)
|
22
|
+
@instance.context._signal_external_workflow(id:, run_id:, signal:, args:, cancellation:, arg_hints:)
|
23
23
|
end
|
24
24
|
|
25
25
|
def cancel
|