temporalio 0.2.0-arm64-darwin

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +23 -0
  3. data/Rakefile +387 -0
  4. data/lib/temporalio/activity/complete_async_error.rb +11 -0
  5. data/lib/temporalio/activity/context.rb +107 -0
  6. data/lib/temporalio/activity/definition.rb +77 -0
  7. data/lib/temporalio/activity/info.rb +63 -0
  8. data/lib/temporalio/activity.rb +69 -0
  9. data/lib/temporalio/api/batch/v1/message.rb +31 -0
  10. data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +93 -0
  11. data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +25 -0
  12. data/lib/temporalio/api/cloud/cloudservice.rb +3 -0
  13. data/lib/temporalio/api/cloud/identity/v1/message.rb +36 -0
  14. data/lib/temporalio/api/cloud/namespace/v1/message.rb +35 -0
  15. data/lib/temporalio/api/cloud/operation/v1/message.rb +27 -0
  16. data/lib/temporalio/api/cloud/region/v1/message.rb +23 -0
  17. data/lib/temporalio/api/command/v1/message.rb +46 -0
  18. data/lib/temporalio/api/common/v1/grpc_status.rb +23 -0
  19. data/lib/temporalio/api/common/v1/message.rb +41 -0
  20. data/lib/temporalio/api/enums/v1/batch_operation.rb +22 -0
  21. data/lib/temporalio/api/enums/v1/command_type.rb +21 -0
  22. data/lib/temporalio/api/enums/v1/common.rb +26 -0
  23. data/lib/temporalio/api/enums/v1/event_type.rb +21 -0
  24. data/lib/temporalio/api/enums/v1/failed_cause.rb +26 -0
  25. data/lib/temporalio/api/enums/v1/namespace.rb +23 -0
  26. data/lib/temporalio/api/enums/v1/query.rb +22 -0
  27. data/lib/temporalio/api/enums/v1/reset.rb +23 -0
  28. data/lib/temporalio/api/enums/v1/schedule.rb +21 -0
  29. data/lib/temporalio/api/enums/v1/task_queue.rb +25 -0
  30. data/lib/temporalio/api/enums/v1/update.rb +22 -0
  31. data/lib/temporalio/api/enums/v1/workflow.rb +30 -0
  32. data/lib/temporalio/api/errordetails/v1/message.rb +42 -0
  33. data/lib/temporalio/api/export/v1/message.rb +24 -0
  34. data/lib/temporalio/api/failure/v1/message.rb +35 -0
  35. data/lib/temporalio/api/filter/v1/message.rb +27 -0
  36. data/lib/temporalio/api/history/v1/message.rb +90 -0
  37. data/lib/temporalio/api/namespace/v1/message.rb +31 -0
  38. data/lib/temporalio/api/nexus/v1/message.rb +40 -0
  39. data/lib/temporalio/api/operatorservice/v1/request_response.rb +49 -0
  40. data/lib/temporalio/api/operatorservice/v1/service.rb +23 -0
  41. data/lib/temporalio/api/operatorservice.rb +3 -0
  42. data/lib/temporalio/api/protocol/v1/message.rb +23 -0
  43. data/lib/temporalio/api/query/v1/message.rb +27 -0
  44. data/lib/temporalio/api/replication/v1/message.rb +26 -0
  45. data/lib/temporalio/api/schedule/v1/message.rb +42 -0
  46. data/lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb +25 -0
  47. data/lib/temporalio/api/sdk/v1/task_complete_metadata.rb +21 -0
  48. data/lib/temporalio/api/sdk/v1/user_metadata.rb +23 -0
  49. data/lib/temporalio/api/sdk/v1/workflow_metadata.rb +23 -0
  50. data/lib/temporalio/api/taskqueue/v1/message.rb +45 -0
  51. data/lib/temporalio/api/update/v1/message.rb +33 -0
  52. data/lib/temporalio/api/version/v1/message.rb +26 -0
  53. data/lib/temporalio/api/workflow/v1/message.rb +43 -0
  54. data/lib/temporalio/api/workflowservice/v1/request_response.rb +189 -0
  55. data/lib/temporalio/api/workflowservice/v1/service.rb +23 -0
  56. data/lib/temporalio/api/workflowservice.rb +3 -0
  57. data/lib/temporalio/api.rb +13 -0
  58. data/lib/temporalio/cancellation.rb +150 -0
  59. data/lib/temporalio/client/activity_id_reference.rb +32 -0
  60. data/lib/temporalio/client/async_activity_handle.rb +110 -0
  61. data/lib/temporalio/client/connection/cloud_service.rb +648 -0
  62. data/lib/temporalio/client/connection/operator_service.rb +249 -0
  63. data/lib/temporalio/client/connection/service.rb +41 -0
  64. data/lib/temporalio/client/connection/workflow_service.rb +1218 -0
  65. data/lib/temporalio/client/connection.rb +270 -0
  66. data/lib/temporalio/client/interceptor.rb +316 -0
  67. data/lib/temporalio/client/workflow_execution.rb +103 -0
  68. data/lib/temporalio/client/workflow_execution_count.rb +36 -0
  69. data/lib/temporalio/client/workflow_execution_status.rb +18 -0
  70. data/lib/temporalio/client/workflow_handle.rb +446 -0
  71. data/lib/temporalio/client/workflow_query_reject_condition.rb +14 -0
  72. data/lib/temporalio/client/workflow_update_handle.rb +67 -0
  73. data/lib/temporalio/client/workflow_update_wait_stage.rb +17 -0
  74. data/lib/temporalio/client.rb +404 -0
  75. data/lib/temporalio/common_enums.rb +24 -0
  76. data/lib/temporalio/converters/data_converter.rb +102 -0
  77. data/lib/temporalio/converters/failure_converter.rb +200 -0
  78. data/lib/temporalio/converters/payload_codec.rb +26 -0
  79. data/lib/temporalio/converters/payload_converter/binary_null.rb +34 -0
  80. data/lib/temporalio/converters/payload_converter/binary_plain.rb +35 -0
  81. data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +42 -0
  82. data/lib/temporalio/converters/payload_converter/composite.rb +62 -0
  83. data/lib/temporalio/converters/payload_converter/encoding.rb +35 -0
  84. data/lib/temporalio/converters/payload_converter/json_plain.rb +44 -0
  85. data/lib/temporalio/converters/payload_converter/json_protobuf.rb +41 -0
  86. data/lib/temporalio/converters/payload_converter.rb +73 -0
  87. data/lib/temporalio/converters.rb +9 -0
  88. data/lib/temporalio/error/failure.rb +219 -0
  89. data/lib/temporalio/error.rb +147 -0
  90. data/lib/temporalio/internal/bridge/3.1/temporalio_bridge.bundle +0 -0
  91. data/lib/temporalio/internal/bridge/3.2/temporalio_bridge.bundle +0 -0
  92. data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.bundle +0 -0
  93. data/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +34 -0
  94. data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +31 -0
  95. data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +33 -0
  96. data/lib/temporalio/internal/bridge/api/common/common.rb +26 -0
  97. data/lib/temporalio/internal/bridge/api/core_interface.rb +36 -0
  98. data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +27 -0
  99. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +52 -0
  100. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +54 -0
  101. data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +30 -0
  102. data/lib/temporalio/internal/bridge/api.rb +3 -0
  103. data/lib/temporalio/internal/bridge/client.rb +90 -0
  104. data/lib/temporalio/internal/bridge/runtime.rb +53 -0
  105. data/lib/temporalio/internal/bridge/testing.rb +46 -0
  106. data/lib/temporalio/internal/bridge/worker.rb +83 -0
  107. data/lib/temporalio/internal/bridge.rb +36 -0
  108. data/lib/temporalio/internal/client/implementation.rb +525 -0
  109. data/lib/temporalio/internal/proto_utils.rb +54 -0
  110. data/lib/temporalio/internal/worker/activity_worker.rb +345 -0
  111. data/lib/temporalio/internal/worker/multi_runner.rb +169 -0
  112. data/lib/temporalio/internal.rb +7 -0
  113. data/lib/temporalio/retry_policy.rb +51 -0
  114. data/lib/temporalio/runtime.rb +271 -0
  115. data/lib/temporalio/scoped_logger.rb +96 -0
  116. data/lib/temporalio/search_attributes.rb +300 -0
  117. data/lib/temporalio/testing/activity_environment.rb +132 -0
  118. data/lib/temporalio/testing/workflow_environment.rb +137 -0
  119. data/lib/temporalio/testing.rb +10 -0
  120. data/lib/temporalio/version.rb +5 -0
  121. data/lib/temporalio/worker/activity_executor/fiber.rb +49 -0
  122. data/lib/temporalio/worker/activity_executor/thread_pool.rb +254 -0
  123. data/lib/temporalio/worker/activity_executor.rb +55 -0
  124. data/lib/temporalio/worker/interceptor.rb +88 -0
  125. data/lib/temporalio/worker/tuner.rb +151 -0
  126. data/lib/temporalio/worker.rb +426 -0
  127. data/lib/temporalio/workflow_history.rb +22 -0
  128. data/lib/temporalio.rb +7 -0
  129. data/temporalio.gemspec +28 -0
  130. metadata +191 -0
@@ -0,0 +1,525 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'google/protobuf/well_known_types'
4
+ require 'securerandom'
5
+ require 'temporalio/api'
6
+ require 'temporalio/client/activity_id_reference'
7
+ require 'temporalio/client/async_activity_handle'
8
+ require 'temporalio/client/connection'
9
+ require 'temporalio/client/interceptor'
10
+ require 'temporalio/client/workflow_execution'
11
+ require 'temporalio/client/workflow_execution_count'
12
+ require 'temporalio/client/workflow_handle'
13
+ require 'temporalio/common_enums'
14
+ require 'temporalio/converters'
15
+ require 'temporalio/error'
16
+ require 'temporalio/error/failure'
17
+ require 'temporalio/internal/proto_utils'
18
+ require 'temporalio/runtime'
19
+ require 'temporalio/search_attributes'
20
+
21
+ module Temporalio
22
+ module Internal
23
+ module Client
24
+ class Implementation < Temporalio::Client::Interceptor::Outbound
25
+ def initialize(client)
26
+ super(nil)
27
+ @client = client
28
+ end
29
+
30
+ def start_workflow(input)
31
+ # TODO(cretz): Signal/update with start
32
+ req = Api::WorkflowService::V1::StartWorkflowExecutionRequest.new(
33
+ request_id: SecureRandom.uuid,
34
+ namespace: @client.namespace,
35
+ workflow_type: Api::Common::V1::WorkflowType.new(name: input.workflow.to_s),
36
+ workflow_id: input.workflow_id,
37
+ task_queue: Api::TaskQueue::V1::TaskQueue.new(name: input.task_queue.to_s),
38
+ input: @client.data_converter.to_payloads(input.args),
39
+ workflow_execution_timeout: ProtoUtils.seconds_to_duration(input.execution_timeout),
40
+ workflow_run_timeout: ProtoUtils.seconds_to_duration(input.run_timeout),
41
+ workflow_task_timeout: ProtoUtils.seconds_to_duration(input.task_timeout),
42
+ identity: @client.connection.identity,
43
+ workflow_id_reuse_policy: input.id_reuse_policy,
44
+ workflow_id_conflict_policy: input.id_conflict_policy,
45
+ retry_policy: input.retry_policy&.to_proto,
46
+ cron_schedule: input.cron_schedule,
47
+ memo: ProtoUtils.memo_to_proto(input.memo, @client.data_converter),
48
+ search_attributes: input.search_attributes&.to_proto,
49
+ workflow_start_delay: ProtoUtils.seconds_to_duration(input.start_delay),
50
+ request_eager_execution: input.request_eager_start,
51
+ header: input.headers
52
+ )
53
+
54
+ # Send request
55
+ begin
56
+ resp = @client.workflow_service.start_workflow_execution(
57
+ req,
58
+ rpc_retry: true,
59
+ rpc_metadata: input.rpc_metadata,
60
+ rpc_timeout: input.rpc_timeout
61
+ )
62
+ rescue Error::RPCError => e
63
+ # Unpack and raise already started if that's the error, otherwise default raise
64
+ if e.code == Error::RPCError::Code::ALREADY_EXISTS && e.grpc_status.details.first
65
+ details = e.grpc_status.details.first.unpack(
66
+ Api::ErrorDetails::V1::WorkflowExecutionAlreadyStartedFailure
67
+ )
68
+ if details
69
+ raise Error::WorkflowAlreadyStartedError.new(
70
+ workflow_id: req.workflow_id,
71
+ workflow_type: req.workflow_type.name,
72
+ run_id: details.run_id
73
+ )
74
+ end
75
+ end
76
+ raise
77
+ end
78
+
79
+ # Return handle
80
+ Temporalio::Client::WorkflowHandle.new(
81
+ client: @client,
82
+ id: input.workflow_id,
83
+ run_id: nil,
84
+ result_run_id: resp.run_id,
85
+ first_execution_run_id: resp.run_id
86
+ )
87
+ end
88
+
89
+ def list_workflows(input)
90
+ Enumerator.new do |yielder|
91
+ req = Api::WorkflowService::V1::ListWorkflowExecutionsRequest.new(
92
+ namespace: @client.namespace,
93
+ query: input.query || ''
94
+ )
95
+ loop do
96
+ resp = @client.workflow_service.list_workflow_executions(
97
+ req,
98
+ rpc_retry: true,
99
+ rpc_metadata: input.rpc_metadata,
100
+ rpc_timeout: input.rpc_timeout
101
+ )
102
+ resp.executions.each do |raw_info|
103
+ yielder << Temporalio::Client::WorkflowExecution.new(raw_info, @client.data_converter)
104
+ end
105
+ break if resp.next_page_token.empty?
106
+
107
+ req.next_page_token = resp.next_page_token
108
+ end
109
+ end
110
+ end
111
+
112
+ def count_workflows(input)
113
+ resp = @client.workflow_service.count_workflow_executions(
114
+ Api::WorkflowService::V1::CountWorkflowExecutionsRequest.new(
115
+ namespace: @client.namespace,
116
+ query: input.query || ''
117
+ ),
118
+ rpc_retry: true,
119
+ rpc_metadata: input.rpc_metadata,
120
+ rpc_timeout: input.rpc_timeout
121
+ )
122
+ Temporalio::Client::WorkflowExecutionCount.new(
123
+ resp.count,
124
+ resp.groups.map do |group|
125
+ Temporalio::Client::WorkflowExecutionCount::AggregationGroup.new(
126
+ group.count,
127
+ group.group_values.map { |payload| SearchAttributes.value_from_payload(payload) }
128
+ )
129
+ end
130
+ )
131
+ end
132
+
133
+ def describe_workflow(input)
134
+ resp = @client.workflow_service.describe_workflow_execution(
135
+ Api::WorkflowService::V1::DescribeWorkflowExecutionRequest.new(
136
+ namespace: @client.namespace,
137
+ execution: Api::Common::V1::WorkflowExecution.new(
138
+ workflow_id: input.workflow_id,
139
+ run_id: input.run_id || ''
140
+ )
141
+ ),
142
+ rpc_retry: true,
143
+ rpc_metadata: input.rpc_metadata,
144
+ rpc_timeout: input.rpc_timeout
145
+ )
146
+ Temporalio::Client::WorkflowExecution::Description.new(resp, @client.data_converter)
147
+ end
148
+
149
+ def fetch_workflow_history_events(input)
150
+ Enumerator.new do |yielder|
151
+ req = Api::WorkflowService::V1::GetWorkflowExecutionHistoryRequest.new(
152
+ namespace: @client.namespace,
153
+ execution: Api::Common::V1::WorkflowExecution.new(
154
+ workflow_id: input.workflow_id,
155
+ run_id: input.run_id || ''
156
+ ),
157
+ wait_new_event: input.wait_new_event,
158
+ history_event_filter_type: input.event_filter_type,
159
+ skip_archival: input.skip_archival
160
+ )
161
+ loop do
162
+ resp = @client.workflow_service.get_workflow_execution_history(
163
+ req,
164
+ rpc_retry: true,
165
+ rpc_metadata: input.rpc_metadata,
166
+ rpc_timeout: input.rpc_timeout
167
+ )
168
+ resp.history&.events&.each { |event| yielder << event }
169
+ break if resp.next_page_token.empty?
170
+
171
+ req.next_page_token = resp.next_page_token
172
+ end
173
+ end
174
+ end
175
+
176
+ def signal_workflow(input)
177
+ @client.workflow_service.signal_workflow_execution(
178
+ Api::WorkflowService::V1::SignalWorkflowExecutionRequest.new(
179
+ namespace: @client.namespace,
180
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
181
+ workflow_id: input.workflow_id,
182
+ run_id: input.run_id || ''
183
+ ),
184
+ signal_name: input.signal,
185
+ input: @client.data_converter.to_payloads(input.args),
186
+ header: input.headers,
187
+ identity: @client.connection.identity,
188
+ request_id: SecureRandom.uuid
189
+ ),
190
+ rpc_retry: true,
191
+ rpc_metadata: input.rpc_metadata,
192
+ rpc_timeout: input.rpc_timeout
193
+ )
194
+ nil
195
+ end
196
+
197
+ def query_workflow(input)
198
+ begin
199
+ resp = @client.workflow_service.query_workflow(
200
+ Api::WorkflowService::V1::QueryWorkflowRequest.new(
201
+ namespace: @client.namespace,
202
+ execution: Api::Common::V1::WorkflowExecution.new(
203
+ workflow_id: input.workflow_id,
204
+ run_id: input.run_id || ''
205
+ ),
206
+ query: Api::Query::V1::WorkflowQuery.new(
207
+ query_type: input.query,
208
+ query_args: @client.data_converter.to_payloads(input.args),
209
+ header: input.headers
210
+ ),
211
+ query_reject_condition: input.reject_condition || 0
212
+ ),
213
+ rpc_retry: true,
214
+ rpc_metadata: input.rpc_metadata,
215
+ rpc_timeout: input.rpc_timeout
216
+ )
217
+ rescue Error::RPCError => e
218
+ # If the status is INVALID_ARGUMENT, we can assume it's a query failed
219
+ # error
220
+ raise Error::WorkflowQueryFailedError, e.message if e.code == Error::RPCError::Code::INVALID_ARGUMENT
221
+
222
+ raise
223
+ end
224
+ unless resp.query_rejected.nil?
225
+ raise Error::WorkflowQueryRejectedError.new(status: ProtoUtils.enum_to_int(
226
+ Api::Enums::V1::WorkflowExecutionStatus, resp.query_rejected.status
227
+ ))
228
+ end
229
+
230
+ results = @client.data_converter.from_payloads(resp.query_result)
231
+ warn("Expected 0 or 1 query result, got #{results.size}") if results.size > 1
232
+ results&.first
233
+ end
234
+
235
+ def start_workflow_update(input)
236
+ if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::ADMITTED
237
+ raise ArgumentError, 'ADMITTED wait stage not supported'
238
+ end
239
+
240
+ req = Api::WorkflowService::V1::UpdateWorkflowExecutionRequest.new(
241
+ namespace: @client.namespace,
242
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
243
+ workflow_id: input.workflow_id,
244
+ run_id: input.run_id || ''
245
+ ),
246
+ request: Api::Update::V1::Request.new(
247
+ meta: Api::Update::V1::Meta.new(
248
+ update_id: input.update_id,
249
+ identity: @client.connection.identity
250
+ ),
251
+ input: Api::Update::V1::Input.new(
252
+ name: input.update,
253
+ args: @client.data_converter.to_payloads(input.args),
254
+ header: input.headers
255
+ )
256
+ ),
257
+ wait_policy: Api::Update::V1::WaitPolicy.new(
258
+ lifecycle_stage: input.wait_for_stage
259
+ )
260
+ )
261
+
262
+ # Repeatedly try to invoke start until the update reaches user-provided
263
+ # wait stage or is at least ACCEPTED (as of the time of this writing,
264
+ # the user cannot specify sooner than ACCEPTED)
265
+ # @type var resp: untyped
266
+ resp = nil
267
+ loop do
268
+ resp = @client.workflow_service.update_workflow_execution(
269
+ req,
270
+ rpc_retry: true,
271
+ rpc_metadata: input.rpc_metadata,
272
+ rpc_timeout: input.rpc_timeout
273
+ )
274
+
275
+ # We're only done if the response stage is after the requested stage
276
+ # or the response stage is accepted
277
+ if resp.stage >= req.wait_policy.lifecycle_stage ||
278
+ resp.stage >= Temporalio::Client::WorkflowUpdateWaitStage::ACCEPTED
279
+ break
280
+ end
281
+ rescue Error::RPCError => e
282
+ # Deadline exceeded or cancel is a special error type
283
+ if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELLED
284
+ raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
285
+ end
286
+
287
+ raise
288
+ end
289
+
290
+ # If the user wants to wait until completed, we must poll until outcome
291
+ # if not already there
292
+ if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED && !resp.outcome
293
+ resp.outcome = @client._impl.poll_workflow_update(
294
+ Temporalio::Client::Interceptor::PollWorkflowUpdateInput.new(
295
+ workflow_id: input.workflow_id,
296
+ run_id: input.run_id,
297
+ update_id: input.update_id,
298
+ rpc_metadata: input.rpc_metadata,
299
+ rpc_timeout: input.rpc_timeout
300
+ )
301
+ )
302
+ end
303
+
304
+ Temporalio::Client::WorkflowUpdateHandle.new(
305
+ client: @client,
306
+ id: input.update_id,
307
+ workflow_id: input.workflow_id,
308
+ workflow_run_id: input.run_id,
309
+ known_outcome: resp.outcome
310
+ )
311
+ end
312
+
313
+ def poll_workflow_update(input)
314
+ req = Api::WorkflowService::V1::PollWorkflowExecutionUpdateRequest.new(
315
+ namespace: @client.namespace,
316
+ update_ref: Api::Update::V1::UpdateRef.new(
317
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
318
+ workflow_id: input.workflow_id,
319
+ run_id: input.run_id || ''
320
+ ),
321
+ update_id: input.update_id
322
+ ),
323
+ identity: @client.connection.identity,
324
+ wait_policy: Api::Update::V1::WaitPolicy.new(
325
+ lifecycle_stage: Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED
326
+ )
327
+ )
328
+
329
+ # Continue polling as long as we have no outcome
330
+ loop do
331
+ resp = @client.workflow_service.poll_workflow_execution_update(
332
+ req,
333
+ rpc_retry: true,
334
+ rpc_metadata: input.rpc_metadata,
335
+ rpc_timeout: input.rpc_timeout
336
+ )
337
+ return resp.outcome if resp.outcome
338
+ rescue Error::RPCError => e
339
+ # Deadline exceeded or cancel is a special error type
340
+ if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELLED
341
+ raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
342
+ end
343
+
344
+ raise
345
+ end
346
+ end
347
+
348
+ def cancel_workflow(input)
349
+ @client.workflow_service.request_cancel_workflow_execution(
350
+ Api::WorkflowService::V1::RequestCancelWorkflowExecutionRequest.new(
351
+ namespace: @client.namespace,
352
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
353
+ workflow_id: input.workflow_id,
354
+ run_id: input.run_id || ''
355
+ ),
356
+ first_execution_run_id: input.first_execution_run_id,
357
+ identity: @client.connection.identity,
358
+ request_id: SecureRandom.uuid
359
+ ),
360
+ rpc_retry: true,
361
+ rpc_metadata: input.rpc_metadata,
362
+ rpc_timeout: input.rpc_timeout
363
+ )
364
+ nil
365
+ end
366
+
367
+ def terminate_workflow(input)
368
+ @client.workflow_service.terminate_workflow_execution(
369
+ Api::WorkflowService::V1::TerminateWorkflowExecutionRequest.new(
370
+ namespace: @client.namespace,
371
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
372
+ workflow_id: input.workflow_id,
373
+ run_id: input.run_id || ''
374
+ ),
375
+ reason: input.reason || '',
376
+ first_execution_run_id: input.first_execution_run_id,
377
+ details: @client.data_converter.to_payloads(input.details),
378
+ identity: @client.connection.identity
379
+ ),
380
+ rpc_retry: true,
381
+ rpc_metadata: input.rpc_metadata,
382
+ rpc_timeout: input.rpc_timeout
383
+ )
384
+ nil
385
+ end
386
+
387
+ def heartbeat_async_activity(input)
388
+ resp = if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
389
+ @client.workflow_service.record_activity_task_heartbeat_by_id(
390
+ Api::WorkflowService::V1::RecordActivityTaskHeartbeatByIdRequest.new(
391
+ workflow_id: input.task_token_or_id_reference.workflow_id,
392
+ run_id: input.task_token_or_id_reference.run_id,
393
+ activity_id: input.task_token_or_id_reference.activity_id,
394
+ namespace: @client.namespace,
395
+ identity: @client.connection.identity,
396
+ details: @client.data_converter.to_payloads(input.details)
397
+ ),
398
+ rpc_retry: true,
399
+ rpc_metadata: input.rpc_metadata,
400
+ rpc_timeout: input.rpc_timeout
401
+ )
402
+ else
403
+ @client.workflow_service.record_activity_task_heartbeat(
404
+ Api::WorkflowService::V1::RecordActivityTaskHeartbeatRequest.new(
405
+ task_token: input.task_token_or_id_reference,
406
+ namespace: @client.namespace,
407
+ identity: @client.connection.identity,
408
+ details: @client.data_converter.to_payloads(input.details)
409
+ ),
410
+ rpc_retry: true,
411
+ rpc_metadata: input.rpc_metadata,
412
+ rpc_timeout: input.rpc_timeout
413
+ )
414
+ end
415
+ raise Error::AsyncActivityCanceledError if resp.cancel_requested
416
+
417
+ nil
418
+ end
419
+
420
+ def complete_async_activity(input)
421
+ if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
422
+ @client.workflow_service.respond_activity_task_completed_by_id(
423
+ Api::WorkflowService::V1::RespondActivityTaskCompletedByIdRequest.new(
424
+ workflow_id: input.task_token_or_id_reference.workflow_id,
425
+ run_id: input.task_token_or_id_reference.run_id,
426
+ activity_id: input.task_token_or_id_reference.activity_id,
427
+ namespace: @client.namespace,
428
+ identity: @client.connection.identity,
429
+ result: @client.data_converter.to_payloads([input.result])
430
+ ),
431
+ rpc_retry: true,
432
+ rpc_metadata: input.rpc_metadata,
433
+ rpc_timeout: input.rpc_timeout
434
+ )
435
+ else
436
+ @client.workflow_service.respond_activity_task_completed(
437
+ Api::WorkflowService::V1::RespondActivityTaskCompletedRequest.new(
438
+ task_token: input.task_token_or_id_reference,
439
+ namespace: @client.namespace,
440
+ identity: @client.connection.identity,
441
+ result: @client.data_converter.to_payloads([input.result])
442
+ ),
443
+ rpc_retry: true,
444
+ rpc_metadata: input.rpc_metadata,
445
+ rpc_timeout: input.rpc_timeout
446
+ )
447
+ end
448
+ nil
449
+ end
450
+
451
+ def fail_async_activity(input)
452
+ if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
453
+ @client.workflow_service.respond_activity_task_failed_by_id(
454
+ Api::WorkflowService::V1::RespondActivityTaskFailedByIdRequest.new(
455
+ workflow_id: input.task_token_or_id_reference.workflow_id,
456
+ run_id: input.task_token_or_id_reference.run_id,
457
+ activity_id: input.task_token_or_id_reference.activity_id,
458
+ namespace: @client.namespace,
459
+ identity: @client.connection.identity,
460
+ failure: @client.data_converter.to_failure(input.error),
461
+ last_heartbeat_details: if input.last_heartbeat_details.empty?
462
+ nil
463
+ else
464
+ @client.data_converter.to_payloads(input.last_heartbeat_details)
465
+ end
466
+ ),
467
+ rpc_retry: true,
468
+ rpc_metadata: input.rpc_metadata,
469
+ rpc_timeout: input.rpc_timeout
470
+ )
471
+ else
472
+ @client.workflow_service.respond_activity_task_failed(
473
+ Api::WorkflowService::V1::RespondActivityTaskFailedRequest.new(
474
+ task_token: input.task_token_or_id_reference,
475
+ namespace: @client.namespace,
476
+ identity: @client.connection.identity,
477
+ failure: @client.data_converter.to_failure(input.error),
478
+ last_heartbeat_details: if input.last_heartbeat_details.empty?
479
+ nil
480
+ else
481
+ @client.data_converter.to_payloads(input.last_heartbeat_details)
482
+ end
483
+ ),
484
+ rpc_retry: true,
485
+ rpc_metadata: input.rpc_metadata,
486
+ rpc_timeout: input.rpc_timeout
487
+ )
488
+ end
489
+ nil
490
+ end
491
+
492
+ def report_cancellation_async_activity(input)
493
+ if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
494
+ @client.workflow_service.respond_activity_task_canceled_by_id(
495
+ Api::WorkflowService::V1::RespondActivityTaskCanceledByIdRequest.new(
496
+ workflow_id: input.task_token_or_id_reference.workflow_id,
497
+ run_id: input.task_token_or_id_reference.run_id,
498
+ activity_id: input.task_token_or_id_reference.activity_id,
499
+ namespace: @client.namespace,
500
+ identity: @client.connection.identity,
501
+ details: @client.data_converter.to_payloads(input.details)
502
+ ),
503
+ rpc_retry: true,
504
+ rpc_metadata: input.rpc_metadata,
505
+ rpc_timeout: input.rpc_timeout
506
+ )
507
+ else
508
+ @client.workflow_service.respond_activity_task_canceled(
509
+ Api::WorkflowService::V1::RespondActivityTaskCanceledRequest.new(
510
+ task_token: input.task_token_or_id_reference,
511
+ namespace: @client.namespace,
512
+ identity: @client.connection.identity,
513
+ details: @client.data_converter.to_payloads(input.details)
514
+ ),
515
+ rpc_retry: true,
516
+ rpc_metadata: input.rpc_metadata,
517
+ rpc_timeout: input.rpc_timeout
518
+ )
519
+ end
520
+ nil
521
+ end
522
+ end
523
+ end
524
+ end
525
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'temporalio/api'
4
+
5
+ module Temporalio
6
+ module Internal
7
+ module ProtoUtils
8
+ def self.seconds_to_duration(seconds_float)
9
+ return nil if seconds_float.nil?
10
+
11
+ seconds = seconds_float.to_i
12
+ nanos = ((seconds_float - seconds) * 1_000_000_000).round
13
+ Google::Protobuf::Duration.new(seconds:, nanos:)
14
+ end
15
+
16
+ def self.memo_to_proto(hash, converter)
17
+ return nil if hash.nil?
18
+
19
+ Api::Common::V1::Memo.new(fields: hash.transform_values { |val| converter.to_payload(val) })
20
+ end
21
+
22
+ def self.memo_from_proto(memo, converter)
23
+ return nil if memo.nil?
24
+
25
+ memo.fields.each_with_object({}) { |(key, val), h| h[key] = converter.from_payload(val) } # rubocop:disable Style/HashTransformValues
26
+ end
27
+
28
+ def self.string_or(str, default = nil)
29
+ str && !str.empty? ? str : default
30
+ end
31
+
32
+ def self.enum_to_int(enum_mod, enum_val, zero_means_nil: false)
33
+ # Per https://protobuf.dev/reference/ruby/ruby-generated/#enum when
34
+ # enums are read back, they are symbols if they are known or number
35
+ # otherwise
36
+ enum_val = enum_mod.resolve(enum_val) || raise('Unexpected missing symbol') if enum_val.is_a?(Symbol)
37
+ enum_val = nil if zero_means_nil && enum_val.zero?
38
+ enum_val
39
+ end
40
+
41
+ def self.convert_from_payload_array(converter, payloads)
42
+ return [] if payloads.empty?
43
+
44
+ converter.from_payloads(Api::Common::V1::Payloads.new(payloads:))
45
+ end
46
+
47
+ def self.convert_to_payload_array(converter, values)
48
+ return [] if values.empty?
49
+
50
+ converter.to_payloads(values).payloads.to_ary
51
+ end
52
+ end
53
+ end
54
+ end