temporalio 0.5.0-aarch64-linux → 1.0.0-aarch64-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/lib/temporalio/activity/info.rb +5 -0
- data/lib/temporalio/api/batch/v1/message.rb +4 -1
- data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +12 -1
- data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +1 -1
- data/lib/temporalio/api/cloud/connectivityrule/v1/message.rb +29 -0
- data/lib/temporalio/api/cloud/identity/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/namespace/v1/message.rb +2 -1
- data/lib/temporalio/api/cloud/operation/v1/message.rb +1 -1
- data/lib/temporalio/api/common/v1/message.rb +2 -1
- data/lib/temporalio/api/enums/v1/batch_operation.rb +1 -1
- data/lib/temporalio/api/enums/v1/task_queue.rb +2 -1
- data/lib/temporalio/api/history/v1/message.rb +1 -1
- data/lib/temporalio/api/payload_visitor.rb +19 -1
- data/lib/temporalio/api/sdk/v1/worker_config.rb +23 -0
- data/lib/temporalio/api/taskqueue/v1/message.rb +5 -1
- data/lib/temporalio/api/worker/v1/message.rb +2 -1
- data/lib/temporalio/api/workflowservice/v1/request_response.rb +10 -1
- data/lib/temporalio/api/workflowservice/v1/service.rb +1 -1
- data/lib/temporalio/cancellation.rb +16 -12
- data/lib/temporalio/client/async_activity_handle.rb +1 -0
- data/lib/temporalio/client/connection/cloud_service.rb +75 -0
- data/lib/temporalio/client/connection/workflow_service.rb +45 -0
- data/lib/temporalio/client/connection.rb +2 -1
- data/lib/temporalio/contrib/open_telemetry.rb +9 -13
- data/lib/temporalio/converters/payload_converter/json_plain.rb +22 -5
- data/lib/temporalio/env_config.rb +343 -0
- data/lib/temporalio/error.rb +5 -1
- 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/workflow_activation/workflow_activation.rb +1 -1
- data/lib/temporalio/internal/bridge/worker.rb +50 -0
- data/lib/temporalio/internal/client/implementation.rb +7 -2
- data/lib/temporalio/internal/worker/activity_worker.rb +1 -0
- data/lib/temporalio/internal/worker/workflow_instance/context.rb +7 -4
- data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +2 -0
- data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +18 -11
- data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +6 -5
- data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +5 -2
- data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +10 -4
- data/lib/temporalio/internal/worker/workflow_instance.rb +77 -80
- data/lib/temporalio/priority.rb +47 -6
- data/lib/temporalio/scoped_logger.rb +1 -1
- data/lib/temporalio/testing/activity_environment.rb +1 -0
- data/lib/temporalio/version.rb +1 -1
- data/lib/temporalio/worker/illegal_workflow_call_validator.rb +9 -0
- data/lib/temporalio/worker/interceptor.rb +1 -0
- data/lib/temporalio/worker/tuner.rb +185 -16
- data/lib/temporalio/worker.rb +10 -1
- data/lib/temporalio/workflow/definition.rb +4 -6
- data/lib/temporalio/workflow/info.rb +3 -0
- data/lib/temporalio/workflow.rb +80 -6
- metadata +5 -2
@@ -40,6 +40,7 @@ module Temporalio
|
|
40
40
|
TunerSlotSupplierOptions = Struct.new(
|
41
41
|
:fixed_size,
|
42
42
|
:resource_based,
|
43
|
+
:custom,
|
43
44
|
keyword_init: true
|
44
45
|
)
|
45
46
|
|
@@ -103,6 +104,55 @@ module Temporalio
|
|
103
104
|
# TODO(cretz): Log error on this somehow?
|
104
105
|
async_complete_activity_task(proto.to_proto, queue)
|
105
106
|
end
|
107
|
+
|
108
|
+
class CustomSlotSupplier
|
109
|
+
def initialize(slot_supplier:, thread_pool:)
|
110
|
+
@slot_supplier = slot_supplier
|
111
|
+
@thread_pool = thread_pool
|
112
|
+
end
|
113
|
+
|
114
|
+
def reserve_slot(context, cancellation, &block)
|
115
|
+
run_user_code do
|
116
|
+
@slot_supplier.reserve_slot(context, cancellation) { |v| block.call(v) }
|
117
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
118
|
+
block.call(e)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def try_reserve_slot(context, &block)
|
123
|
+
run_user_code do
|
124
|
+
block.call(@slot_supplier.try_reserve_slot(context))
|
125
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
126
|
+
block.call(e)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def mark_slot_used(context, &block)
|
131
|
+
run_user_code do
|
132
|
+
block.call(@slot_supplier.mark_slot_used(context))
|
133
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
134
|
+
block.call(e)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def release_slot(context, &block)
|
139
|
+
run_user_code do
|
140
|
+
block.call(@slot_supplier.release_slot(context))
|
141
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
142
|
+
block.call(e)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def run_user_code(&)
|
149
|
+
if @thread_pool
|
150
|
+
@thread_pool.execute(&)
|
151
|
+
else
|
152
|
+
yield
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
106
156
|
end
|
107
157
|
end
|
108
158
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'google/protobuf/well_known_types'
|
4
4
|
require 'securerandom'
|
5
|
+
require 'temporalio/activity'
|
5
6
|
require 'temporalio/api'
|
6
7
|
require 'temporalio/client/activity_id_reference'
|
7
8
|
require 'temporalio/client/async_activity_handle'
|
@@ -829,9 +830,13 @@ module Temporalio
|
|
829
830
|
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
830
831
|
)
|
831
832
|
end
|
832
|
-
|
833
|
+
return unless resp.cancel_requested || resp.activity_paused || resp.activity_reset
|
833
834
|
|
834
|
-
|
835
|
+
raise Error::AsyncActivityCanceledError, Activity::CancellationDetails.new(
|
836
|
+
cancel_requested: resp.cancel_requested,
|
837
|
+
paused: resp.activity_paused,
|
838
|
+
reset: resp.activity_reset
|
839
|
+
)
|
835
840
|
end
|
836
841
|
|
837
842
|
def complete_async_activity(input)
|
@@ -185,6 +185,7 @@ module Temporalio
|
|
185
185
|
payloads = codec.decode(payloads) if codec
|
186
186
|
payloads.map { |p| Temporalio::Converters::RawValue.new(p) }
|
187
187
|
end,
|
188
|
+
retry_policy: (RetryPolicy._from_proto(start.retry_policy) if start.retry_policy),
|
188
189
|
schedule_to_close_timeout: Internal::ProtoUtils.duration_to_seconds(start.schedule_to_close_timeout),
|
189
190
|
scheduled_time: Internal::ProtoUtils.timestamp_to_time(start.scheduled_time) || raise, # Never nil
|
190
191
|
start_to_close_timeout: Internal::ProtoUtils.duration_to_seconds(start.start_to_close_timeout),
|
@@ -63,12 +63,13 @@ module Temporalio
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def durable_scheduler_disabled(&)
|
66
|
-
prev = Fiber.
|
67
|
-
|
68
|
-
|
66
|
+
prev = Fiber.scheduler
|
67
|
+
# Imply illegal call tracing disabled
|
68
|
+
illegal_call_tracing_disabled do
|
69
|
+
Fiber.set_scheduler(nil)
|
69
70
|
yield
|
70
71
|
ensure
|
71
|
-
|
72
|
+
Fiber.set_scheduler(prev)
|
72
73
|
end
|
73
74
|
end
|
74
75
|
|
@@ -129,6 +130,7 @@ module Temporalio
|
|
129
130
|
def execute_local_activity(
|
130
131
|
activity,
|
131
132
|
*args,
|
133
|
+
summary:,
|
132
134
|
schedule_to_close_timeout:,
|
133
135
|
schedule_to_start_timeout:,
|
134
136
|
start_to_close_timeout:,
|
@@ -156,6 +158,7 @@ module Temporalio
|
|
156
158
|
Temporalio::Worker::Interceptor::Workflow::ExecuteLocalActivityInput.new(
|
157
159
|
activity:,
|
158
160
|
args:,
|
161
|
+
summary:,
|
159
162
|
schedule_to_close_timeout:,
|
160
163
|
schedule_to_start_timeout:,
|
161
164
|
start_to_close_timeout:,
|
@@ -16,7 +16,7 @@ module Temporalio
|
|
16
16
|
# @type var fixed_val: :all | Worker::IllegalWorkflowCallValidator | Hash[Symbol, TrueClass | Worker::IllegalWorkflowCallValidator] # rubocop:disable Layout/LineLength
|
17
17
|
fixed_val = case val
|
18
18
|
when Temporalio::Worker::IllegalWorkflowCallValidator
|
19
|
-
if
|
19
|
+
if val.method_name
|
20
20
|
raise ArgumentError,
|
21
21
|
'Top level IllegalWorkflowCallValidator instances cannot have method name'
|
22
22
|
end
|
@@ -84,7 +84,7 @@ module Temporalio
|
|
84
84
|
when :all
|
85
85
|
''
|
86
86
|
when Temporalio::Worker::IllegalWorkflowCallValidator
|
87
|
-
|
87
|
+
disable_temporarily do
|
88
88
|
vals.block.call(Temporalio::Worker::IllegalWorkflowCallValidator::CallInfo.new(
|
89
89
|
class_name:, method_name: tp.callee_id, trace_point: tp
|
90
90
|
))
|
@@ -98,7 +98,7 @@ module Temporalio
|
|
98
98
|
when true
|
99
99
|
''
|
100
100
|
when Temporalio::Worker::IllegalWorkflowCallValidator
|
101
|
-
|
101
|
+
disable_temporarily do
|
102
102
|
per_method.block.call(Temporalio::Worker::IllegalWorkflowCallValidator::CallInfo.new(
|
103
103
|
class_name:, method_name: tp.callee_id, trace_point: tp
|
104
104
|
))
|
@@ -118,8 +118,11 @@ module Temporalio
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def enable(&block)
|
121
|
-
# We've seen leaking issues in Ruby 3.2 where
|
122
|
-
# that it was not started on. So we will check
|
121
|
+
# This is not reentrant and not expected to be called as such. We've seen leaking issues in Ruby 3.2 where
|
122
|
+
# the TracePoint inadvertently remains enabled even for threads that it was not started on. So we will check
|
123
|
+
# the thread ourselves. We also use the "enabled thread" concept for disabling checks too, see
|
124
|
+
# disable_temporarily for more details.
|
125
|
+
|
123
126
|
@enabled_thread = Thread.current
|
124
127
|
@tracepoint.enable do
|
125
128
|
block.call
|
@@ -128,13 +131,17 @@ module Temporalio
|
|
128
131
|
end
|
129
132
|
end
|
130
133
|
|
131
|
-
def
|
134
|
+
def disable_temporarily(&)
|
135
|
+
# An earlier version of this used @tracepoint.disable, but in some versions of Ruby, the observed behavior
|
136
|
+
# is confusingly not reentrant or at least not predictable. Therefore, instead of calling
|
137
|
+
# @tracepoint.disable, we are just unsetting the enabled thread. This means the tracer is still running, but
|
138
|
+
# no checks are performed. This is effectively a no-op if tracing was never enabled.
|
139
|
+
|
132
140
|
previous_thread = @enabled_thread
|
133
|
-
@
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
141
|
+
@enabled_thread = nil
|
142
|
+
yield
|
143
|
+
ensure
|
144
|
+
@enabled_thread = previous_thread
|
138
145
|
end
|
139
146
|
end
|
140
147
|
end
|
@@ -114,14 +114,15 @@ module Temporalio
|
|
114
114
|
local_retry_threshold: ProtoUtils.seconds_to_duration(input.local_retry_threshold),
|
115
115
|
attempt: do_backoff&.attempt || 0,
|
116
116
|
original_schedule_time: do_backoff&.original_schedule_time
|
117
|
-
)
|
117
|
+
),
|
118
|
+
user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter)
|
118
119
|
)
|
119
120
|
)
|
120
121
|
seq
|
121
122
|
end
|
122
123
|
end
|
123
124
|
|
124
|
-
def execute_activity_with_local_backoffs(local:, cancellation:, result_hint:, &)
|
125
|
+
def execute_activity_with_local_backoffs(local:, cancellation:, result_hint:, &block)
|
125
126
|
# We do not even want to schedule if the cancellation is already cancelled. We choose to use canceled
|
126
127
|
# failure instead of wrapping in activity failure which is similar to what other SDKs do, with the accepted
|
127
128
|
# tradeoff that it makes rescue more difficult (hence the presence of Error.canceled? helper).
|
@@ -130,7 +131,7 @@ module Temporalio
|
|
130
131
|
# This has to be done in a loop for local activity backoff
|
131
132
|
last_local_backoff = nil
|
132
133
|
loop do
|
133
|
-
result = execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, &)
|
134
|
+
result = execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, &block)
|
134
135
|
return result unless result.is_a?(Bridge::Api::ActivityResult::DoBackoff)
|
135
136
|
|
136
137
|
# @type var result: untyped
|
@@ -142,9 +143,9 @@ module Temporalio
|
|
142
143
|
end
|
143
144
|
|
144
145
|
# If this doesn't raise, it returns success | DoBackoff
|
145
|
-
def execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, &)
|
146
|
+
def execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, &block)
|
146
147
|
# Add to pending activities (removed by the resolver)
|
147
|
-
seq =
|
148
|
+
seq = block.call(last_local_backoff)
|
148
149
|
@instance.pending_activities[seq] = Fiber.current
|
149
150
|
|
150
151
|
# Add cancellation hook
|
@@ -27,8 +27,11 @@ module Temporalio
|
|
27
27
|
return true
|
28
28
|
end
|
29
29
|
|
30
|
-
# Disable
|
31
|
-
|
30
|
+
# Disable scheduler since logs technically have local mutexes in them that cannot be done durably or they
|
31
|
+
# will block workflows
|
32
|
+
@instance.context.durable_scheduler_disabled do
|
33
|
+
super
|
34
|
+
end
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
@@ -40,10 +40,15 @@ module Temporalio
|
|
40
40
|
cond_fiber = nil
|
41
41
|
cond_result = nil
|
42
42
|
@wait_conditions.each do |seq, cond|
|
43
|
+
# Evaluate condition or skip if not true
|
43
44
|
next unless (cond_result = cond.first.call)
|
44
45
|
|
45
|
-
|
46
|
-
|
46
|
+
# There have been reports of this fiber being completed already, so we make sure not to process if it
|
47
|
+
# has, but we still delete it
|
48
|
+
deleted_cond = @wait_conditions.delete(seq)
|
49
|
+
next unless deleted_cond&.last&.alive?
|
50
|
+
|
51
|
+
cond_fiber = deleted_cond.last
|
47
52
|
break
|
48
53
|
end
|
49
54
|
return unless cond_fiber
|
@@ -106,7 +111,7 @@ module Temporalio
|
|
106
111
|
# We just yield because unblock will resume this. We will just wrap in timeout if needed.
|
107
112
|
if timeout
|
108
113
|
begin
|
109
|
-
|
114
|
+
Workflow.timeout(timeout) { Fiber.yield }
|
110
115
|
true
|
111
116
|
rescue Timeout::Error
|
112
117
|
false
|
@@ -141,7 +146,8 @@ module Temporalio
|
|
141
146
|
unless @instance.io_enabled
|
142
147
|
raise Workflow::NondeterminismError,
|
143
148
|
'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.
|
149
|
+
'the code can be run in a Temporalio::Workflow::Unsafe.durable_scheduler_disabled ' \
|
150
|
+
'or Temporalio::Workflow::Unsafe.io_enabled block.'
|
145
151
|
end
|
146
152
|
|
147
153
|
# Use regular Ruby behavior of blocking this thread. There is no Ruby implementation of io_wait we can just
|
@@ -125,6 +125,7 @@ module Temporalio
|
|
125
125
|
continued_run_id: ProtoUtils.string_or(@init_job.continued_from_execution_run_id),
|
126
126
|
cron_schedule: ProtoUtils.string_or(@init_job.cron_schedule),
|
127
127
|
execution_timeout: ProtoUtils.duration_to_seconds(@init_job.workflow_execution_timeout),
|
128
|
+
first_execution_run_id: @init_job.first_execution_run_id,
|
128
129
|
headers: ProtoUtils.headers_from_proto_map(@init_job.headers, @payload_converter) || {},
|
129
130
|
last_failure: if @init_job.continued_failure
|
130
131
|
@failure_converter.from_failure(@init_job.continued_failure, @payload_converter)
|
@@ -162,86 +163,9 @@ module Temporalio
|
|
162
163
|
end
|
163
164
|
|
164
165
|
def activate(activation)
|
165
|
-
# Run inside of scheduler
|
166
|
-
run_in_scheduler { activate_internal(activation) }
|
167
|
-
end
|
168
|
-
|
169
|
-
def add_command(command)
|
170
|
-
raise Workflow::InvalidWorkflowStateError, 'Cannot add commands in this context' if @context_frozen
|
171
|
-
|
172
|
-
@commands << command
|
173
|
-
end
|
174
|
-
|
175
|
-
def instance
|
176
|
-
@instance or raise 'Instance accessed before created'
|
177
|
-
end
|
178
|
-
|
179
|
-
def search_attributes
|
180
|
-
# Lazy on first access
|
181
|
-
@search_attributes ||= SearchAttributes._from_proto(
|
182
|
-
@init_job.search_attributes, disable_mutations: true, never_nil: true
|
183
|
-
) || raise
|
184
|
-
end
|
185
|
-
|
186
|
-
def memo
|
187
|
-
# Lazy on first access
|
188
|
-
@memo ||= ExternallyImmutableHash.new(ProtoUtils.memo_from_proto(@init_job.memo, payload_converter) || {})
|
189
|
-
end
|
190
|
-
|
191
|
-
def now
|
192
|
-
# Create each time
|
193
|
-
ProtoUtils.timestamp_to_time(@now_timestamp) or raise 'Time unexpectedly not present'
|
194
|
-
end
|
195
|
-
|
196
|
-
def illegal_call_tracing_disabled(&)
|
197
|
-
@tracer.disable(&)
|
198
|
-
end
|
199
|
-
|
200
|
-
def patch(patch_id:, deprecated:)
|
201
|
-
# Use memoized result if present. If this is being deprecated, we can still use memoized result and skip the
|
202
|
-
# command.
|
203
|
-
patch_id = patch_id.to_s
|
204
|
-
@patches_memoized ||= {}
|
205
|
-
@patches_memoized.fetch(patch_id) do
|
206
|
-
patched = !replaying || @patches_notified.include?(patch_id)
|
207
|
-
@patches_memoized[patch_id] = patched
|
208
|
-
if patched
|
209
|
-
add_command(
|
210
|
-
Bridge::Api::WorkflowCommands::WorkflowCommand.new(
|
211
|
-
set_patch_marker: Bridge::Api::WorkflowCommands::SetPatchMarker.new(patch_id:, deprecated:)
|
212
|
-
)
|
213
|
-
)
|
214
|
-
end
|
215
|
-
patched
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
def metric_meter
|
220
|
-
@metric_meter ||= ReplaySafeMetric::Meter.new(
|
221
|
-
@runtime_metric_meter.with_additional_attributes(
|
222
|
-
{
|
223
|
-
namespace: info.namespace,
|
224
|
-
task_queue: info.task_queue,
|
225
|
-
workflow_type: info.workflow_type
|
226
|
-
}
|
227
|
-
)
|
228
|
-
)
|
229
|
-
end
|
230
|
-
|
231
|
-
private
|
232
|
-
|
233
|
-
def run_in_scheduler(&)
|
166
|
+
# Run inside of scheduler (removed on ensure)
|
234
167
|
Fiber.set_scheduler(@scheduler)
|
235
|
-
if @tracer
|
236
|
-
@tracer.enable(&)
|
237
|
-
else
|
238
|
-
yield
|
239
|
-
end
|
240
|
-
ensure
|
241
|
-
Fiber.set_scheduler(nil)
|
242
|
-
end
|
243
168
|
|
244
|
-
def activate_internal(activation)
|
245
169
|
# Reset some activation state
|
246
170
|
@commands = []
|
247
171
|
@current_activation_error = nil
|
@@ -266,8 +190,12 @@ module Temporalio
|
|
266
190
|
# the first activation)
|
267
191
|
@primary_fiber ||= schedule(top_level: true) { run_workflow }
|
268
192
|
|
269
|
-
# Run the event loop
|
270
|
-
@
|
193
|
+
# Run the event loop in the tracer if it exists
|
194
|
+
if @tracer
|
195
|
+
@tracer.enable { @scheduler.run_until_all_yielded }
|
196
|
+
else
|
197
|
+
@scheduler.run_until_all_yielded
|
198
|
+
end
|
271
199
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
272
200
|
on_top_level_exception(e)
|
273
201
|
end
|
@@ -306,8 +234,77 @@ module Temporalio
|
|
306
234
|
ensure
|
307
235
|
@commands = nil
|
308
236
|
@current_activation_error = nil
|
237
|
+
Fiber.set_scheduler(nil)
|
238
|
+
end
|
239
|
+
|
240
|
+
def add_command(command)
|
241
|
+
raise Workflow::InvalidWorkflowStateError, 'Cannot add commands in this context' if @context_frozen
|
242
|
+
|
243
|
+
@commands << command
|
244
|
+
end
|
245
|
+
|
246
|
+
def instance
|
247
|
+
@instance or raise 'Instance accessed before created'
|
248
|
+
end
|
249
|
+
|
250
|
+
def search_attributes
|
251
|
+
# Lazy on first access
|
252
|
+
@search_attributes ||= SearchAttributes._from_proto(
|
253
|
+
@init_job.search_attributes, disable_mutations: true, never_nil: true
|
254
|
+
) || raise
|
255
|
+
end
|
256
|
+
|
257
|
+
def memo
|
258
|
+
# Lazy on first access
|
259
|
+
@memo ||= ExternallyImmutableHash.new(ProtoUtils.memo_from_proto(@init_job.memo, payload_converter) || {})
|
260
|
+
end
|
261
|
+
|
262
|
+
def now
|
263
|
+
# Create each time
|
264
|
+
ProtoUtils.timestamp_to_time(@now_timestamp) or raise 'Time unexpectedly not present'
|
309
265
|
end
|
310
266
|
|
267
|
+
def illegal_call_tracing_disabled(&)
|
268
|
+
if @tracer
|
269
|
+
@tracer.disable_temporarily(&)
|
270
|
+
else
|
271
|
+
yield
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def patch(patch_id:, deprecated:)
|
276
|
+
# Use memoized result if present. If this is being deprecated, we can still use memoized result and skip the
|
277
|
+
# command.
|
278
|
+
patch_id = patch_id.to_s
|
279
|
+
@patches_memoized ||= {}
|
280
|
+
@patches_memoized.fetch(patch_id) do
|
281
|
+
patched = !replaying || @patches_notified.include?(patch_id)
|
282
|
+
@patches_memoized[patch_id] = patched
|
283
|
+
if patched
|
284
|
+
add_command(
|
285
|
+
Bridge::Api::WorkflowCommands::WorkflowCommand.new(
|
286
|
+
set_patch_marker: Bridge::Api::WorkflowCommands::SetPatchMarker.new(patch_id:, deprecated:)
|
287
|
+
)
|
288
|
+
)
|
289
|
+
end
|
290
|
+
patched
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def metric_meter
|
295
|
+
@metric_meter ||= ReplaySafeMetric::Meter.new(
|
296
|
+
@runtime_metric_meter.with_additional_attributes(
|
297
|
+
{
|
298
|
+
namespace: info.namespace,
|
299
|
+
task_queue: info.task_queue,
|
300
|
+
workflow_type: info.workflow_type
|
301
|
+
}
|
302
|
+
)
|
303
|
+
)
|
304
|
+
end
|
305
|
+
|
306
|
+
private
|
307
|
+
|
311
308
|
def create_instance
|
312
309
|
# Convert workflow arguments
|
313
310
|
@workflow_arguments = convert_args(payload_array: @init_job.arguments,
|
data/lib/temporalio/priority.rb
CHANGED
@@ -4,7 +4,9 @@ require 'temporalio/api'
|
|
4
4
|
|
5
5
|
module Temporalio
|
6
6
|
Priority = Data.define(
|
7
|
-
:priority_key
|
7
|
+
:priority_key,
|
8
|
+
:fairness_key,
|
9
|
+
:fairness_weight
|
8
10
|
)
|
9
11
|
|
10
12
|
# Priority contains metadata that controls relative ordering of task processing when tasks are
|
@@ -29,31 +31,70 @@ module Temporalio
|
|
29
31
|
#
|
30
32
|
# The default priority is (min+max)/2. With the default max of 5 and min of 1, that comes
|
31
33
|
# out to 3.
|
34
|
+
#
|
35
|
+
# @!attribute fairness_key
|
36
|
+
# @return [String, nil] FairnessKey is a short string that's used as a key for a fairness
|
37
|
+
# balancing mechanism. It may correspond to a tenant id, or to a fixed
|
38
|
+
# string like "high" or "low". The default is the empty string.
|
39
|
+
#
|
40
|
+
# The fairness mechanism attempts to dispatch tasks for a given key in
|
41
|
+
# proportion to its weight. For example, using a thousand distinct tenant
|
42
|
+
# ids, each with a weight of 1.0 (the default) will result in each tenant
|
43
|
+
# getting a roughly equal share of task dispatch throughput.
|
44
|
+
#
|
45
|
+
# Fairness keys are limited to 64 bytes.
|
46
|
+
#
|
47
|
+
# @!attribute fairness_weight
|
48
|
+
# @return [Float, nil] Weight for a task can come from multiple sources for
|
49
|
+
# flexibility. From highest to lowest precedence:
|
50
|
+
# 1. Weights for a small set of keys can be overridden in task queue
|
51
|
+
# configuration with an API.
|
52
|
+
# 2. It can be attached to the workflow/activity in this field.
|
53
|
+
# 3. The default fairness_weight of 1.0 will be used.
|
54
|
+
#
|
55
|
+
# Weight values are clamped to the range [0.001, 1000].
|
32
56
|
class Priority
|
33
57
|
# @!visibility private
|
34
58
|
def self._from_proto(priority)
|
35
59
|
return default if priority.nil?
|
36
60
|
|
37
|
-
new(
|
61
|
+
new(
|
62
|
+
priority_key: priority.priority_key.zero? ? nil : priority.priority_key,
|
63
|
+
fairness_key: priority.fairness_key.empty? ? nil : priority.fairness_key,
|
64
|
+
fairness_weight: priority.fairness_weight.zero? ? nil : priority.fairness_weight
|
65
|
+
)
|
38
66
|
end
|
39
67
|
|
40
68
|
# The default priority instance.
|
41
69
|
#
|
42
70
|
# @return [Priority] The default priority
|
43
71
|
def self.default
|
44
|
-
@default ||= new(priority_key: nil)
|
72
|
+
@default ||= new(priority_key: nil, fairness_key: nil, fairness_weight: nil)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Initialize a new Priority instance.
|
76
|
+
#
|
77
|
+
# @param priority_key [Integer, nil] The priority key
|
78
|
+
# @param fairness_key [String, nil] The fairness key
|
79
|
+
# @param fairness_weight [Float, nil] The fairness weight
|
80
|
+
def initialize(priority_key: nil, fairness_key: nil, fairness_weight: nil)
|
81
|
+
super
|
45
82
|
end
|
46
83
|
|
47
84
|
# @!visibility private
|
48
85
|
def _to_proto
|
49
|
-
return nil if
|
86
|
+
return nil if empty?
|
50
87
|
|
51
|
-
Temporalio::Api::Common::V1::Priority.new(
|
88
|
+
Temporalio::Api::Common::V1::Priority.new(
|
89
|
+
priority_key: priority_key || 0,
|
90
|
+
fairness_key: fairness_key || '',
|
91
|
+
fairness_weight: fairness_weight || 0.0
|
92
|
+
)
|
52
93
|
end
|
53
94
|
|
54
95
|
# @return [Boolean] True if this priority is empty/default
|
55
96
|
def empty?
|
56
|
-
priority_key.nil?
|
97
|
+
priority_key.nil? && fairness_key.nil? && fairness_weight.nil?
|
57
98
|
end
|
58
99
|
end
|
59
100
|
end
|
@@ -17,7 +17,7 @@ module Temporalio
|
|
17
17
|
|
18
18
|
# @see Logger.add
|
19
19
|
def add(severity, message = nil, progname = nil)
|
20
|
-
return true if (severity || Logger::
|
20
|
+
return true if (severity || Logger::UNKNOWN) < level
|
21
21
|
return super if scoped_values_getter.nil? || @disable_scoped_values
|
22
22
|
|
23
23
|
scoped_values = scoped_values_getter.call
|
data/lib/temporalio/version.rb
CHANGED
@@ -39,6 +39,15 @@ module Temporalio
|
|
39
39
|
]
|
40
40
|
end
|
41
41
|
|
42
|
+
# @return [IllegalWorkflowCallValidator] Workflow call validator that is tailored to disallow most Mutex calls,
|
43
|
+
# but let others through for certain situations.
|
44
|
+
def self.known_safe_mutex_validator
|
45
|
+
@known_safe_mutex_validator ||= IllegalWorkflowCallValidator.new do
|
46
|
+
# Only Google Protobuf use of Mutex is known to be safe, fail unless any caller location path has protobuf
|
47
|
+
raise 'disallowed' unless caller_locations&.any? { |loc| loc.path&.include?('google/protobuf/') }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
42
51
|
# @return [String, nil] Method name if this validator is specific to a method.
|
43
52
|
attr_reader :method_name
|
44
53
|
|