temporalio 0.3.0-x86_64-linux → 0.5.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/.yardopts +1 -1
- data/Gemfile +4 -0
- data/Rakefile +1 -1
- 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/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_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 +34 -4
@@ -9,6 +9,7 @@ require 'temporalio/client/connection'
|
|
9
9
|
require 'temporalio/client/interceptor'
|
10
10
|
require 'temporalio/client/schedule'
|
11
11
|
require 'temporalio/client/schedule_handle'
|
12
|
+
require 'temporalio/client/with_start_workflow_operation'
|
12
13
|
require 'temporalio/client/workflow_execution'
|
13
14
|
require 'temporalio/client/workflow_execution_count'
|
14
15
|
require 'temporalio/client/workflow_handle'
|
@@ -41,21 +42,18 @@ module Temporalio
|
|
41
42
|
end
|
42
43
|
|
43
44
|
def initialize(client)
|
44
|
-
super(nil)
|
45
|
+
super(nil) # steep:ignore
|
45
46
|
@client = client
|
46
47
|
end
|
47
48
|
|
48
49
|
def start_workflow(input)
|
49
|
-
# TODO(cretz): Signal/update with start
|
50
50
|
req = Api::WorkflowService::V1::StartWorkflowExecutionRequest.new(
|
51
51
|
request_id: SecureRandom.uuid,
|
52
52
|
namespace: @client.namespace,
|
53
|
-
workflow_type: Api::Common::V1::WorkflowType.new(
|
54
|
-
name: Workflow::Definition._workflow_type_from_workflow_parameter(input.workflow)
|
55
|
-
),
|
53
|
+
workflow_type: Api::Common::V1::WorkflowType.new(name: input.workflow),
|
56
54
|
workflow_id: input.workflow_id,
|
57
55
|
task_queue: Api::TaskQueue::V1::TaskQueue.new(name: input.task_queue.to_s),
|
58
|
-
input: @client.data_converter.to_payloads(input.args),
|
56
|
+
input: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
|
59
57
|
workflow_execution_timeout: ProtoUtils.seconds_to_duration(input.execution_timeout),
|
60
58
|
workflow_run_timeout: ProtoUtils.seconds_to_duration(input.run_timeout),
|
61
59
|
workflow_task_timeout: ProtoUtils.seconds_to_duration(input.task_timeout),
|
@@ -68,7 +66,12 @@ module Temporalio
|
|
68
66
|
search_attributes: input.search_attributes&._to_proto,
|
69
67
|
workflow_start_delay: ProtoUtils.seconds_to_duration(input.start_delay),
|
70
68
|
request_eager_execution: input.request_eager_start,
|
71
|
-
|
69
|
+
user_metadata: ProtoUtils.to_user_metadata(
|
70
|
+
input.static_summary, input.static_details, @client.data_converter
|
71
|
+
),
|
72
|
+
header: ProtoUtils.headers_to_proto(input.headers, @client.data_converter),
|
73
|
+
priority: input.priority._to_proto,
|
74
|
+
versioning_override: input.versioning_override&._to_proto
|
72
75
|
)
|
73
76
|
|
74
77
|
# Send request
|
@@ -100,29 +103,251 @@ module Temporalio
|
|
100
103
|
id: input.workflow_id,
|
101
104
|
run_id: nil,
|
102
105
|
result_run_id: resp.run_id,
|
103
|
-
first_execution_run_id: resp.run_id
|
106
|
+
first_execution_run_id: resp.run_id,
|
107
|
+
result_hint: input.result_hint
|
104
108
|
)
|
105
109
|
end
|
106
110
|
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
111
|
+
def start_update_with_start_workflow(input)
|
112
|
+
raise ArgumentError, 'Start operation is required' unless input.start_workflow_operation
|
113
|
+
|
114
|
+
if input.start_workflow_operation.options.id_conflict_policy == WorkflowIDConflictPolicy::UNSPECIFIED
|
115
|
+
raise ArgumentError, 'ID conflict policy is required in start operation'
|
116
|
+
end
|
117
|
+
|
118
|
+
# Try to mark used before using
|
119
|
+
input.start_workflow_operation._mark_used
|
120
|
+
|
121
|
+
# Build request
|
122
|
+
start_options = input.start_workflow_operation.options
|
123
|
+
start_req = _start_workflow_request_from_with_start_options(
|
124
|
+
Api::WorkflowService::V1::StartWorkflowExecutionRequest, start_options
|
125
|
+
)
|
126
|
+
req = Api::WorkflowService::V1::ExecuteMultiOperationRequest.new(
|
127
|
+
namespace: @client.namespace,
|
128
|
+
operations: [
|
129
|
+
Api::WorkflowService::V1::ExecuteMultiOperationRequest::Operation.new(start_workflow: start_req),
|
130
|
+
Api::WorkflowService::V1::ExecuteMultiOperationRequest::Operation.new(
|
131
|
+
update_workflow: Api::WorkflowService::V1::UpdateWorkflowExecutionRequest.new(
|
132
|
+
namespace: @client.namespace,
|
133
|
+
workflow_execution: Api::Common::V1::WorkflowExecution.new(
|
134
|
+
workflow_id: start_options.id
|
135
|
+
),
|
136
|
+
request: Api::Update::V1::Request.new(
|
137
|
+
meta: Api::Update::V1::Meta.new(
|
138
|
+
update_id: input.update_id,
|
139
|
+
identity: @client.connection.identity
|
140
|
+
),
|
141
|
+
input: Api::Update::V1::Input.new(
|
142
|
+
name: input.update,
|
143
|
+
args: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
|
144
|
+
header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
|
145
|
+
)
|
146
|
+
),
|
147
|
+
wait_policy: Api::Update::V1::WaitPolicy.new(
|
148
|
+
lifecycle_stage: input.wait_for_stage
|
149
|
+
)
|
150
|
+
)
|
151
|
+
)
|
152
|
+
]
|
153
|
+
)
|
154
|
+
|
155
|
+
# Continually try to start until an exception occurs, the user-asked stage is reached, or the stage is
|
156
|
+
# accepted. But we will set the workflow handle as soon as we can.
|
157
|
+
# @type var update_resp: untyped
|
158
|
+
update_resp = nil
|
159
|
+
run_id = nil
|
160
|
+
begin
|
113
161
|
loop do
|
114
|
-
resp = @client.workflow_service.
|
115
|
-
req,
|
116
|
-
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
162
|
+
resp = @client.workflow_service.execute_multi_operation(
|
163
|
+
req, rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
117
164
|
)
|
118
|
-
resp.
|
119
|
-
|
165
|
+
run_id = resp.responses.first.start_workflow.run_id
|
166
|
+
# Set workflow handle (no-op if already set)
|
167
|
+
input.start_workflow_operation._set_workflow_handle(
|
168
|
+
Temporalio::Client::WorkflowHandle.new(
|
169
|
+
client: @client,
|
170
|
+
id: start_options.id,
|
171
|
+
run_id: nil,
|
172
|
+
result_run_id: run_id,
|
173
|
+
first_execution_run_id: run_id,
|
174
|
+
result_hint: start_options.result_hint
|
175
|
+
)
|
176
|
+
)
|
177
|
+
update_resp = resp.responses.last.update_workflow
|
178
|
+
|
179
|
+
# We're only done if the response stage is at least accepted
|
180
|
+
if update_resp && Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage.resolve(update_resp.stage) >=
|
181
|
+
Temporalio::Client::WorkflowUpdateWaitStage::ACCEPTED
|
182
|
+
break
|
120
183
|
end
|
121
|
-
|
184
|
+
end
|
122
185
|
|
123
|
-
|
186
|
+
# If the user wants to wait until completed, we must poll until outcome if not already there
|
187
|
+
if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED && update_resp.outcome
|
188
|
+
update_resp.outcome = @client._impl.poll_workflow_update(
|
189
|
+
Temporalio::Client::Interceptor::PollWorkflowUpdateInput.new(
|
190
|
+
workflow_id: start_options.id,
|
191
|
+
run_id:,
|
192
|
+
update_id: input.update_id,
|
193
|
+
rpc_options: input.rpc_options
|
194
|
+
)
|
195
|
+
)
|
196
|
+
end
|
197
|
+
rescue Error => e
|
198
|
+
# If this is a multi-operation failure, set exception to the first present, non-OK, non-aborted error
|
199
|
+
if e.is_a?(Error::RPCError)
|
200
|
+
multi_err = e.grpc_status.details&.first&.unpack(Api::ErrorDetails::V1::MultiOperationExecutionFailure)
|
201
|
+
if multi_err
|
202
|
+
non_aborted = multi_err.statuses.find do |s|
|
203
|
+
# Exists, not-ok, not-aborted
|
204
|
+
s && s.code != Error::RPCError::Code::OK &&
|
205
|
+
!s.details&.first&.is(Api::Failure::V1::MultiOperationExecutionAborted)
|
206
|
+
end
|
207
|
+
if non_aborted
|
208
|
+
e = Error::RPCError.new(
|
209
|
+
non_aborted.message,
|
210
|
+
code: non_aborted.code,
|
211
|
+
raw_grpc_status: Api::Common::V1::GrpcStatus.new(
|
212
|
+
code: non_aborted.code, message: non_aborted.message, details: non_aborted.details.to_a
|
213
|
+
)
|
214
|
+
)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
if e.is_a?(Error::RPCError)
|
219
|
+
# Deadline exceeded or cancel is a special error type
|
220
|
+
if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELED
|
221
|
+
e = Error::WorkflowUpdateRPCTimeoutOrCanceledError.new
|
222
|
+
elsif e.code == Error::RPCError::Code::ALREADY_EXISTS && e.grpc_status.details.first
|
223
|
+
# Unpack and set already started if that's the error
|
224
|
+
details = e.grpc_status.details.first.unpack(
|
225
|
+
Api::ErrorDetails::V1::WorkflowExecutionAlreadyStartedFailure
|
226
|
+
)
|
227
|
+
if details
|
228
|
+
e = Error::WorkflowAlreadyStartedError.new(
|
229
|
+
workflow_id: start_options.id,
|
230
|
+
workflow_type: start_req.workflow_type,
|
231
|
+
run_id: details.run_id
|
232
|
+
)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
# Cancel is a special type
|
237
|
+
e = Error::WorkflowUpdateRPCTimeoutOrCanceledError.new if e.is_a?(Error::CanceledError)
|
238
|
+
# Before we raise here, we want to try to set the start operation exception (no-op if already set with a
|
239
|
+
# handle)
|
240
|
+
input.start_workflow_operation._set_workflow_handle(e)
|
241
|
+
raise e
|
242
|
+
end
|
243
|
+
|
244
|
+
# Return handle
|
245
|
+
Temporalio::Client::WorkflowUpdateHandle.new(
|
246
|
+
client: @client,
|
247
|
+
id: input.update_id,
|
248
|
+
workflow_id: start_options.id,
|
249
|
+
workflow_run_id: run_id,
|
250
|
+
known_outcome: update_resp.outcome,
|
251
|
+
result_hint: input.result_hint
|
252
|
+
)
|
253
|
+
end
|
254
|
+
|
255
|
+
def signal_with_start_workflow(input)
|
256
|
+
raise ArgumentError, 'Start operation is required' unless input.start_workflow_operation
|
257
|
+
|
258
|
+
# Try to mark used before using
|
259
|
+
input.start_workflow_operation._mark_used
|
260
|
+
|
261
|
+
# Build req
|
262
|
+
start_options = input.start_workflow_operation.options
|
263
|
+
req = _start_workflow_request_from_with_start_options(
|
264
|
+
Api::WorkflowService::V1::SignalWithStartWorkflowExecutionRequest, start_options
|
265
|
+
)
|
266
|
+
req.signal_name = input.signal
|
267
|
+
req.signal_input = @client.data_converter.to_payloads(input.args, hints: input.arg_hints)
|
268
|
+
|
269
|
+
# Send request
|
270
|
+
begin
|
271
|
+
resp = @client.workflow_service.signal_with_start_workflow_execution(
|
272
|
+
req,
|
273
|
+
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
274
|
+
)
|
275
|
+
rescue Error::RPCError => e
|
276
|
+
# Unpack and raise already started if that's the error, otherwise default raise
|
277
|
+
if e.code == Error::RPCError::Code::ALREADY_EXISTS && e.grpc_status.details.first
|
278
|
+
details = e.grpc_status.details.first.unpack(
|
279
|
+
Api::ErrorDetails::V1::WorkflowExecutionAlreadyStartedFailure
|
280
|
+
)
|
281
|
+
if details
|
282
|
+
e = Error::WorkflowAlreadyStartedError.new(
|
283
|
+
workflow_id: req.workflow_id,
|
284
|
+
workflow_type: req.workflow_type.name,
|
285
|
+
run_id: details.run_id
|
286
|
+
)
|
287
|
+
end
|
124
288
|
end
|
289
|
+
# Before we raise here, we want to the start operation exception
|
290
|
+
input.start_workflow_operation._set_workflow_handle(e)
|
291
|
+
raise e
|
125
292
|
end
|
293
|
+
|
294
|
+
# Set handle and return handle
|
295
|
+
handle = Temporalio::Client::WorkflowHandle.new(
|
296
|
+
client: @client,
|
297
|
+
id: start_options.id,
|
298
|
+
run_id: nil,
|
299
|
+
result_run_id: resp.run_id,
|
300
|
+
first_execution_run_id: resp.run_id,
|
301
|
+
result_hint: start_options.result_hint
|
302
|
+
)
|
303
|
+
input.start_workflow_operation._set_workflow_handle(handle)
|
304
|
+
handle
|
305
|
+
end
|
306
|
+
|
307
|
+
def _start_workflow_request_from_with_start_options(klass, start_options)
|
308
|
+
klass.new(
|
309
|
+
request_id: SecureRandom.uuid,
|
310
|
+
namespace: @client.namespace,
|
311
|
+
workflow_type: Api::Common::V1::WorkflowType.new(name: start_options.workflow),
|
312
|
+
workflow_id: start_options.id,
|
313
|
+
task_queue: Api::TaskQueue::V1::TaskQueue.new(name: start_options.task_queue.to_s),
|
314
|
+
input: @client.data_converter.to_payloads(start_options.args, hints: start_options.arg_hints),
|
315
|
+
workflow_execution_timeout: ProtoUtils.seconds_to_duration(start_options.execution_timeout),
|
316
|
+
workflow_run_timeout: ProtoUtils.seconds_to_duration(start_options.run_timeout),
|
317
|
+
workflow_task_timeout: ProtoUtils.seconds_to_duration(start_options.task_timeout),
|
318
|
+
identity: @client.connection.identity,
|
319
|
+
workflow_id_reuse_policy: start_options.id_reuse_policy,
|
320
|
+
workflow_id_conflict_policy: start_options.id_conflict_policy,
|
321
|
+
retry_policy: start_options.retry_policy&._to_proto,
|
322
|
+
cron_schedule: start_options.cron_schedule,
|
323
|
+
memo: ProtoUtils.memo_to_proto(start_options.memo, @client.data_converter),
|
324
|
+
search_attributes: start_options.search_attributes&._to_proto,
|
325
|
+
workflow_start_delay: ProtoUtils.seconds_to_duration(start_options.start_delay),
|
326
|
+
user_metadata: ProtoUtils.to_user_metadata(
|
327
|
+
start_options.static_summary, start_options.static_details, @client.data_converter
|
328
|
+
),
|
329
|
+
header: ProtoUtils.headers_to_proto(start_options.headers, @client.data_converter)
|
330
|
+
)
|
331
|
+
end
|
332
|
+
|
333
|
+
def list_workflow_page(input)
|
334
|
+
req = Api::WorkflowService::V1::ListWorkflowExecutionsRequest.new(
|
335
|
+
namespace: @client.namespace,
|
336
|
+
query: input.query || '',
|
337
|
+
next_page_token: input.next_page_token,
|
338
|
+
page_size: input.page_size
|
339
|
+
)
|
340
|
+
resp = @client.workflow_service.list_workflow_executions(
|
341
|
+
req,
|
342
|
+
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
343
|
+
)
|
344
|
+
executions = resp.executions.map do |raw_info|
|
345
|
+
Temporalio::Client::WorkflowExecution.new(raw_info, @client.data_converter)
|
346
|
+
end
|
347
|
+
Temporalio::Client::ListWorkflowPage.new(
|
348
|
+
executions: executions,
|
349
|
+
next_page_token: resp.next_page_token
|
350
|
+
)
|
126
351
|
end
|
127
352
|
|
128
353
|
def count_workflows(input)
|
@@ -191,8 +416,8 @@ module Temporalio
|
|
191
416
|
workflow_id: input.workflow_id,
|
192
417
|
run_id: input.run_id || ''
|
193
418
|
),
|
194
|
-
signal_name:
|
195
|
-
input: @client.data_converter.to_payloads(input.args),
|
419
|
+
signal_name: input.signal,
|
420
|
+
input: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
|
196
421
|
header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter),
|
197
422
|
identity: @client.connection.identity,
|
198
423
|
request_id: SecureRandom.uuid
|
@@ -212,8 +437,8 @@ module Temporalio
|
|
212
437
|
run_id: input.run_id || ''
|
213
438
|
),
|
214
439
|
query: Api::Query::V1::WorkflowQuery.new(
|
215
|
-
query_type:
|
216
|
-
query_args: @client.data_converter.to_payloads(input.args),
|
440
|
+
query_type: input.query,
|
441
|
+
query_args: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
|
217
442
|
header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
|
218
443
|
),
|
219
444
|
query_reject_condition: input.reject_condition || 0
|
@@ -233,7 +458,7 @@ module Temporalio
|
|
233
458
|
))
|
234
459
|
end
|
235
460
|
|
236
|
-
results = @client.data_converter.from_payloads(resp.query_result)
|
461
|
+
results = @client.data_converter.from_payloads(resp.query_result, hints: Array(input.result_hint))
|
237
462
|
warn("Expected 0 or 1 query result, got #{results.size}") if results.size > 1
|
238
463
|
results&.first
|
239
464
|
end
|
@@ -255,8 +480,8 @@ module Temporalio
|
|
255
480
|
identity: @client.connection.identity
|
256
481
|
),
|
257
482
|
input: Api::Update::V1::Input.new(
|
258
|
-
name:
|
259
|
-
args: @client.data_converter.to_payloads(input.args),
|
483
|
+
name: input.update,
|
484
|
+
args: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
|
260
485
|
header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
|
261
486
|
)
|
262
487
|
),
|
@@ -270,6 +495,10 @@ module Temporalio
|
|
270
495
|
# the user cannot specify sooner than ACCEPTED)
|
271
496
|
# @type var resp: untyped
|
272
497
|
resp = nil
|
498
|
+
expected_stage = ProtoUtils.enum_to_int(Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage,
|
499
|
+
req.wait_policy.lifecycle_stage)
|
500
|
+
accepted_stage = ProtoUtils.enum_to_int(Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage,
|
501
|
+
Temporalio::Client::WorkflowUpdateWaitStage::ACCEPTED)
|
273
502
|
loop do
|
274
503
|
resp = @client.workflow_service.update_workflow_execution(
|
275
504
|
req,
|
@@ -278,17 +507,17 @@ module Temporalio
|
|
278
507
|
|
279
508
|
# We're only done if the response stage is after the requested stage
|
280
509
|
# or the response stage is accepted
|
281
|
-
|
282
|
-
|
283
|
-
break
|
284
|
-
end
|
510
|
+
actual_stage = ProtoUtils.enum_to_int(Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage, resp.stage)
|
511
|
+
break if actual_stage >= expected_stage || actual_stage >= accepted_stage
|
285
512
|
rescue Error::RPCError => e
|
286
513
|
# Deadline exceeded or cancel is a special error type
|
287
|
-
if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::
|
514
|
+
if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELED
|
288
515
|
raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
|
289
516
|
end
|
290
517
|
|
291
518
|
raise
|
519
|
+
rescue Error::CanceledError
|
520
|
+
raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
|
292
521
|
end
|
293
522
|
|
294
523
|
# If the user wants to wait until completed, we must poll until outcome
|
@@ -309,7 +538,8 @@ module Temporalio
|
|
309
538
|
id: input.update_id,
|
310
539
|
workflow_id: input.workflow_id,
|
311
540
|
workflow_run_id: input.run_id,
|
312
|
-
known_outcome: resp.outcome
|
541
|
+
known_outcome: resp.outcome,
|
542
|
+
result_hint: input.result_hint
|
313
543
|
)
|
314
544
|
end
|
315
545
|
|
@@ -338,7 +568,7 @@ module Temporalio
|
|
338
568
|
return resp.outcome if resp.outcome
|
339
569
|
rescue Error::RPCError => e
|
340
570
|
# Deadline exceeded or cancel is a special error type
|
341
|
-
if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::
|
571
|
+
if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELED
|
342
572
|
raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
|
343
573
|
end
|
344
574
|
|
@@ -584,7 +814,7 @@ module Temporalio
|
|
584
814
|
activity_id: input.task_token_or_id_reference.activity_id,
|
585
815
|
namespace: @client.namespace,
|
586
816
|
identity: @client.connection.identity,
|
587
|
-
details: @client.data_converter.to_payloads(input.details)
|
817
|
+
details: @client.data_converter.to_payloads(input.details, hints: input.detail_hints)
|
588
818
|
),
|
589
819
|
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
590
820
|
)
|
@@ -594,7 +824,7 @@ module Temporalio
|
|
594
824
|
task_token: input.task_token_or_id_reference,
|
595
825
|
namespace: @client.namespace,
|
596
826
|
identity: @client.connection.identity,
|
597
|
-
details: @client.data_converter.to_payloads(input.details)
|
827
|
+
details: @client.data_converter.to_payloads(input.details, hints: input.detail_hints)
|
598
828
|
),
|
599
829
|
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
600
830
|
)
|
@@ -613,7 +843,7 @@ module Temporalio
|
|
613
843
|
activity_id: input.task_token_or_id_reference.activity_id,
|
614
844
|
namespace: @client.namespace,
|
615
845
|
identity: @client.connection.identity,
|
616
|
-
result: @client.data_converter.to_payloads([input.result])
|
846
|
+
result: @client.data_converter.to_payloads([input.result], hints: Array(input.result_hint))
|
617
847
|
),
|
618
848
|
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
619
849
|
)
|
@@ -623,7 +853,7 @@ module Temporalio
|
|
623
853
|
task_token: input.task_token_or_id_reference,
|
624
854
|
namespace: @client.namespace,
|
625
855
|
identity: @client.connection.identity,
|
626
|
-
result: @client.data_converter.to_payloads([input.result])
|
856
|
+
result: @client.data_converter.to_payloads([input.result], hints: Array(input.result_hint))
|
627
857
|
),
|
628
858
|
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
629
859
|
)
|
@@ -632,6 +862,14 @@ module Temporalio
|
|
632
862
|
end
|
633
863
|
|
634
864
|
def fail_async_activity(input)
|
865
|
+
last_heartbeat_details = if input.last_heartbeat_details.empty?
|
866
|
+
nil
|
867
|
+
else
|
868
|
+
@client.data_converter.to_payloads(
|
869
|
+
input.last_heartbeat_details,
|
870
|
+
hints: input.last_heartbeat_detail_hints
|
871
|
+
)
|
872
|
+
end
|
635
873
|
if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
|
636
874
|
@client.workflow_service.respond_activity_task_failed_by_id(
|
637
875
|
Api::WorkflowService::V1::RespondActivityTaskFailedByIdRequest.new(
|
@@ -641,11 +879,7 @@ module Temporalio
|
|
641
879
|
namespace: @client.namespace,
|
642
880
|
identity: @client.connection.identity,
|
643
881
|
failure: @client.data_converter.to_failure(input.error),
|
644
|
-
last_heartbeat_details:
|
645
|
-
nil
|
646
|
-
else
|
647
|
-
@client.data_converter.to_payloads(input.last_heartbeat_details)
|
648
|
-
end
|
882
|
+
last_heartbeat_details:
|
649
883
|
),
|
650
884
|
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
651
885
|
)
|
@@ -656,11 +890,7 @@ module Temporalio
|
|
656
890
|
namespace: @client.namespace,
|
657
891
|
identity: @client.connection.identity,
|
658
892
|
failure: @client.data_converter.to_failure(input.error),
|
659
|
-
last_heartbeat_details:
|
660
|
-
nil
|
661
|
-
else
|
662
|
-
@client.data_converter.to_payloads(input.last_heartbeat_details)
|
663
|
-
end
|
893
|
+
last_heartbeat_details:
|
664
894
|
),
|
665
895
|
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
666
896
|
)
|
@@ -677,7 +907,7 @@ module Temporalio
|
|
677
907
|
activity_id: input.task_token_or_id_reference.activity_id,
|
678
908
|
namespace: @client.namespace,
|
679
909
|
identity: @client.connection.identity,
|
680
|
-
details: @client.data_converter.to_payloads(input.details)
|
910
|
+
details: @client.data_converter.to_payloads(input.details, hints: input.detail_hints)
|
681
911
|
),
|
682
912
|
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
683
913
|
)
|
@@ -687,7 +917,7 @@ module Temporalio
|
|
687
917
|
task_token: input.task_token_or_id_reference,
|
688
918
|
namespace: @client.namespace,
|
689
919
|
identity: @client.connection.identity,
|
690
|
-
details: @client.data_converter.to_payloads(input.details)
|
920
|
+
details: @client.data_converter.to_payloads(input.details, hints: input.detail_hints)
|
691
921
|
),
|
692
922
|
rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
|
693
923
|
)
|
@@ -51,7 +51,7 @@ module Temporalio
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def self.memo_from_proto(memo, converter)
|
54
|
-
return nil if memo.nil? || memo.fields.size.zero? # rubocop:disable Style/ZeroLengthPredicate Google Maps don't have empty
|
54
|
+
return nil if memo.nil? || memo.fields.size.zero? # rubocop:disable Style/ZeroLengthPredicate -- Google Maps don't have empty
|
55
55
|
|
56
56
|
memo.fields.each_with_object({}) { |(key, val), h| h[key] = converter.from_payload(val) } # rubocop:disable Style/HashTransformValues
|
57
57
|
end
|
@@ -73,7 +73,7 @@ module Temporalio
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def self.headers_from_proto_map(headers, converter)
|
76
|
-
return nil if headers.nil? || headers.size.zero? # rubocop:disable Style/ZeroLengthPredicate Google Maps don't have empty
|
76
|
+
return nil if headers.nil? || headers.size.zero? # rubocop:disable Style/ZeroLengthPredicate -- Google Maps don't have empty
|
77
77
|
|
78
78
|
headers.each_with_object({}) do |(key, val), h| # rubocop:disable Style/HashTransformValues
|
79
79
|
# @type var h: Hash[String, Object?]
|
@@ -94,16 +94,48 @@ module Temporalio
|
|
94
94
|
enum_val
|
95
95
|
end
|
96
96
|
|
97
|
-
def self.convert_from_payload_array(converter, payloads)
|
97
|
+
def self.convert_from_payload_array(converter, payloads, hints:)
|
98
98
|
return [] if payloads.empty?
|
99
99
|
|
100
|
-
converter.from_payloads(Api::Common::V1::Payloads.new(payloads:))
|
100
|
+
converter.from_payloads(Api::Common::V1::Payloads.new(payloads:), hints:)
|
101
101
|
end
|
102
102
|
|
103
|
-
def self.convert_to_payload_array(converter, values)
|
103
|
+
def self.convert_to_payload_array(converter, values, hints:)
|
104
104
|
return [] if values.empty?
|
105
105
|
|
106
|
-
converter.to_payloads(values).payloads.to_ary
|
106
|
+
converter.to_payloads(values, hints:).payloads.to_ary
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.assert_non_reserved_name(name)
|
110
|
+
name = name&.to_s # In case it's a symbol or not present
|
111
|
+
return unless name
|
112
|
+
raise "'#{name}' cannot start with '__temporal_'" if name.start_with?('__temporal_')
|
113
|
+
# Might as well disable __stack_trace and __enhanced_stack_trace everywhere even though technically it's only
|
114
|
+
# reserved for queries
|
115
|
+
raise "'#{name}' name invalid" if name == '__stack_trace' || name == '__enhanced_stack_trace'
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.reserved_name?(name)
|
119
|
+
name = name&.to_s # In case it's a symbol or not present
|
120
|
+
return false unless name
|
121
|
+
|
122
|
+
name.start_with?('__temporal_') || name == '__stack_trace' || name == '__enhanced_stack_trace'
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.to_user_metadata(summary, details, converter)
|
126
|
+
return nil if (!summary || summary.empty?) && (!details || details.empty?)
|
127
|
+
|
128
|
+
metadata = Temporalio::Api::Sdk::V1::UserMetadata.new
|
129
|
+
metadata.summary = converter.to_payload(summary) if summary && !summary.empty?
|
130
|
+
metadata.details = converter.to_payload(details) if details && !details.empty?
|
131
|
+
metadata
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.from_user_metadata(metadata, converter)
|
135
|
+
[
|
136
|
+
(converter.from_payload(metadata.summary) if metadata&.summary), #: String?
|
137
|
+
(converter.from_payload(metadata.details) if metadata&.details) #: String?
|
138
|
+
]
|
107
139
|
end
|
108
140
|
|
109
141
|
class LazyMemo
|