clara-temporalio 0.4.3-arm64-darwin

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.
Files changed (190) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +2 -0
  3. data/Gemfile +27 -0
  4. data/Rakefile +101 -0
  5. data/lib/temporalio/activity/cancellation_details.rb +58 -0
  6. data/lib/temporalio/activity/complete_async_error.rb +11 -0
  7. data/lib/temporalio/activity/context.rb +131 -0
  8. data/lib/temporalio/activity/definition.rb +197 -0
  9. data/lib/temporalio/activity/info.rb +70 -0
  10. data/lib/temporalio/activity.rb +14 -0
  11. data/lib/temporalio/api/activity/v1/message.rb +25 -0
  12. data/lib/temporalio/api/batch/v1/message.rb +38 -0
  13. data/lib/temporalio/api/cloud/account/v1/message.rb +28 -0
  14. data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +135 -0
  15. data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +25 -0
  16. data/lib/temporalio/api/cloud/cloudservice.rb +3 -0
  17. data/lib/temporalio/api/cloud/identity/v1/message.rb +46 -0
  18. data/lib/temporalio/api/cloud/namespace/v1/message.rb +46 -0
  19. data/lib/temporalio/api/cloud/nexus/v1/message.rb +32 -0
  20. data/lib/temporalio/api/cloud/operation/v1/message.rb +28 -0
  21. data/lib/temporalio/api/cloud/region/v1/message.rb +24 -0
  22. data/lib/temporalio/api/cloud/resource/v1/message.rb +23 -0
  23. data/lib/temporalio/api/cloud/sink/v1/message.rb +24 -0
  24. data/lib/temporalio/api/cloud/usage/v1/message.rb +31 -0
  25. data/lib/temporalio/api/command/v1/message.rb +46 -0
  26. data/lib/temporalio/api/common/v1/grpc_status.rb +23 -0
  27. data/lib/temporalio/api/common/v1/message.rb +49 -0
  28. data/lib/temporalio/api/deployment/v1/message.rb +39 -0
  29. data/lib/temporalio/api/enums/v1/batch_operation.rb +22 -0
  30. data/lib/temporalio/api/enums/v1/command_type.rb +21 -0
  31. data/lib/temporalio/api/enums/v1/common.rb +28 -0
  32. data/lib/temporalio/api/enums/v1/deployment.rb +23 -0
  33. data/lib/temporalio/api/enums/v1/event_type.rb +21 -0
  34. data/lib/temporalio/api/enums/v1/failed_cause.rb +26 -0
  35. data/lib/temporalio/api/enums/v1/namespace.rb +23 -0
  36. data/lib/temporalio/api/enums/v1/nexus.rb +21 -0
  37. data/lib/temporalio/api/enums/v1/query.rb +22 -0
  38. data/lib/temporalio/api/enums/v1/reset.rb +23 -0
  39. data/lib/temporalio/api/enums/v1/schedule.rb +21 -0
  40. data/lib/temporalio/api/enums/v1/task_queue.rb +25 -0
  41. data/lib/temporalio/api/enums/v1/update.rb +22 -0
  42. data/lib/temporalio/api/enums/v1/workflow.rb +31 -0
  43. data/lib/temporalio/api/errordetails/v1/message.rb +44 -0
  44. data/lib/temporalio/api/export/v1/message.rb +24 -0
  45. data/lib/temporalio/api/failure/v1/message.rb +38 -0
  46. data/lib/temporalio/api/filter/v1/message.rb +27 -0
  47. data/lib/temporalio/api/history/v1/message.rb +94 -0
  48. data/lib/temporalio/api/namespace/v1/message.rb +31 -0
  49. data/lib/temporalio/api/nexus/v1/message.rb +41 -0
  50. data/lib/temporalio/api/operatorservice/v1/request_response.rb +49 -0
  51. data/lib/temporalio/api/operatorservice/v1/service.rb +23 -0
  52. data/lib/temporalio/api/operatorservice.rb +3 -0
  53. data/lib/temporalio/api/payload_visitor.rb +1668 -0
  54. data/lib/temporalio/api/protocol/v1/message.rb +23 -0
  55. data/lib/temporalio/api/query/v1/message.rb +28 -0
  56. data/lib/temporalio/api/replication/v1/message.rb +26 -0
  57. data/lib/temporalio/api/rules/v1/message.rb +27 -0
  58. data/lib/temporalio/api/schedule/v1/message.rb +43 -0
  59. data/lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb +25 -0
  60. data/lib/temporalio/api/sdk/v1/task_complete_metadata.rb +21 -0
  61. data/lib/temporalio/api/sdk/v1/user_metadata.rb +23 -0
  62. data/lib/temporalio/api/sdk/v1/workflow_metadata.rb +23 -0
  63. data/lib/temporalio/api/taskqueue/v1/message.rb +48 -0
  64. data/lib/temporalio/api/testservice/v1/request_response.rb +31 -0
  65. data/lib/temporalio/api/testservice/v1/service.rb +23 -0
  66. data/lib/temporalio/api/update/v1/message.rb +33 -0
  67. data/lib/temporalio/api/version/v1/message.rb +26 -0
  68. data/lib/temporalio/api/workflow/v1/message.rb +63 -0
  69. data/lib/temporalio/api/workflowservice/v1/request_response.rb +244 -0
  70. data/lib/temporalio/api/workflowservice/v1/service.rb +23 -0
  71. data/lib/temporalio/api/workflowservice.rb +3 -0
  72. data/lib/temporalio/api.rb +15 -0
  73. data/lib/temporalio/cancellation.rb +170 -0
  74. data/lib/temporalio/client/activity_id_reference.rb +32 -0
  75. data/lib/temporalio/client/async_activity_handle.rb +85 -0
  76. data/lib/temporalio/client/connection/cloud_service.rb +786 -0
  77. data/lib/temporalio/client/connection/operator_service.rb +201 -0
  78. data/lib/temporalio/client/connection/service.rb +42 -0
  79. data/lib/temporalio/client/connection/test_service.rb +111 -0
  80. data/lib/temporalio/client/connection/workflow_service.rb +1326 -0
  81. data/lib/temporalio/client/connection.rb +316 -0
  82. data/lib/temporalio/client/interceptor.rb +457 -0
  83. data/lib/temporalio/client/schedule.rb +991 -0
  84. data/lib/temporalio/client/schedule_handle.rb +126 -0
  85. data/lib/temporalio/client/with_start_workflow_operation.rb +115 -0
  86. data/lib/temporalio/client/workflow_execution.rb +119 -0
  87. data/lib/temporalio/client/workflow_execution_count.rb +36 -0
  88. data/lib/temporalio/client/workflow_execution_status.rb +18 -0
  89. data/lib/temporalio/client/workflow_handle.rb +389 -0
  90. data/lib/temporalio/client/workflow_query_reject_condition.rb +14 -0
  91. data/lib/temporalio/client/workflow_update_handle.rb +65 -0
  92. data/lib/temporalio/client/workflow_update_wait_stage.rb +17 -0
  93. data/lib/temporalio/client.rb +625 -0
  94. data/lib/temporalio/common_enums.rb +55 -0
  95. data/lib/temporalio/contrib/open_telemetry.rb +469 -0
  96. data/lib/temporalio/converters/data_converter.rb +99 -0
  97. data/lib/temporalio/converters/failure_converter.rb +205 -0
  98. data/lib/temporalio/converters/payload_codec.rb +26 -0
  99. data/lib/temporalio/converters/payload_converter/binary_null.rb +34 -0
  100. data/lib/temporalio/converters/payload_converter/binary_plain.rb +35 -0
  101. data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +42 -0
  102. data/lib/temporalio/converters/payload_converter/composite.rb +66 -0
  103. data/lib/temporalio/converters/payload_converter/encoding.rb +35 -0
  104. data/lib/temporalio/converters/payload_converter/json_plain.rb +44 -0
  105. data/lib/temporalio/converters/payload_converter/json_protobuf.rb +41 -0
  106. data/lib/temporalio/converters/payload_converter.rb +71 -0
  107. data/lib/temporalio/converters/raw_value.rb +20 -0
  108. data/lib/temporalio/converters.rb +9 -0
  109. data/lib/temporalio/error/failure.rb +237 -0
  110. data/lib/temporalio/error.rb +156 -0
  111. data/lib/temporalio/internal/bridge/3.2/temporalio_bridge.bundle +0 -0
  112. data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.bundle +0 -0
  113. data/lib/temporalio/internal/bridge/3.4/temporalio_bridge.bundle +0 -0
  114. data/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +34 -0
  115. data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +32 -0
  116. data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +33 -0
  117. data/lib/temporalio/internal/bridge/api/common/common.rb +27 -0
  118. data/lib/temporalio/internal/bridge/api/core_interface.rb +40 -0
  119. data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +27 -0
  120. data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +34 -0
  121. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +56 -0
  122. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +58 -0
  123. data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +31 -0
  124. data/lib/temporalio/internal/bridge/api.rb +3 -0
  125. data/lib/temporalio/internal/bridge/client.rb +95 -0
  126. data/lib/temporalio/internal/bridge/runtime.rb +56 -0
  127. data/lib/temporalio/internal/bridge/testing.rb +69 -0
  128. data/lib/temporalio/internal/bridge/worker.rb +109 -0
  129. data/lib/temporalio/internal/bridge.rb +36 -0
  130. data/lib/temporalio/internal/client/implementation.rb +926 -0
  131. data/lib/temporalio/internal/metric.rb +122 -0
  132. data/lib/temporalio/internal/proto_utils.rb +165 -0
  133. data/lib/temporalio/internal/worker/activity_worker.rb +448 -0
  134. data/lib/temporalio/internal/worker/multi_runner.rb +213 -0
  135. data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +54 -0
  136. data/lib/temporalio/internal/worker/workflow_instance/context.rb +391 -0
  137. data/lib/temporalio/internal/worker/workflow_instance/details.rb +49 -0
  138. data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +32 -0
  139. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +22 -0
  140. data/lib/temporalio/internal/worker/workflow_instance/handler_execution.rb +25 -0
  141. data/lib/temporalio/internal/worker/workflow_instance/handler_hash.rb +41 -0
  142. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +97 -0
  143. data/lib/temporalio/internal/worker/workflow_instance/inbound_implementation.rb +62 -0
  144. data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +404 -0
  145. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +37 -0
  146. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_metric.rb +40 -0
  147. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +183 -0
  148. data/lib/temporalio/internal/worker/workflow_instance.rb +800 -0
  149. data/lib/temporalio/internal/worker/workflow_worker.rb +249 -0
  150. data/lib/temporalio/internal.rb +7 -0
  151. data/lib/temporalio/metric.rb +109 -0
  152. data/lib/temporalio/priority.rb +59 -0
  153. data/lib/temporalio/retry_policy.rb +74 -0
  154. data/lib/temporalio/runtime/metric_buffer.rb +94 -0
  155. data/lib/temporalio/runtime.rb +352 -0
  156. data/lib/temporalio/scoped_logger.rb +96 -0
  157. data/lib/temporalio/search_attributes.rb +356 -0
  158. data/lib/temporalio/testing/activity_environment.rb +175 -0
  159. data/lib/temporalio/testing/workflow_environment.rb +406 -0
  160. data/lib/temporalio/testing.rb +10 -0
  161. data/lib/temporalio/version.rb +5 -0
  162. data/lib/temporalio/versioning_override.rb +55 -0
  163. data/lib/temporalio/worker/activity_executor/fiber.rb +49 -0
  164. data/lib/temporalio/worker/activity_executor/thread_pool.rb +46 -0
  165. data/lib/temporalio/worker/activity_executor.rb +55 -0
  166. data/lib/temporalio/worker/deployment_options.rb +45 -0
  167. data/lib/temporalio/worker/interceptor.rb +367 -0
  168. data/lib/temporalio/worker/poller_behavior.rb +61 -0
  169. data/lib/temporalio/worker/thread_pool.rb +237 -0
  170. data/lib/temporalio/worker/tuner.rb +189 -0
  171. data/lib/temporalio/worker/workflow_executor/thread_pool.rb +236 -0
  172. data/lib/temporalio/worker/workflow_executor.rb +26 -0
  173. data/lib/temporalio/worker/workflow_replayer.rb +349 -0
  174. data/lib/temporalio/worker.rb +633 -0
  175. data/lib/temporalio/worker_deployment_version.rb +67 -0
  176. data/lib/temporalio/workflow/activity_cancellation_type.rb +20 -0
  177. data/lib/temporalio/workflow/child_workflow_cancellation_type.rb +21 -0
  178. data/lib/temporalio/workflow/child_workflow_handle.rb +43 -0
  179. data/lib/temporalio/workflow/definition.rb +680 -0
  180. data/lib/temporalio/workflow/external_workflow_handle.rb +41 -0
  181. data/lib/temporalio/workflow/future.rb +151 -0
  182. data/lib/temporalio/workflow/handler_unfinished_policy.rb +13 -0
  183. data/lib/temporalio/workflow/info.rb +107 -0
  184. data/lib/temporalio/workflow/parent_close_policy.rb +19 -0
  185. data/lib/temporalio/workflow/update_info.rb +20 -0
  186. data/lib/temporalio/workflow.rb +594 -0
  187. data/lib/temporalio/workflow_history.rb +47 -0
  188. data/lib/temporalio.rb +12 -0
  189. data/temporalio.gemspec +31 -0
  190. metadata +267 -0
@@ -0,0 +1,926 @@
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/schedule'
11
+ require 'temporalio/client/schedule_handle'
12
+ require 'temporalio/client/with_start_workflow_operation'
13
+ require 'temporalio/client/workflow_execution'
14
+ require 'temporalio/client/workflow_execution_count'
15
+ require 'temporalio/client/workflow_handle'
16
+ require 'temporalio/common_enums'
17
+ require 'temporalio/converters'
18
+ require 'temporalio/error'
19
+ require 'temporalio/error/failure'
20
+ require 'temporalio/internal/proto_utils'
21
+ require 'temporalio/runtime'
22
+ require 'temporalio/search_attributes'
23
+ require 'temporalio/workflow/definition'
24
+
25
+ module Temporalio
26
+ module Internal
27
+ module Client
28
+ class Implementation < Temporalio::Client::Interceptor::Outbound
29
+ def self.with_default_rpc_options(user_rpc_options)
30
+ # If the user did not provide an override_retry, we need to make sure
31
+ # we use an option set that has it as "true"
32
+ if user_rpc_options.nil?
33
+ user_rpc_options = @always_retry_options ||= Temporalio::Client::RPCOptions.new(override_retry: true)
34
+ elsif !user_rpc_options.is_a?(Temporalio::Client::RPCOptions)
35
+ raise ArgumentError, 'rpc_options must be RPCOptions'
36
+ elsif user_rpc_options.override_retry.nil?
37
+ # Copy and set as true
38
+ user_rpc_options = user_rpc_options.dup
39
+ user_rpc_options.override_retry = true
40
+ end
41
+ user_rpc_options
42
+ end
43
+
44
+ def initialize(client)
45
+ super(nil) # steep:ignore
46
+ @client = client
47
+ end
48
+
49
+ def start_workflow(input)
50
+ req = Api::WorkflowService::V1::StartWorkflowExecutionRequest.new(
51
+ request_id: SecureRandom.uuid,
52
+ namespace: @client.namespace,
53
+ workflow_type: Api::Common::V1::WorkflowType.new(name: input.workflow),
54
+ workflow_id: input.workflow_id,
55
+ task_queue: Api::TaskQueue::V1::TaskQueue.new(name: input.task_queue.to_s),
56
+ input: @client.data_converter.to_payloads(input.args),
57
+ workflow_execution_timeout: ProtoUtils.seconds_to_duration(input.execution_timeout),
58
+ workflow_run_timeout: ProtoUtils.seconds_to_duration(input.run_timeout),
59
+ workflow_task_timeout: ProtoUtils.seconds_to_duration(input.task_timeout),
60
+ identity: @client.connection.identity,
61
+ workflow_id_reuse_policy: input.id_reuse_policy,
62
+ workflow_id_conflict_policy: input.id_conflict_policy,
63
+ retry_policy: input.retry_policy&._to_proto,
64
+ cron_schedule: input.cron_schedule,
65
+ memo: ProtoUtils.memo_to_proto(input.memo, @client.data_converter),
66
+ search_attributes: input.search_attributes&._to_proto,
67
+ workflow_start_delay: ProtoUtils.seconds_to_duration(input.start_delay),
68
+ request_eager_execution: input.request_eager_start,
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
75
+ )
76
+
77
+ # Send request
78
+ begin
79
+ resp = @client.workflow_service.start_workflow_execution(
80
+ req,
81
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
82
+ )
83
+ rescue Error::RPCError => e
84
+ # Unpack and raise already started if that's the error, otherwise default raise
85
+ if e.code == Error::RPCError::Code::ALREADY_EXISTS && e.grpc_status.details.first
86
+ details = e.grpc_status.details.first.unpack(
87
+ Api::ErrorDetails::V1::WorkflowExecutionAlreadyStartedFailure
88
+ )
89
+ if details
90
+ raise Error::WorkflowAlreadyStartedError.new(
91
+ workflow_id: req.workflow_id,
92
+ workflow_type: req.workflow_type.name,
93
+ run_id: details.run_id
94
+ )
95
+ end
96
+ end
97
+ raise
98
+ end
99
+
100
+ # Return handle
101
+ Temporalio::Client::WorkflowHandle.new(
102
+ client: @client,
103
+ id: input.workflow_id,
104
+ run_id: nil,
105
+ result_run_id: resp.run_id,
106
+ first_execution_run_id: resp.run_id
107
+ )
108
+ end
109
+
110
+ def start_update_with_start_workflow(input)
111
+ raise ArgumentError, 'Start operation is required' unless input.start_workflow_operation
112
+
113
+ if input.start_workflow_operation.options.id_conflict_policy == WorkflowIDConflictPolicy::UNSPECIFIED
114
+ raise ArgumentError, 'ID conflict policy is required in start operation'
115
+ end
116
+
117
+ # Try to mark used before using
118
+ input.start_workflow_operation._mark_used
119
+
120
+ # Build request
121
+ start_options = input.start_workflow_operation.options
122
+ start_req = _start_workflow_request_from_with_start_options(
123
+ Api::WorkflowService::V1::StartWorkflowExecutionRequest, start_options
124
+ )
125
+ req = Api::WorkflowService::V1::ExecuteMultiOperationRequest.new(
126
+ namespace: @client.namespace,
127
+ operations: [
128
+ Api::WorkflowService::V1::ExecuteMultiOperationRequest::Operation.new(start_workflow: start_req),
129
+ Api::WorkflowService::V1::ExecuteMultiOperationRequest::Operation.new(
130
+ update_workflow: Api::WorkflowService::V1::UpdateWorkflowExecutionRequest.new(
131
+ namespace: @client.namespace,
132
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
133
+ workflow_id: start_options.id
134
+ ),
135
+ request: Api::Update::V1::Request.new(
136
+ meta: Api::Update::V1::Meta.new(
137
+ update_id: input.update_id,
138
+ identity: @client.connection.identity
139
+ ),
140
+ input: Api::Update::V1::Input.new(
141
+ name: input.update,
142
+ args: @client.data_converter.to_payloads(input.args),
143
+ header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
144
+ )
145
+ ),
146
+ wait_policy: Api::Update::V1::WaitPolicy.new(
147
+ lifecycle_stage: input.wait_for_stage
148
+ )
149
+ )
150
+ )
151
+ ]
152
+ )
153
+
154
+ # Continually try to start until an exception occurs, the user-asked stage is reached, or the stage is
155
+ # accepted. But we will set the workflow handle as soon as we can.
156
+ # @type var update_resp: untyped
157
+ update_resp = nil
158
+ run_id = nil
159
+ begin
160
+ loop do
161
+ resp = @client.workflow_service.execute_multi_operation(
162
+ req, rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
163
+ )
164
+ run_id = resp.responses.first.start_workflow.run_id
165
+ # Set workflow handle (no-op if already set)
166
+ input.start_workflow_operation._set_workflow_handle(
167
+ Temporalio::Client::WorkflowHandle.new(
168
+ client: @client,
169
+ id: start_options.id,
170
+ run_id: nil,
171
+ result_run_id: run_id,
172
+ first_execution_run_id: run_id
173
+ )
174
+ )
175
+ update_resp = resp.responses.last.update_workflow
176
+
177
+ # We're only done if the response stage is at least accepted
178
+ if update_resp && Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage.resolve(update_resp.stage) >=
179
+ Temporalio::Client::WorkflowUpdateWaitStage::ACCEPTED
180
+ break
181
+ end
182
+ end
183
+
184
+ # If the user wants to wait until completed, we must poll until outcome if not already there
185
+ if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED && update_resp.outcome
186
+ update_resp.outcome = @client._impl.poll_workflow_update(
187
+ Temporalio::Client::Interceptor::PollWorkflowUpdateInput.new(
188
+ workflow_id: start_options.id,
189
+ run_id:,
190
+ update_id: input.update_id,
191
+ rpc_options: input.rpc_options
192
+ )
193
+ )
194
+ end
195
+ rescue Error => e
196
+ # If this is a multi-operation failure, set exception to the first present, non-OK, non-aborted error
197
+ if e.is_a?(Error::RPCError)
198
+ multi_err = e.grpc_status.details&.first&.unpack(Api::ErrorDetails::V1::MultiOperationExecutionFailure)
199
+ if multi_err
200
+ non_aborted = multi_err.statuses.find do |s|
201
+ # Exists, not-ok, not-aborted
202
+ s && s.code != Error::RPCError::Code::OK &&
203
+ !s.details&.first&.is(Api::Failure::V1::MultiOperationExecutionAborted)
204
+ end
205
+ if non_aborted
206
+ e = Error::RPCError.new(
207
+ non_aborted.message,
208
+ code: non_aborted.code,
209
+ raw_grpc_status: Api::Common::V1::GrpcStatus.new(
210
+ code: non_aborted.code, message: non_aborted.message, details: non_aborted.details.to_a
211
+ )
212
+ )
213
+ end
214
+ end
215
+ end
216
+ if e.is_a?(Error::RPCError)
217
+ # Deadline exceeded or cancel is a special error type
218
+ if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELED
219
+ e = Error::WorkflowUpdateRPCTimeoutOrCanceledError.new
220
+ elsif e.code == Error::RPCError::Code::ALREADY_EXISTS && e.grpc_status.details.first
221
+ # Unpack and set already started if that's the error
222
+ details = e.grpc_status.details.first.unpack(
223
+ Api::ErrorDetails::V1::WorkflowExecutionAlreadyStartedFailure
224
+ )
225
+ if details
226
+ e = Error::WorkflowAlreadyStartedError.new(
227
+ workflow_id: start_options.id,
228
+ workflow_type: start_req.workflow_type,
229
+ run_id: details.run_id
230
+ )
231
+ end
232
+ end
233
+ end
234
+ # Cancel is a special type
235
+ e = Error::WorkflowUpdateRPCTimeoutOrCanceledError.new if e.is_a?(Error::CanceledError)
236
+ # Before we raise here, we want to try to set the start operation exception (no-op if already set with a
237
+ # handle)
238
+ input.start_workflow_operation._set_workflow_handle(e)
239
+ raise e
240
+ end
241
+
242
+ # Return handle
243
+ Temporalio::Client::WorkflowUpdateHandle.new(
244
+ client: @client,
245
+ id: input.update_id,
246
+ workflow_id: start_options.id,
247
+ workflow_run_id: run_id,
248
+ known_outcome: update_resp.outcome
249
+ )
250
+ end
251
+
252
+ def signal_with_start_workflow(input)
253
+ raise ArgumentError, 'Start operation is required' unless input.start_workflow_operation
254
+
255
+ # Try to mark used before using
256
+ input.start_workflow_operation._mark_used
257
+
258
+ # Build req
259
+ start_options = input.start_workflow_operation.options
260
+ req = _start_workflow_request_from_with_start_options(
261
+ Api::WorkflowService::V1::SignalWithStartWorkflowExecutionRequest, start_options
262
+ )
263
+ req.signal_name = input.signal
264
+ req.signal_input = @client.data_converter.to_payloads(input.args)
265
+
266
+ # Send request
267
+ begin
268
+ resp = @client.workflow_service.signal_with_start_workflow_execution(
269
+ req,
270
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
271
+ )
272
+ rescue Error::RPCError => e
273
+ # Unpack and raise already started if that's the error, otherwise default raise
274
+ if e.code == Error::RPCError::Code::ALREADY_EXISTS && e.grpc_status.details.first
275
+ details = e.grpc_status.details.first.unpack(
276
+ Api::ErrorDetails::V1::WorkflowExecutionAlreadyStartedFailure
277
+ )
278
+ if details
279
+ e = Error::WorkflowAlreadyStartedError.new(
280
+ workflow_id: req.workflow_id,
281
+ workflow_type: req.workflow_type.name,
282
+ run_id: details.run_id
283
+ )
284
+ end
285
+ end
286
+ # Before we raise here, we want to the start operation exception
287
+ input.start_workflow_operation._set_workflow_handle(e)
288
+ raise e
289
+ end
290
+
291
+ # Set handle and return handle
292
+ handle = Temporalio::Client::WorkflowHandle.new(
293
+ client: @client,
294
+ id: start_options.id,
295
+ run_id: nil,
296
+ result_run_id: resp.run_id,
297
+ first_execution_run_id: resp.run_id
298
+ )
299
+ input.start_workflow_operation._set_workflow_handle(handle)
300
+ handle
301
+ end
302
+
303
+ def _start_workflow_request_from_with_start_options(klass, start_options)
304
+ klass.new(
305
+ request_id: SecureRandom.uuid,
306
+ namespace: @client.namespace,
307
+ workflow_type: Api::Common::V1::WorkflowType.new(name: start_options.workflow),
308
+ workflow_id: start_options.id,
309
+ task_queue: Api::TaskQueue::V1::TaskQueue.new(name: start_options.task_queue.to_s),
310
+ input: @client.data_converter.to_payloads(start_options.args),
311
+ workflow_execution_timeout: ProtoUtils.seconds_to_duration(start_options.execution_timeout),
312
+ workflow_run_timeout: ProtoUtils.seconds_to_duration(start_options.run_timeout),
313
+ workflow_task_timeout: ProtoUtils.seconds_to_duration(start_options.task_timeout),
314
+ identity: @client.connection.identity,
315
+ workflow_id_reuse_policy: start_options.id_reuse_policy,
316
+ workflow_id_conflict_policy: start_options.id_conflict_policy,
317
+ retry_policy: start_options.retry_policy&._to_proto,
318
+ cron_schedule: start_options.cron_schedule,
319
+ memo: ProtoUtils.memo_to_proto(start_options.memo, @client.data_converter),
320
+ search_attributes: start_options.search_attributes&._to_proto,
321
+ workflow_start_delay: ProtoUtils.seconds_to_duration(start_options.start_delay),
322
+ user_metadata: ProtoUtils.to_user_metadata(
323
+ start_options.static_summary, start_options.static_details, @client.data_converter
324
+ ),
325
+ header: ProtoUtils.headers_to_proto(start_options.headers, @client.data_converter)
326
+ )
327
+ end
328
+
329
+ def list_workflows(input)
330
+ Enumerator.new do |yielder|
331
+ req = Api::WorkflowService::V1::ListWorkflowExecutionsRequest.new(
332
+ namespace: @client.namespace,
333
+ query: input.query || ''
334
+ )
335
+ loop do
336
+ resp = @client.workflow_service.list_workflow_executions(
337
+ req,
338
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
339
+ )
340
+ resp.executions.each do |raw_info|
341
+ yielder << Temporalio::Client::WorkflowExecution.new(raw_info, @client.data_converter)
342
+ end
343
+ break if resp.next_page_token.empty?
344
+
345
+ req.next_page_token = resp.next_page_token
346
+ end
347
+ end
348
+ end
349
+
350
+ def count_workflows(input)
351
+ resp = @client.workflow_service.count_workflow_executions(
352
+ Api::WorkflowService::V1::CountWorkflowExecutionsRequest.new(
353
+ namespace: @client.namespace,
354
+ query: input.query || ''
355
+ ),
356
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
357
+ )
358
+ Temporalio::Client::WorkflowExecutionCount.new(
359
+ resp.count,
360
+ resp.groups.map do |group|
361
+ Temporalio::Client::WorkflowExecutionCount::AggregationGroup.new(
362
+ group.count,
363
+ group.group_values.map { |payload| SearchAttributes._value_from_payload(payload) }
364
+ )
365
+ end
366
+ )
367
+ end
368
+
369
+ def describe_workflow(input)
370
+ resp = @client.workflow_service.describe_workflow_execution(
371
+ Api::WorkflowService::V1::DescribeWorkflowExecutionRequest.new(
372
+ namespace: @client.namespace,
373
+ execution: Api::Common::V1::WorkflowExecution.new(
374
+ workflow_id: input.workflow_id,
375
+ run_id: input.run_id || ''
376
+ )
377
+ ),
378
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
379
+ )
380
+ Temporalio::Client::WorkflowExecution::Description.new(resp, @client.data_converter)
381
+ end
382
+
383
+ def fetch_workflow_history_events(input)
384
+ Enumerator.new do |yielder|
385
+ req = Api::WorkflowService::V1::GetWorkflowExecutionHistoryRequest.new(
386
+ namespace: @client.namespace,
387
+ execution: Api::Common::V1::WorkflowExecution.new(
388
+ workflow_id: input.workflow_id,
389
+ run_id: input.run_id || ''
390
+ ),
391
+ wait_new_event: input.wait_new_event,
392
+ history_event_filter_type: input.event_filter_type,
393
+ skip_archival: input.skip_archival
394
+ )
395
+ loop do
396
+ resp = @client.workflow_service.get_workflow_execution_history(
397
+ req,
398
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
399
+ )
400
+ resp.history&.events&.each { |event| yielder << event }
401
+ break if resp.next_page_token.empty?
402
+
403
+ req.next_page_token = resp.next_page_token
404
+ end
405
+ end
406
+ end
407
+
408
+ def signal_workflow(input)
409
+ @client.workflow_service.signal_workflow_execution(
410
+ Api::WorkflowService::V1::SignalWorkflowExecutionRequest.new(
411
+ namespace: @client.namespace,
412
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
413
+ workflow_id: input.workflow_id,
414
+ run_id: input.run_id || ''
415
+ ),
416
+ signal_name: input.signal,
417
+ input: @client.data_converter.to_payloads(input.args),
418
+ header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter),
419
+ identity: @client.connection.identity,
420
+ request_id: SecureRandom.uuid
421
+ ),
422
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
423
+ )
424
+ nil
425
+ end
426
+
427
+ def query_workflow(input)
428
+ begin
429
+ resp = @client.workflow_service.query_workflow(
430
+ Api::WorkflowService::V1::QueryWorkflowRequest.new(
431
+ namespace: @client.namespace,
432
+ execution: Api::Common::V1::WorkflowExecution.new(
433
+ workflow_id: input.workflow_id,
434
+ run_id: input.run_id || ''
435
+ ),
436
+ query: Api::Query::V1::WorkflowQuery.new(
437
+ query_type: input.query,
438
+ query_args: @client.data_converter.to_payloads(input.args),
439
+ header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
440
+ ),
441
+ query_reject_condition: input.reject_condition || 0
442
+ ),
443
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
444
+ )
445
+ rescue Error::RPCError => e
446
+ # If the status is INVALID_ARGUMENT, we can assume it's a query failed
447
+ # error
448
+ raise Error::WorkflowQueryFailedError, e.message if e.code == Error::RPCError::Code::INVALID_ARGUMENT
449
+
450
+ raise
451
+ end
452
+ unless resp.query_rejected.nil?
453
+ raise Error::WorkflowQueryRejectedError.new(status: ProtoUtils.enum_to_int(
454
+ Api::Enums::V1::WorkflowExecutionStatus, resp.query_rejected.status
455
+ ))
456
+ end
457
+
458
+ results = @client.data_converter.from_payloads(resp.query_result)
459
+ warn("Expected 0 or 1 query result, got #{results.size}") if results.size > 1
460
+ results&.first
461
+ end
462
+
463
+ def start_workflow_update(input)
464
+ if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::ADMITTED
465
+ raise ArgumentError, 'ADMITTED wait stage not supported'
466
+ end
467
+
468
+ req = Api::WorkflowService::V1::UpdateWorkflowExecutionRequest.new(
469
+ namespace: @client.namespace,
470
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
471
+ workflow_id: input.workflow_id,
472
+ run_id: input.run_id || ''
473
+ ),
474
+ request: Api::Update::V1::Request.new(
475
+ meta: Api::Update::V1::Meta.new(
476
+ update_id: input.update_id,
477
+ identity: @client.connection.identity
478
+ ),
479
+ input: Api::Update::V1::Input.new(
480
+ name: input.update,
481
+ args: @client.data_converter.to_payloads(input.args),
482
+ header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
483
+ )
484
+ ),
485
+ wait_policy: Api::Update::V1::WaitPolicy.new(
486
+ lifecycle_stage: input.wait_for_stage
487
+ )
488
+ )
489
+
490
+ # Repeatedly try to invoke start until the update reaches user-provided
491
+ # wait stage or is at least ACCEPTED (as of the time of this writing,
492
+ # the user cannot specify sooner than ACCEPTED)
493
+ # @type var resp: untyped
494
+ resp = nil
495
+ expected_stage = ProtoUtils.enum_to_int(Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage,
496
+ req.wait_policy.lifecycle_stage)
497
+ accepted_stage = ProtoUtils.enum_to_int(Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage,
498
+ Temporalio::Client::WorkflowUpdateWaitStage::ACCEPTED)
499
+ loop do
500
+ resp = @client.workflow_service.update_workflow_execution(
501
+ req,
502
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
503
+ )
504
+
505
+ # We're only done if the response stage is after the requested stage
506
+ # or the response stage is accepted
507
+ actual_stage = ProtoUtils.enum_to_int(Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage, resp.stage)
508
+ break if actual_stage >= expected_stage || actual_stage >= accepted_stage
509
+ rescue Error::RPCError => e
510
+ # Deadline exceeded or cancel is a special error type
511
+ if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELED
512
+ raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
513
+ end
514
+
515
+ raise
516
+ rescue Error::CanceledError
517
+ raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
518
+ end
519
+
520
+ # If the user wants to wait until completed, we must poll until outcome
521
+ # if not already there
522
+ if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED && !resp.outcome
523
+ resp.outcome = @client._impl.poll_workflow_update(
524
+ Temporalio::Client::Interceptor::PollWorkflowUpdateInput.new(
525
+ workflow_id: input.workflow_id,
526
+ run_id: input.run_id,
527
+ update_id: input.update_id,
528
+ rpc_options: input.rpc_options
529
+ )
530
+ )
531
+ end
532
+
533
+ Temporalio::Client::WorkflowUpdateHandle.new(
534
+ client: @client,
535
+ id: input.update_id,
536
+ workflow_id: input.workflow_id,
537
+ workflow_run_id: input.run_id,
538
+ known_outcome: resp.outcome
539
+ )
540
+ end
541
+
542
+ def poll_workflow_update(input)
543
+ req = Api::WorkflowService::V1::PollWorkflowExecutionUpdateRequest.new(
544
+ namespace: @client.namespace,
545
+ update_ref: Api::Update::V1::UpdateRef.new(
546
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
547
+ workflow_id: input.workflow_id,
548
+ run_id: input.run_id || ''
549
+ ),
550
+ update_id: input.update_id
551
+ ),
552
+ identity: @client.connection.identity,
553
+ wait_policy: Api::Update::V1::WaitPolicy.new(
554
+ lifecycle_stage: Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED
555
+ )
556
+ )
557
+
558
+ # Continue polling as long as we have no outcome
559
+ loop do
560
+ resp = @client.workflow_service.poll_workflow_execution_update(
561
+ req,
562
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
563
+ )
564
+ return resp.outcome if resp.outcome
565
+ rescue Error::RPCError => e
566
+ # Deadline exceeded or cancel is a special error type
567
+ if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELED
568
+ raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
569
+ end
570
+
571
+ raise
572
+ end
573
+ end
574
+
575
+ def cancel_workflow(input)
576
+ @client.workflow_service.request_cancel_workflow_execution(
577
+ Api::WorkflowService::V1::RequestCancelWorkflowExecutionRequest.new(
578
+ namespace: @client.namespace,
579
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
580
+ workflow_id: input.workflow_id,
581
+ run_id: input.run_id || ''
582
+ ),
583
+ first_execution_run_id: input.first_execution_run_id,
584
+ identity: @client.connection.identity,
585
+ request_id: SecureRandom.uuid
586
+ ),
587
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
588
+ )
589
+ nil
590
+ end
591
+
592
+ def terminate_workflow(input)
593
+ @client.workflow_service.terminate_workflow_execution(
594
+ Api::WorkflowService::V1::TerminateWorkflowExecutionRequest.new(
595
+ namespace: @client.namespace,
596
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
597
+ workflow_id: input.workflow_id,
598
+ run_id: input.run_id || ''
599
+ ),
600
+ reason: input.reason || '',
601
+ first_execution_run_id: input.first_execution_run_id,
602
+ details: @client.data_converter.to_payloads(input.details),
603
+ identity: @client.connection.identity
604
+ ),
605
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
606
+ )
607
+ nil
608
+ end
609
+
610
+ def create_schedule(input)
611
+ if input.schedule.state.limited_actions && input.schedule.state.remaining_actions.zero?
612
+ raise 'Must set limited actions to false if there are no remaining actions set'
613
+ end
614
+ if !input.schedule.state.limited_actions && !input.schedule.state.remaining_actions.zero?
615
+ raise 'Must set limited actions to true if there are remaining actions set'
616
+ end
617
+
618
+ @client.workflow_service.create_schedule(
619
+ Api::WorkflowService::V1::CreateScheduleRequest.new(
620
+ namespace: @client.namespace,
621
+ schedule_id: input.id,
622
+ schedule: input.schedule._to_proto(@client.data_converter),
623
+ initial_patch: if input.trigger_immediately || !input.backfills.empty?
624
+ Api::Schedule::V1::SchedulePatch.new(
625
+ trigger_immediately: if input.trigger_immediately
626
+ Api::Schedule::V1::TriggerImmediatelyRequest.new(
627
+ overlap_policy: input.schedule.policy.overlap
628
+ )
629
+ end,
630
+ backfill_request: input.backfills.map(&:_to_proto)
631
+ )
632
+ end,
633
+ identity: @client.connection.identity,
634
+ request_id: SecureRandom.uuid,
635
+ memo: ProtoUtils.memo_to_proto(input.memo, @client.data_converter),
636
+ search_attributes: input.search_attributes&._to_proto
637
+ ),
638
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
639
+ )
640
+ Temporalio::Client::ScheduleHandle.new(client: @client, id: input.id)
641
+ rescue Error::RPCError => e
642
+ # Unpack and raise already started if that's the error, otherwise default raise
643
+ details = if e.code == Error::RPCError::Code::ALREADY_EXISTS && e.grpc_status.details.first
644
+ e.grpc_status.details.first.unpack(Api::ErrorDetails::V1::WorkflowExecutionAlreadyStartedFailure)
645
+ end
646
+ raise Error::ScheduleAlreadyRunningError if details
647
+
648
+ raise
649
+ end
650
+
651
+ def list_schedules(input)
652
+ Enumerator.new do |yielder|
653
+ req = Api::WorkflowService::V1::ListSchedulesRequest.new(
654
+ namespace: @client.namespace,
655
+ query: input.query || ''
656
+ )
657
+ loop do
658
+ resp = @client.workflow_service.list_schedules(
659
+ req,
660
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
661
+ )
662
+ resp.schedules.each do |raw_entry|
663
+ yielder << Temporalio::Client::Schedule::List::Description.new(
664
+ raw_entry:,
665
+ data_converter: @client.data_converter
666
+ )
667
+ end
668
+ break if resp.next_page_token.empty?
669
+
670
+ req.next_page_token = resp.next_page_token
671
+ end
672
+ end
673
+ end
674
+
675
+ def backfill_schedule(input)
676
+ @client.workflow_service.patch_schedule(
677
+ Api::WorkflowService::V1::PatchScheduleRequest.new(
678
+ namespace: @client.namespace,
679
+ schedule_id: input.id,
680
+ patch: Api::Schedule::V1::SchedulePatch.new(
681
+ backfill_request: input.backfills.map(&:_to_proto)
682
+ ),
683
+ identity: @client.connection.identity,
684
+ request_id: SecureRandom.uuid
685
+ ),
686
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
687
+ )
688
+ nil
689
+ end
690
+
691
+ def delete_schedule(input)
692
+ @client.workflow_service.delete_schedule(
693
+ Api::WorkflowService::V1::DeleteScheduleRequest.new(
694
+ namespace: @client.namespace,
695
+ schedule_id: input.id,
696
+ identity: @client.connection.identity
697
+ ),
698
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
699
+ )
700
+ nil
701
+ end
702
+
703
+ def describe_schedule(input)
704
+ Temporalio::Client::Schedule::Description.new(
705
+ id: input.id,
706
+ raw_description: @client.workflow_service.describe_schedule(
707
+ Api::WorkflowService::V1::DescribeScheduleRequest.new(
708
+ namespace: @client.namespace,
709
+ schedule_id: input.id
710
+ ),
711
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
712
+ ),
713
+ data_converter: @client.data_converter
714
+ )
715
+ end
716
+
717
+ def pause_schedule(input)
718
+ @client.workflow_service.patch_schedule(
719
+ Api::WorkflowService::V1::PatchScheduleRequest.new(
720
+ namespace: @client.namespace,
721
+ schedule_id: input.id,
722
+ patch: Api::Schedule::V1::SchedulePatch.new(pause: input.note),
723
+ identity: @client.connection.identity,
724
+ request_id: SecureRandom.uuid
725
+ ),
726
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
727
+ )
728
+ nil
729
+ end
730
+
731
+ def trigger_schedule(input)
732
+ @client.workflow_service.patch_schedule(
733
+ Api::WorkflowService::V1::PatchScheduleRequest.new(
734
+ namespace: @client.namespace,
735
+ schedule_id: input.id,
736
+ patch: Api::Schedule::V1::SchedulePatch.new(
737
+ trigger_immediately: Api::Schedule::V1::TriggerImmediatelyRequest.new(
738
+ overlap_policy: input.overlap || 0
739
+ )
740
+ ),
741
+ identity: @client.connection.identity,
742
+ request_id: SecureRandom.uuid
743
+ ),
744
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
745
+ )
746
+ nil
747
+ end
748
+
749
+ def unpause_schedule(input)
750
+ @client.workflow_service.patch_schedule(
751
+ Api::WorkflowService::V1::PatchScheduleRequest.new(
752
+ namespace: @client.namespace,
753
+ schedule_id: input.id,
754
+ patch: Api::Schedule::V1::SchedulePatch.new(unpause: input.note),
755
+ identity: @client.connection.identity,
756
+ request_id: SecureRandom.uuid
757
+ ),
758
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
759
+ )
760
+ nil
761
+ end
762
+
763
+ def update_schedule(input)
764
+ # TODO(cretz): This is supposed to be a retry-conflict loop, but we do
765
+ # not yet have a way to know update failure is due to conflict token
766
+ # mismatch
767
+ update = input.updater.call(
768
+ Temporalio::Client::Schedule::Update::Input.new(
769
+ description: Temporalio::Client::Schedule::Description.new(
770
+ id: input.id,
771
+ raw_description: @client.workflow_service.describe_schedule(
772
+ Api::WorkflowService::V1::DescribeScheduleRequest.new(
773
+ namespace: @client.namespace,
774
+ schedule_id: input.id
775
+ ),
776
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
777
+ ),
778
+ data_converter: @client.data_converter
779
+ )
780
+ )
781
+ )
782
+ # Do nothing if update is nil, fail if not an expected update
783
+ return nil if update.nil?
784
+
785
+ unless update.is_a?(Temporalio::Client::Schedule::Update)
786
+ raise TypeError,
787
+ 'Expected result of update block to be a Schedule::Update'
788
+ end
789
+
790
+ @client.workflow_service.update_schedule(
791
+ Api::WorkflowService::V1::UpdateScheduleRequest.new(
792
+ namespace: @client.namespace,
793
+ schedule_id: input.id,
794
+ schedule: update.schedule._to_proto(@client.data_converter),
795
+ search_attributes: update.search_attributes&._to_proto,
796
+ identity: @client.connection.identity,
797
+ request_id: SecureRandom.uuid
798
+ ),
799
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
800
+ )
801
+ nil
802
+ end
803
+
804
+ def heartbeat_async_activity(input)
805
+ resp = if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
806
+ @client.workflow_service.record_activity_task_heartbeat_by_id(
807
+ Api::WorkflowService::V1::RecordActivityTaskHeartbeatByIdRequest.new(
808
+ workflow_id: input.task_token_or_id_reference.workflow_id,
809
+ run_id: input.task_token_or_id_reference.run_id,
810
+ activity_id: input.task_token_or_id_reference.activity_id,
811
+ namespace: @client.namespace,
812
+ identity: @client.connection.identity,
813
+ details: @client.data_converter.to_payloads(input.details)
814
+ ),
815
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
816
+ )
817
+ else
818
+ @client.workflow_service.record_activity_task_heartbeat(
819
+ Api::WorkflowService::V1::RecordActivityTaskHeartbeatRequest.new(
820
+ task_token: input.task_token_or_id_reference,
821
+ namespace: @client.namespace,
822
+ identity: @client.connection.identity,
823
+ details: @client.data_converter.to_payloads(input.details)
824
+ ),
825
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
826
+ )
827
+ end
828
+ raise Error::AsyncActivityCanceledError if resp.cancel_requested
829
+
830
+ nil
831
+ end
832
+
833
+ def complete_async_activity(input)
834
+ if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
835
+ @client.workflow_service.respond_activity_task_completed_by_id(
836
+ Api::WorkflowService::V1::RespondActivityTaskCompletedByIdRequest.new(
837
+ workflow_id: input.task_token_or_id_reference.workflow_id,
838
+ run_id: input.task_token_or_id_reference.run_id,
839
+ activity_id: input.task_token_or_id_reference.activity_id,
840
+ namespace: @client.namespace,
841
+ identity: @client.connection.identity,
842
+ result: @client.data_converter.to_payloads([input.result])
843
+ ),
844
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
845
+ )
846
+ else
847
+ @client.workflow_service.respond_activity_task_completed(
848
+ Api::WorkflowService::V1::RespondActivityTaskCompletedRequest.new(
849
+ task_token: input.task_token_or_id_reference,
850
+ namespace: @client.namespace,
851
+ identity: @client.connection.identity,
852
+ result: @client.data_converter.to_payloads([input.result])
853
+ ),
854
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
855
+ )
856
+ end
857
+ nil
858
+ end
859
+
860
+ def fail_async_activity(input)
861
+ if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
862
+ @client.workflow_service.respond_activity_task_failed_by_id(
863
+ Api::WorkflowService::V1::RespondActivityTaskFailedByIdRequest.new(
864
+ workflow_id: input.task_token_or_id_reference.workflow_id,
865
+ run_id: input.task_token_or_id_reference.run_id,
866
+ activity_id: input.task_token_or_id_reference.activity_id,
867
+ namespace: @client.namespace,
868
+ identity: @client.connection.identity,
869
+ failure: @client.data_converter.to_failure(input.error),
870
+ last_heartbeat_details: if input.last_heartbeat_details.empty?
871
+ nil
872
+ else
873
+ @client.data_converter.to_payloads(input.last_heartbeat_details)
874
+ end
875
+ ),
876
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
877
+ )
878
+ else
879
+ @client.workflow_service.respond_activity_task_failed(
880
+ Api::WorkflowService::V1::RespondActivityTaskFailedRequest.new(
881
+ task_token: input.task_token_or_id_reference,
882
+ namespace: @client.namespace,
883
+ identity: @client.connection.identity,
884
+ failure: @client.data_converter.to_failure(input.error),
885
+ last_heartbeat_details: if input.last_heartbeat_details.empty?
886
+ nil
887
+ else
888
+ @client.data_converter.to_payloads(input.last_heartbeat_details)
889
+ end
890
+ ),
891
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
892
+ )
893
+ end
894
+ nil
895
+ end
896
+
897
+ def report_cancellation_async_activity(input)
898
+ if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
899
+ @client.workflow_service.respond_activity_task_canceled_by_id(
900
+ Api::WorkflowService::V1::RespondActivityTaskCanceledByIdRequest.new(
901
+ workflow_id: input.task_token_or_id_reference.workflow_id,
902
+ run_id: input.task_token_or_id_reference.run_id,
903
+ activity_id: input.task_token_or_id_reference.activity_id,
904
+ namespace: @client.namespace,
905
+ identity: @client.connection.identity,
906
+ details: @client.data_converter.to_payloads(input.details)
907
+ ),
908
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
909
+ )
910
+ else
911
+ @client.workflow_service.respond_activity_task_canceled(
912
+ Api::WorkflowService::V1::RespondActivityTaskCanceledRequest.new(
913
+ task_token: input.task_token_or_id_reference,
914
+ namespace: @client.namespace,
915
+ identity: @client.connection.identity,
916
+ details: @client.data_converter.to_payloads(input.details)
917
+ ),
918
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
919
+ )
920
+ end
921
+ nil
922
+ end
923
+ end
924
+ end
925
+ end
926
+ end