temporalio 0.3.0-x86_64-linux-musl → 0.4.0-x86_64-linux-musl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/Rakefile +1 -1
- data/lib/temporalio/activity/context.rb +7 -0
- data/lib/temporalio/activity/definition.rb +4 -1
- 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 +14 -5
- data/lib/temporalio/internal/worker/multi_runner.rb +2 -2
- data/lib/temporalio/internal/worker/workflow_instance/context.rb +53 -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 +6 -3
- 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 +32 -8
- 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/workflow_executor/thread_pool.rb +8 -3
- data/lib/temporalio/worker/workflow_replayer.rb +7 -0
- data/lib/temporalio/worker.rb +34 -0
- 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 +54 -8
- data/temporalio.gemspec +2 -1
- metadata +24 -4
@@ -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)
|
@@ -201,6 +203,7 @@ module Temporalio
|
|
201
203
|
|
202
204
|
# Run
|
203
205
|
activity = RunningActivity.new(
|
206
|
+
worker: @worker,
|
204
207
|
info:,
|
205
208
|
cancellation: Cancellation.new,
|
206
209
|
worker_shutdown_cancellation: @worker._worker_shutdown_cancellation,
|
@@ -211,7 +214,7 @@ module Temporalio
|
|
211
214
|
Activity::Context._current_executor&.set_activity_context(defn, activity)
|
212
215
|
set_running_activity(task_token, activity)
|
213
216
|
run_activity(defn, activity, input)
|
214
|
-
rescue Exception => e # rubocop:disable Lint/RescueException We are intending to catch everything here
|
217
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- We are intending to catch everything here
|
215
218
|
@scoped_logger.warn("Failed starting or sending completion for activity #{start.activity_type}")
|
216
219
|
@scoped_logger.warn(e)
|
217
220
|
# This means that the activity couldn't start or send completion (run
|
@@ -258,7 +261,7 @@ module Temporalio
|
|
258
261
|
result: @worker.options.client.data_converter.to_payload(result)
|
259
262
|
)
|
260
263
|
)
|
261
|
-
rescue Exception => e # rubocop:disable Lint/RescueException We are intending to catch everything here
|
264
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- We are intending to catch everything here
|
262
265
|
if e.is_a?(Activity::CompleteAsyncError)
|
263
266
|
# Wanting to complete async
|
264
267
|
@scoped_logger.debug('Completing activity asynchronously')
|
@@ -299,6 +302,7 @@ module Temporalio
|
|
299
302
|
attr_accessor :instance, :_outbound_impl, :_server_requested_cancel
|
300
303
|
|
301
304
|
def initialize( # rubocop:disable Lint/MissingSuper
|
305
|
+
worker:,
|
302
306
|
info:,
|
303
307
|
cancellation:,
|
304
308
|
worker_shutdown_cancellation:,
|
@@ -306,6 +310,7 @@ module Temporalio
|
|
306
310
|
logger:,
|
307
311
|
runtime_metric_meter:
|
308
312
|
)
|
313
|
+
@worker = worker
|
309
314
|
@info = info
|
310
315
|
@cancellation = cancellation
|
311
316
|
@worker_shutdown_cancellation = worker_shutdown_cancellation
|
@@ -334,6 +339,10 @@ module Temporalio
|
|
334
339
|
}
|
335
340
|
)
|
336
341
|
end
|
342
|
+
|
343
|
+
def client
|
344
|
+
@worker.client
|
345
|
+
end
|
337
346
|
end
|
338
347
|
|
339
348
|
class InboundImplementation < Temporalio::Worker::Interceptor::Activity::Inbound
|
@@ -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
|
@@ -32,6 +32,16 @@ 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
|
+
|
35
45
|
def current_history_length
|
36
46
|
@instance.current_history_length
|
37
47
|
end
|
@@ -52,6 +62,7 @@ module Temporalio
|
|
52
62
|
activity,
|
53
63
|
*args,
|
54
64
|
task_queue:,
|
65
|
+
summary:,
|
55
66
|
schedule_to_close_timeout:,
|
56
67
|
schedule_to_start_timeout:,
|
57
68
|
start_to_close_timeout:,
|
@@ -62,11 +73,22 @@ module Temporalio
|
|
62
73
|
activity_id:,
|
63
74
|
disable_eager_execution:
|
64
75
|
)
|
76
|
+
activity = case activity
|
77
|
+
when Class
|
78
|
+
Activity::Definition::Info.from_activity(activity).name&.to_s
|
79
|
+
when Symbol, String
|
80
|
+
activity.to_s
|
81
|
+
else
|
82
|
+
raise ArgumentError, 'Activity must be a definition class, or a symbol/string'
|
83
|
+
end
|
84
|
+
raise 'Cannot invoke dynamic activities' unless activity
|
85
|
+
|
65
86
|
@outbound.execute_activity(
|
66
87
|
Temporalio::Worker::Interceptor::Workflow::ExecuteActivityInput.new(
|
67
88
|
activity:,
|
68
89
|
args:,
|
69
90
|
task_queue: task_queue || info.task_queue,
|
91
|
+
summary:,
|
70
92
|
schedule_to_close_timeout:,
|
71
93
|
schedule_to_start_timeout:,
|
72
94
|
start_to_close_timeout:,
|
@@ -93,6 +115,16 @@ module Temporalio
|
|
93
115
|
cancellation_type:,
|
94
116
|
activity_id:
|
95
117
|
)
|
118
|
+
activity = case activity
|
119
|
+
when Class
|
120
|
+
Activity::Definition::Info.from_activity(activity).name&.to_s
|
121
|
+
when Symbol, String
|
122
|
+
activity.to_s
|
123
|
+
else
|
124
|
+
raise ArgumentError, 'Activity must be a definition class, or a symbol/string'
|
125
|
+
end
|
126
|
+
raise 'Cannot invoke dynamic activities' unless activity
|
127
|
+
|
96
128
|
@outbound.execute_local_activity(
|
97
129
|
Temporalio::Worker::Interceptor::Workflow::ExecuteLocalActivityInput.new(
|
98
130
|
activity:,
|
@@ -132,6 +164,16 @@ module Temporalio
|
|
132
164
|
)
|
133
165
|
end
|
134
166
|
|
167
|
+
def io_enabled(&)
|
168
|
+
prev = @instance.io_enabled
|
169
|
+
@instance.io_enabled = true
|
170
|
+
begin
|
171
|
+
yield
|
172
|
+
ensure
|
173
|
+
@instance.io_enabled = prev
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
135
177
|
def logger
|
136
178
|
@instance.logger
|
137
179
|
end
|
@@ -191,6 +233,8 @@ module Temporalio
|
|
191
233
|
*args,
|
192
234
|
id:,
|
193
235
|
task_queue:,
|
236
|
+
static_summary:,
|
237
|
+
static_details:,
|
194
238
|
cancellation:,
|
195
239
|
cancellation_type:,
|
196
240
|
parent_close_policy:,
|
@@ -205,10 +249,12 @@ module Temporalio
|
|
205
249
|
)
|
206
250
|
@outbound.start_child_workflow(
|
207
251
|
Temporalio::Worker::Interceptor::Workflow::StartChildWorkflowInput.new(
|
208
|
-
workflow
|
252
|
+
workflow: Workflow::Definition._workflow_type_from_workflow_parameter(workflow),
|
209
253
|
args:,
|
210
254
|
id:,
|
211
255
|
task_queue:,
|
256
|
+
static_summary:,
|
257
|
+
static_details:,
|
212
258
|
cancellation:,
|
213
259
|
cancellation_type:,
|
214
260
|
parent_close_policy:,
|
@@ -225,6 +271,10 @@ module Temporalio
|
|
225
271
|
)
|
226
272
|
end
|
227
273
|
|
274
|
+
def storage
|
275
|
+
@storage ||= {}
|
276
|
+
end
|
277
|
+
|
228
278
|
def timeout(duration, exception_class, *exception_args, summary:, &)
|
229
279
|
raise 'Block required for timeout' unless block_given?
|
230
280
|
|
@@ -306,7 +356,7 @@ module Temporalio
|
|
306
356
|
@outbound.signal_child_workflow(
|
307
357
|
Temporalio::Worker::Interceptor::Workflow::SignalChildWorkflowInput.new(
|
308
358
|
id:,
|
309
|
-
signal
|
359
|
+
signal: Workflow::Definition::Signal._name_from_parameter(signal),
|
310
360
|
args:,
|
311
361
|
cancellation:,
|
312
362
|
headers: {}
|
@@ -319,7 +369,7 @@ module Temporalio
|
|
319
369
|
Temporalio::Worker::Interceptor::Workflow::SignalExternalWorkflowInput.new(
|
320
370
|
id:,
|
321
371
|
run_id:,
|
322
|
-
signal
|
372
|
+
signal: Workflow::Definition::Signal._name_from_parameter(signal),
|
323
373
|
args:,
|
324
374
|
cancellation:,
|
325
375
|
headers: {}
|
@@ -8,7 +8,7 @@ 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
12
|
|
13
13
|
def initialize(
|
14
14
|
namespace:,
|
@@ -22,7 +22,8 @@ module Temporalio
|
|
22
22
|
interceptors:,
|
23
23
|
disable_eager_activity_execution:,
|
24
24
|
illegal_calls:,
|
25
|
-
workflow_failure_exception_types
|
25
|
+
workflow_failure_exception_types:,
|
26
|
+
unsafe_workflow_io_enabled:
|
26
27
|
)
|
27
28
|
@namespace = namespace
|
28
29
|
@task_queue = task_queue
|
@@ -36,6 +37,7 @@ module Temporalio
|
|
36
37
|
@disable_eager_activity_execution = disable_eager_activity_execution
|
37
38
|
@illegal_calls = illegal_calls
|
38
39
|
@workflow_failure_exception_types = workflow_failure_exception_types
|
40
|
+
@unsafe_workflow_io_enabled = unsafe_workflow_io_enabled
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
@@ -56,16 +56,6 @@ module Temporalio
|
|
56
56
|
raise ArgumentError, 'Activity must have schedule_to_close_timeout or start_to_close_timeout'
|
57
57
|
end
|
58
58
|
|
59
|
-
activity_type = case input.activity
|
60
|
-
when Class
|
61
|
-
Activity::Definition::Info.from_activity(input.activity).name
|
62
|
-
when Symbol, String
|
63
|
-
input.activity.to_s
|
64
|
-
else
|
65
|
-
raise ArgumentError, 'Activity must be a definition class, or a symbol/string'
|
66
|
-
end
|
67
|
-
raise 'Cannot invoke dynamic activities' unless activity_type
|
68
|
-
|
69
59
|
execute_activity_with_local_backoffs(local: false, cancellation: input.cancellation) do
|
70
60
|
seq = (@activity_counter += 1)
|
71
61
|
@instance.add_command(
|
@@ -73,7 +63,7 @@ module Temporalio
|
|
73
63
|
schedule_activity: Bridge::Api::WorkflowCommands::ScheduleActivity.new(
|
74
64
|
seq:,
|
75
65
|
activity_id: input.activity_id || seq.to_s,
|
76
|
-
activity_type
|
66
|
+
activity_type: input.activity,
|
77
67
|
task_queue: input.task_queue,
|
78
68
|
headers: ProtoUtils.headers_to_proto_hash(input.headers, @instance.payload_converter),
|
79
69
|
arguments: ProtoUtils.convert_to_payload_array(@instance.payload_converter, input.args),
|
@@ -84,7 +74,8 @@ module Temporalio
|
|
84
74
|
retry_policy: input.retry_policy&._to_proto,
|
85
75
|
cancellation_type: input.cancellation_type,
|
86
76
|
do_not_eagerly_execute: input.disable_eager_execution
|
87
|
-
)
|
77
|
+
),
|
78
|
+
user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter)
|
88
79
|
)
|
89
80
|
)
|
90
81
|
seq
|
@@ -96,16 +87,6 @@ module Temporalio
|
|
96
87
|
raise ArgumentError, 'Activity must have schedule_to_close_timeout or start_to_close_timeout'
|
97
88
|
end
|
98
89
|
|
99
|
-
activity_type = case input.activity
|
100
|
-
when Class
|
101
|
-
Activity::Definition::Info.from_activity(input.activity).name
|
102
|
-
when Symbol, String
|
103
|
-
input.activity.to_s
|
104
|
-
else
|
105
|
-
raise ArgumentError, 'Activity must be a definition class, or a symbol/string'
|
106
|
-
end
|
107
|
-
raise 'Cannot invoke dynamic activities' unless activity_type
|
108
|
-
|
109
90
|
execute_activity_with_local_backoffs(local: true, cancellation: input.cancellation) do |do_backoff|
|
110
91
|
seq = (@activity_counter += 1)
|
111
92
|
@instance.add_command(
|
@@ -113,7 +94,7 @@ module Temporalio
|
|
113
94
|
schedule_local_activity: Bridge::Api::WorkflowCommands::ScheduleLocalActivity.new(
|
114
95
|
seq:,
|
115
96
|
activity_id: input.activity_id || seq.to_s,
|
116
|
-
activity_type
|
97
|
+
activity_type: input.activity,
|
117
98
|
headers: ProtoUtils.headers_to_proto_hash(input.headers, @instance.payload_converter),
|
118
99
|
arguments: ProtoUtils.convert_to_payload_array(@instance.payload_converter, input.args),
|
119
100
|
schedule_to_close_timeout: ProtoUtils.seconds_to_duration(input.schedule_to_close_timeout),
|
@@ -232,7 +213,7 @@ module Temporalio
|
|
232
213
|
seq = (@external_signal_counter += 1)
|
233
214
|
cmd = Bridge::Api::WorkflowCommands::SignalExternalWorkflowExecution.new(
|
234
215
|
seq:,
|
235
|
-
signal_name:
|
216
|
+
signal_name: signal,
|
236
217
|
args: ProtoUtils.convert_to_payload_array(@instance.payload_converter, args),
|
237
218
|
headers: ProtoUtils.headers_to_proto_hash(headers, @instance.payload_converter)
|
238
219
|
)
|
@@ -300,7 +281,8 @@ module Temporalio
|
|
300
281
|
start_timer: Bridge::Api::WorkflowCommands::StartTimer.new(
|
301
282
|
seq:,
|
302
283
|
start_to_fire_timeout: ProtoUtils.seconds_to_duration(duration)
|
303
|
-
)
|
284
|
+
),
|
285
|
+
user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter)
|
304
286
|
)
|
305
287
|
)
|
306
288
|
@instance.pending_timers[seq] = Fiber.current
|
@@ -340,7 +322,7 @@ module Temporalio
|
|
340
322
|
seq:,
|
341
323
|
namespace: @instance.info.namespace,
|
342
324
|
workflow_id: input.id,
|
343
|
-
workflow_type:
|
325
|
+
workflow_type: input.workflow,
|
344
326
|
task_queue: input.task_queue,
|
345
327
|
input: ProtoUtils.convert_to_payload_array(@instance.payload_converter, input.args),
|
346
328
|
workflow_execution_timeout: ProtoUtils.seconds_to_duration(input.execution_timeout),
|
@@ -354,6 +336,9 @@ module Temporalio
|
|
354
336
|
memo: ProtoUtils.memo_to_proto_hash(input.memo, @instance.payload_converter),
|
355
337
|
search_attributes: input.search_attributes&._to_proto_hash,
|
356
338
|
cancellation_type: input.cancellation_type
|
339
|
+
),
|
340
|
+
user_metadata: ProtoUtils.to_user_metadata(
|
341
|
+
input.static_summary, input.static_details, @instance.payload_converter
|
357
342
|
)
|
358
343
|
)
|
359
344
|
)
|
@@ -137,8 +137,28 @@ module Temporalio
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def io_wait(io, events, timeout)
|
140
|
-
#
|
141
|
-
|
140
|
+
# Do not allow if IO disabled
|
141
|
+
unless @instance.io_enabled
|
142
|
+
raise Workflow::NondeterminismError,
|
143
|
+
'Cannot perform IO from inside a workflow. If this is known to be safe, ' \
|
144
|
+
'the code can be run in a Temporalio::Workflow::Unsafe.io_enabled block.'
|
145
|
+
end
|
146
|
+
|
147
|
+
# Use regular Ruby behavior of blocking this thread. There is no Ruby implementation of io_wait we can just
|
148
|
+
# delegate to at this time (or default scheduler or anything like that), so we had to implement this
|
149
|
+
# ourselves.
|
150
|
+
readers = events.nobits?(IO::READABLE) ? nil : [io]
|
151
|
+
writers = events.nobits?(IO::WRITABLE) ? nil : [io]
|
152
|
+
priority = events.nobits?(IO::PRIORITY) ? nil : [io]
|
153
|
+
ready = IO.select(readers, writers, priority, timeout) # steep:ignore
|
154
|
+
|
155
|
+
result = 0
|
156
|
+
unless ready.nil?
|
157
|
+
result |= IO::READABLE if ready[0]&.include?(io)
|
158
|
+
result |= IO::WRITABLE if ready[1]&.include?(io)
|
159
|
+
result |= IO::PRIORITY if ready[2]&.include?(io)
|
160
|
+
end
|
161
|
+
result
|
142
162
|
end
|
143
163
|
|
144
164
|
def kernel_sleep(duration = nil)
|
@@ -4,6 +4,7 @@ require 'json'
|
|
4
4
|
require 'temporalio'
|
5
5
|
require 'temporalio/activity/definition'
|
6
6
|
require 'temporalio/api'
|
7
|
+
require 'temporalio/converters/payload_converter'
|
7
8
|
require 'temporalio/converters/raw_value'
|
8
9
|
require 'temporalio/error'
|
9
10
|
require 'temporalio/internal/bridge/api'
|
@@ -56,6 +57,7 @@ module Temporalio
|
|
56
57
|
:failure_converter, :cancellation, :continue_as_new_suggested, :current_history_length,
|
57
58
|
:current_history_size, :replaying, :random, :signal_handlers, :query_handlers, :update_handlers,
|
58
59
|
:context_frozen
|
60
|
+
attr_accessor :io_enabled, :current_details
|
59
61
|
|
60
62
|
def initialize(details)
|
61
63
|
# Initialize general state
|
@@ -66,6 +68,7 @@ module Temporalio
|
|
66
68
|
@logger = ReplaySafeLogger.new(logger: details.logger, instance: self)
|
67
69
|
@logger.scoped_values_getter = proc { scoped_logger_info }
|
68
70
|
@runtime_metric_meter = details.metric_meter
|
71
|
+
@io_enabled = details.unsafe_workflow_io_enabled
|
69
72
|
@scheduler = Scheduler.new(self)
|
70
73
|
@payload_converter = details.payload_converter
|
71
74
|
@failure_converter = details.failure_converter
|
@@ -115,6 +118,7 @@ module Temporalio
|
|
115
118
|
continued_run_id: ProtoUtils.string_or(@init_job.continued_from_execution_run_id),
|
116
119
|
cron_schedule: ProtoUtils.string_or(@init_job.cron_schedule),
|
117
120
|
execution_timeout: ProtoUtils.duration_to_seconds(@init_job.workflow_execution_timeout),
|
121
|
+
headers: ProtoUtils.headers_from_proto_map(@init_job.headers, @payload_converter) || {},
|
118
122
|
last_failure: if @init_job.continued_failure
|
119
123
|
@failure_converter.from_failure(@init_job.continued_failure, @payload_converter)
|
120
124
|
end,
|
@@ -130,6 +134,12 @@ module Temporalio
|
|
130
134
|
)
|
131
135
|
end,
|
132
136
|
retry_policy: (RetryPolicy._from_proto(@init_job.retry_policy) if @init_job.retry_policy),
|
137
|
+
root: if @init_job.root_workflow
|
138
|
+
Workflow::Info::RootInfo.new(
|
139
|
+
run_id: @init_job.root_workflow.run_id,
|
140
|
+
workflow_id: @init_job.root_workflow.workflow_id
|
141
|
+
)
|
142
|
+
end,
|
133
143
|
run_id: details.initial_activation.run_id,
|
134
144
|
run_timeout: ProtoUtils.duration_to_seconds(@init_job.workflow_run_timeout),
|
135
145
|
start_time: ProtoUtils.timestamp_to_time(details.initial_activation.timestamp) || raise,
|
@@ -348,7 +358,10 @@ module Temporalio
|
|
348
358
|
end
|
349
359
|
|
350
360
|
def apply_signal(job)
|
351
|
-
|
361
|
+
# Get signal definition, falling back to dynamic if not present and not reserved
|
362
|
+
defn = signal_handlers[job.signal_name]
|
363
|
+
defn = signal_handlers[nil] if !defn && !Internal::ProtoUtils.reserved_name?(job.signal_name)
|
364
|
+
|
352
365
|
handler_exec =
|
353
366
|
if defn
|
354
367
|
HandlerExecution.new(name: job.signal_name, update_id: nil, unfinished_policy: defn.unfinished_policy)
|
@@ -381,37 +394,41 @@ module Temporalio
|
|
381
394
|
end
|
382
395
|
|
383
396
|
def apply_query(job)
|
384
|
-
# TODO(cretz): __temporal_workflow_metadata
|
385
|
-
defn = case job.query_type
|
386
|
-
when '__stack_trace'
|
387
|
-
Workflow::Definition::Query.new(
|
388
|
-
name: '__stack_trace',
|
389
|
-
to_invoke: proc { scheduler.stack_trace }
|
390
|
-
)
|
391
|
-
else
|
392
|
-
query_handlers[job.query_type] || query_handlers[nil]
|
393
|
-
end
|
394
397
|
schedule do
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
398
|
+
# If it's a built-in, run it without interceptors, otherwise do normal behavior
|
399
|
+
result = if job.query_type == '__stack_trace'
|
400
|
+
# Use raw value built from default converter because we don't want to use user-conversion
|
401
|
+
Converters::RawValue.new(Converters::PayloadConverter.default.to_payload(scheduler.stack_trace))
|
402
|
+
elsif job.query_type == '__temporal_workflow_metadata'
|
403
|
+
# Use raw value built from default converter because we don't want to use user-conversion
|
404
|
+
Converters::RawValue.new(Converters::PayloadConverter.default.to_payload(workflow_metadata))
|
405
|
+
else
|
406
|
+
# Get query definition, falling back to dynamic if not present and not reserved
|
407
|
+
defn = query_handlers[job.query_type]
|
408
|
+
defn = query_handlers[nil] if !defn && !Internal::ProtoUtils.reserved_name?(job.query_type)
|
409
|
+
|
410
|
+
unless defn
|
411
|
+
raise "Query handler for #{job.query_type} expected but not found, " \
|
412
|
+
"known queries: [#{query_handlers.keys.compact.sort.join(', ')}]"
|
413
|
+
end
|
414
|
+
|
415
|
+
with_context_frozen do
|
416
|
+
@inbound.handle_query(
|
417
|
+
Temporalio::Worker::Interceptor::Workflow::HandleQueryInput.new(
|
418
|
+
id: job.query_id,
|
419
|
+
query: job.query_type,
|
420
|
+
args: begin
|
421
|
+
convert_handler_args(payload_array: job.arguments, defn:)
|
422
|
+
rescue StandardError => e
|
423
|
+
raise "Failed converting query input arguments: #{e}"
|
424
|
+
end,
|
425
|
+
definition: defn,
|
426
|
+
headers: ProtoUtils.headers_from_proto_map(job.headers, @payload_converter) || {}
|
427
|
+
)
|
428
|
+
)
|
429
|
+
end
|
430
|
+
end
|
399
431
|
|
400
|
-
result = with_context_frozen do
|
401
|
-
@inbound.handle_query(
|
402
|
-
Temporalio::Worker::Interceptor::Workflow::HandleQueryInput.new(
|
403
|
-
id: job.query_id,
|
404
|
-
query: job.query_type,
|
405
|
-
args: begin
|
406
|
-
convert_handler_args(payload_array: job.arguments, defn:)
|
407
|
-
rescue StandardError => e
|
408
|
-
raise "Failed converting query input arguments: #{e}"
|
409
|
-
end,
|
410
|
-
definition: defn,
|
411
|
-
headers: ProtoUtils.headers_from_proto_map(job.headers, @payload_converter) || {}
|
412
|
-
)
|
413
|
-
)
|
414
|
-
end
|
415
432
|
add_command(
|
416
433
|
Bridge::Api::WorkflowCommands::WorkflowCommand.new(
|
417
434
|
respond_to_query: Bridge::Api::WorkflowCommands::QueryResult.new(
|
@@ -435,7 +452,10 @@ module Temporalio
|
|
435
452
|
end
|
436
453
|
|
437
454
|
def apply_update(job)
|
438
|
-
|
455
|
+
# Get update definition, falling back to dynamic if not present and not reserved
|
456
|
+
defn = update_handlers[job.name]
|
457
|
+
defn = update_handlers[nil] if !defn && !Internal::ProtoUtils.reserved_name?(job.name)
|
458
|
+
|
439
459
|
handler_exec =
|
440
460
|
(HandlerExecution.new(name: job.name, update_id: job.id, unfinished_policy: defn.unfinished_policy) if defn)
|
441
461
|
schedule(handler_exec:) do
|
@@ -527,7 +547,7 @@ module Temporalio
|
|
527
547
|
result = @inbound.execute(
|
528
548
|
Temporalio::Worker::Interceptor::Workflow::ExecuteInput.new(
|
529
549
|
args: @workflow_arguments,
|
530
|
-
headers:
|
550
|
+
headers: @info.headers
|
531
551
|
)
|
532
552
|
)
|
533
553
|
add_command(
|
@@ -671,6 +691,30 @@ module Temporalio
|
|
671
691
|
end
|
672
692
|
end
|
673
693
|
|
694
|
+
def workflow_metadata
|
695
|
+
Temporalio::Api::Sdk::V1::WorkflowMetadata.new(
|
696
|
+
definition: Temporalio::Api::Sdk::V1::WorkflowDefinition.new(
|
697
|
+
type: info.workflow_type,
|
698
|
+
query_definitions: query_handlers.values.map do |defn|
|
699
|
+
Temporalio::Api::Sdk::V1::WorkflowInteractionDefinition.new(
|
700
|
+
name: defn.name || '', description: defn.description || ''
|
701
|
+
)
|
702
|
+
end,
|
703
|
+
signal_definitions: signal_handlers.values.map do |defn|
|
704
|
+
Temporalio::Api::Sdk::V1::WorkflowInteractionDefinition.new(
|
705
|
+
name: defn.name || '', description: defn.description || ''
|
706
|
+
)
|
707
|
+
end,
|
708
|
+
update_definitions: update_handlers.values.map do |defn|
|
709
|
+
Temporalio::Api::Sdk::V1::WorkflowInteractionDefinition.new(
|
710
|
+
name: defn.name || '', description: defn.description || ''
|
711
|
+
)
|
712
|
+
end
|
713
|
+
),
|
714
|
+
current_details: current_details || ''
|
715
|
+
)
|
716
|
+
end
|
717
|
+
|
674
718
|
def scoped_logger_info
|
675
719
|
@scoped_logger_info ||= {
|
676
720
|
attempt: info.attempt,
|
@@ -67,6 +67,7 @@ module Temporalio
|
|
67
67
|
illegal_workflow_calls:,
|
68
68
|
workflow_failure_exception_types:,
|
69
69
|
workflow_payload_codec_thread_pool:,
|
70
|
+
unsafe_workflow_io_enabled:,
|
70
71
|
debug_mode:,
|
71
72
|
on_eviction: nil
|
72
73
|
)
|
@@ -109,7 +110,8 @@ module Temporalio
|
|
109
110
|
end
|
110
111
|
|
111
112
|
t
|
112
|
-
end.freeze
|
113
|
+
end.freeze,
|
114
|
+
unsafe_workflow_io_enabled:
|
113
115
|
)
|
114
116
|
@state.on_eviction = on_eviction if on_eviction
|
115
117
|
|
@@ -184,14 +186,14 @@ module Temporalio
|
|
184
186
|
class State
|
185
187
|
attr_reader :workflow_definitions, :bridge_worker, :logger, :metric_meter, :data_converter, :deadlock_timeout,
|
186
188
|
:illegal_calls, :namespace, :task_queue, :disable_eager_activity_execution,
|
187
|
-
:workflow_interceptors, :workflow_failure_exception_types
|
189
|
+
:workflow_interceptors, :workflow_failure_exception_types, :unsafe_workflow_io_enabled
|
188
190
|
|
189
191
|
attr_writer :on_eviction
|
190
192
|
|
191
193
|
def initialize(
|
192
194
|
workflow_definitions:, bridge_worker:, logger:, metric_meter:, data_converter:, deadlock_timeout:,
|
193
195
|
illegal_calls:, namespace:, task_queue:, disable_eager_activity_execution:,
|
194
|
-
workflow_interceptors:, workflow_failure_exception_types:
|
196
|
+
workflow_interceptors:, workflow_failure_exception_types:, unsafe_workflow_io_enabled:
|
195
197
|
)
|
196
198
|
@workflow_definitions = workflow_definitions
|
197
199
|
@bridge_worker = bridge_worker
|
@@ -205,6 +207,7 @@ module Temporalio
|
|
205
207
|
@disable_eager_activity_execution = disable_eager_activity_execution
|
206
208
|
@workflow_interceptors = workflow_interceptors
|
207
209
|
@workflow_failure_exception_types = workflow_failure_exception_types
|
210
|
+
@unsafe_workflow_io_enabled = unsafe_workflow_io_enabled
|
208
211
|
|
209
212
|
@running_workflows = {}
|
210
213
|
@running_workflows_mutex = Mutex.new
|