amit-temporalio 0.3.1-x86_64-linux-musl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +2 -0
  3. data/Gemfile +23 -0
  4. data/Rakefile +101 -0
  5. data/lib/temporalio/activity/complete_async_error.rb +11 -0
  6. data/lib/temporalio/activity/context.rb +116 -0
  7. data/lib/temporalio/activity/definition.rb +189 -0
  8. data/lib/temporalio/activity/info.rb +64 -0
  9. data/lib/temporalio/activity.rb +12 -0
  10. data/lib/temporalio/api/activity/v1/message.rb +25 -0
  11. data/lib/temporalio/api/batch/v1/message.rb +31 -0
  12. data/lib/temporalio/api/cloud/account/v1/message.rb +28 -0
  13. data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +126 -0
  14. data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +25 -0
  15. data/lib/temporalio/api/cloud/cloudservice.rb +3 -0
  16. data/lib/temporalio/api/cloud/identity/v1/message.rb +41 -0
  17. data/lib/temporalio/api/cloud/namespace/v1/message.rb +42 -0
  18. data/lib/temporalio/api/cloud/nexus/v1/message.rb +31 -0
  19. data/lib/temporalio/api/cloud/operation/v1/message.rb +28 -0
  20. data/lib/temporalio/api/cloud/region/v1/message.rb +24 -0
  21. data/lib/temporalio/api/cloud/resource/v1/message.rb +23 -0
  22. data/lib/temporalio/api/cloud/sink/v1/message.rb +24 -0
  23. data/lib/temporalio/api/cloud/usage/v1/message.rb +31 -0
  24. data/lib/temporalio/api/command/v1/message.rb +46 -0
  25. data/lib/temporalio/api/common/v1/grpc_status.rb +23 -0
  26. data/lib/temporalio/api/common/v1/message.rb +47 -0
  27. data/lib/temporalio/api/enums/v1/batch_operation.rb +22 -0
  28. data/lib/temporalio/api/enums/v1/command_type.rb +21 -0
  29. data/lib/temporalio/api/enums/v1/common.rb +26 -0
  30. data/lib/temporalio/api/enums/v1/event_type.rb +21 -0
  31. data/lib/temporalio/api/enums/v1/failed_cause.rb +26 -0
  32. data/lib/temporalio/api/enums/v1/namespace.rb +23 -0
  33. data/lib/temporalio/api/enums/v1/query.rb +22 -0
  34. data/lib/temporalio/api/enums/v1/reset.rb +23 -0
  35. data/lib/temporalio/api/enums/v1/schedule.rb +21 -0
  36. data/lib/temporalio/api/enums/v1/task_queue.rb +25 -0
  37. data/lib/temporalio/api/enums/v1/update.rb +22 -0
  38. data/lib/temporalio/api/enums/v1/workflow.rb +30 -0
  39. data/lib/temporalio/api/errordetails/v1/message.rb +42 -0
  40. data/lib/temporalio/api/export/v1/message.rb +24 -0
  41. data/lib/temporalio/api/failure/v1/message.rb +35 -0
  42. data/lib/temporalio/api/filter/v1/message.rb +27 -0
  43. data/lib/temporalio/api/history/v1/message.rb +90 -0
  44. data/lib/temporalio/api/namespace/v1/message.rb +31 -0
  45. data/lib/temporalio/api/nexus/v1/message.rb +40 -0
  46. data/lib/temporalio/api/operatorservice/v1/request_response.rb +49 -0
  47. data/lib/temporalio/api/operatorservice/v1/service.rb +23 -0
  48. data/lib/temporalio/api/operatorservice.rb +3 -0
  49. data/lib/temporalio/api/payload_visitor.rb +1513 -0
  50. data/lib/temporalio/api/protocol/v1/message.rb +23 -0
  51. data/lib/temporalio/api/query/v1/message.rb +27 -0
  52. data/lib/temporalio/api/replication/v1/message.rb +26 -0
  53. data/lib/temporalio/api/schedule/v1/message.rb +43 -0
  54. data/lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb +25 -0
  55. data/lib/temporalio/api/sdk/v1/task_complete_metadata.rb +21 -0
  56. data/lib/temporalio/api/sdk/v1/user_metadata.rb +23 -0
  57. data/lib/temporalio/api/sdk/v1/workflow_metadata.rb +23 -0
  58. data/lib/temporalio/api/taskqueue/v1/message.rb +45 -0
  59. data/lib/temporalio/api/testservice/v1/request_response.rb +31 -0
  60. data/lib/temporalio/api/testservice/v1/service.rb +23 -0
  61. data/lib/temporalio/api/update/v1/message.rb +33 -0
  62. data/lib/temporalio/api/version/v1/message.rb +26 -0
  63. data/lib/temporalio/api/workflow/v1/message.rb +43 -0
  64. data/lib/temporalio/api/workflowservice/v1/request_response.rb +204 -0
  65. data/lib/temporalio/api/workflowservice/v1/service.rb +23 -0
  66. data/lib/temporalio/api/workflowservice.rb +3 -0
  67. data/lib/temporalio/api.rb +14 -0
  68. data/lib/temporalio/cancellation.rb +170 -0
  69. data/lib/temporalio/client/activity_id_reference.rb +32 -0
  70. data/lib/temporalio/client/async_activity_handle.rb +85 -0
  71. data/lib/temporalio/client/connection/cloud_service.rb +726 -0
  72. data/lib/temporalio/client/connection/operator_service.rb +201 -0
  73. data/lib/temporalio/client/connection/service.rb +42 -0
  74. data/lib/temporalio/client/connection/test_service.rb +111 -0
  75. data/lib/temporalio/client/connection/workflow_service.rb +1041 -0
  76. data/lib/temporalio/client/connection.rb +316 -0
  77. data/lib/temporalio/client/interceptor.rb +416 -0
  78. data/lib/temporalio/client/schedule.rb +967 -0
  79. data/lib/temporalio/client/schedule_handle.rb +126 -0
  80. data/lib/temporalio/client/workflow_execution.rb +100 -0
  81. data/lib/temporalio/client/workflow_execution_count.rb +36 -0
  82. data/lib/temporalio/client/workflow_execution_status.rb +18 -0
  83. data/lib/temporalio/client/workflow_handle.rb +389 -0
  84. data/lib/temporalio/client/workflow_query_reject_condition.rb +14 -0
  85. data/lib/temporalio/client/workflow_update_handle.rb +65 -0
  86. data/lib/temporalio/client/workflow_update_wait_stage.rb +17 -0
  87. data/lib/temporalio/client.rb +484 -0
  88. data/lib/temporalio/common_enums.rb +41 -0
  89. data/lib/temporalio/converters/data_converter.rb +99 -0
  90. data/lib/temporalio/converters/failure_converter.rb +202 -0
  91. data/lib/temporalio/converters/payload_codec.rb +26 -0
  92. data/lib/temporalio/converters/payload_converter/binary_null.rb +34 -0
  93. data/lib/temporalio/converters/payload_converter/binary_plain.rb +35 -0
  94. data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +42 -0
  95. data/lib/temporalio/converters/payload_converter/composite.rb +66 -0
  96. data/lib/temporalio/converters/payload_converter/encoding.rb +35 -0
  97. data/lib/temporalio/converters/payload_converter/json_plain.rb +44 -0
  98. data/lib/temporalio/converters/payload_converter/json_protobuf.rb +41 -0
  99. data/lib/temporalio/converters/payload_converter.rb +71 -0
  100. data/lib/temporalio/converters/raw_value.rb +20 -0
  101. data/lib/temporalio/converters.rb +9 -0
  102. data/lib/temporalio/error/failure.rb +219 -0
  103. data/lib/temporalio/error.rb +155 -0
  104. data/lib/temporalio/internal/bridge/3.2/temporalio_bridge.so +0 -0
  105. data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.so +0 -0
  106. data/lib/temporalio/internal/bridge/3.4/temporalio_bridge.so +0 -0
  107. data/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +34 -0
  108. data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +31 -0
  109. data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +33 -0
  110. data/lib/temporalio/internal/bridge/api/common/common.rb +26 -0
  111. data/lib/temporalio/internal/bridge/api/core_interface.rb +40 -0
  112. data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +27 -0
  113. data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +33 -0
  114. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +56 -0
  115. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +57 -0
  116. data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +30 -0
  117. data/lib/temporalio/internal/bridge/api.rb +3 -0
  118. data/lib/temporalio/internal/bridge/client.rb +95 -0
  119. data/lib/temporalio/internal/bridge/runtime.rb +53 -0
  120. data/lib/temporalio/internal/bridge/testing.rb +66 -0
  121. data/lib/temporalio/internal/bridge/worker.rb +85 -0
  122. data/lib/temporalio/internal/bridge.rb +36 -0
  123. data/lib/temporalio/internal/client/implementation.rb +700 -0
  124. data/lib/temporalio/internal/metric.rb +122 -0
  125. data/lib/temporalio/internal/proto_utils.rb +133 -0
  126. data/lib/temporalio/internal/worker/activity_worker.rb +376 -0
  127. data/lib/temporalio/internal/worker/multi_runner.rb +213 -0
  128. data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +54 -0
  129. data/lib/temporalio/internal/worker/workflow_instance/context.rb +333 -0
  130. data/lib/temporalio/internal/worker/workflow_instance/details.rb +44 -0
  131. data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +32 -0
  132. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +22 -0
  133. data/lib/temporalio/internal/worker/workflow_instance/handler_execution.rb +25 -0
  134. data/lib/temporalio/internal/worker/workflow_instance/handler_hash.rb +41 -0
  135. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +97 -0
  136. data/lib/temporalio/internal/worker/workflow_instance/inbound_implementation.rb +62 -0
  137. data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +415 -0
  138. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +37 -0
  139. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_metric.rb +40 -0
  140. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +163 -0
  141. data/lib/temporalio/internal/worker/workflow_instance.rb +730 -0
  142. data/lib/temporalio/internal/worker/workflow_worker.rb +236 -0
  143. data/lib/temporalio/internal.rb +7 -0
  144. data/lib/temporalio/metric.rb +109 -0
  145. data/lib/temporalio/retry_policy.rb +74 -0
  146. data/lib/temporalio/runtime.rb +314 -0
  147. data/lib/temporalio/scoped_logger.rb +96 -0
  148. data/lib/temporalio/search_attributes.rb +343 -0
  149. data/lib/temporalio/testing/activity_environment.rb +136 -0
  150. data/lib/temporalio/testing/workflow_environment.rb +383 -0
  151. data/lib/temporalio/testing.rb +10 -0
  152. data/lib/temporalio/version.rb +5 -0
  153. data/lib/temporalio/worker/activity_executor/fiber.rb +49 -0
  154. data/lib/temporalio/worker/activity_executor/thread_pool.rb +46 -0
  155. data/lib/temporalio/worker/activity_executor.rb +55 -0
  156. data/lib/temporalio/worker/interceptor.rb +362 -0
  157. data/lib/temporalio/worker/thread_pool.rb +237 -0
  158. data/lib/temporalio/worker/tuner.rb +189 -0
  159. data/lib/temporalio/worker/workflow_executor/thread_pool.rb +230 -0
  160. data/lib/temporalio/worker/workflow_executor.rb +26 -0
  161. data/lib/temporalio/worker/workflow_replayer.rb +343 -0
  162. data/lib/temporalio/worker.rb +569 -0
  163. data/lib/temporalio/workflow/activity_cancellation_type.rb +20 -0
  164. data/lib/temporalio/workflow/child_workflow_cancellation_type.rb +21 -0
  165. data/lib/temporalio/workflow/child_workflow_handle.rb +43 -0
  166. data/lib/temporalio/workflow/definition.rb +566 -0
  167. data/lib/temporalio/workflow/external_workflow_handle.rb +41 -0
  168. data/lib/temporalio/workflow/future.rb +151 -0
  169. data/lib/temporalio/workflow/handler_unfinished_policy.rb +13 -0
  170. data/lib/temporalio/workflow/info.rb +82 -0
  171. data/lib/temporalio/workflow/parent_close_policy.rb +19 -0
  172. data/lib/temporalio/workflow/update_info.rb +20 -0
  173. data/lib/temporalio/workflow.rb +529 -0
  174. data/lib/temporalio/workflow_history.rb +47 -0
  175. data/lib/temporalio.rb +11 -0
  176. data/temporalio.gemspec +28 -0
  177. metadata +238 -0
@@ -0,0 +1,700 @@
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/workflow_execution'
13
+ require 'temporalio/client/workflow_execution_count'
14
+ require 'temporalio/client/workflow_handle'
15
+ require 'temporalio/common_enums'
16
+ require 'temporalio/converters'
17
+ require 'temporalio/error'
18
+ require 'temporalio/error/failure'
19
+ require 'temporalio/internal/proto_utils'
20
+ require 'temporalio/runtime'
21
+ require 'temporalio/search_attributes'
22
+ require 'temporalio/workflow/definition'
23
+
24
+ module Temporalio
25
+ module Internal
26
+ module Client
27
+ class Implementation < Temporalio::Client::Interceptor::Outbound
28
+ def self.with_default_rpc_options(user_rpc_options)
29
+ # If the user did not provide an override_retry, we need to make sure
30
+ # we use an option set that has it as "true"
31
+ if user_rpc_options.nil?
32
+ user_rpc_options = @always_retry_options ||= Temporalio::Client::RPCOptions.new(override_retry: true)
33
+ elsif !user_rpc_options.is_a?(Temporalio::Client::RPCOptions)
34
+ raise ArgumentError, 'rpc_options must be RPCOptions'
35
+ elsif user_rpc_options.override_retry.nil?
36
+ # Copy and set as true
37
+ user_rpc_options = user_rpc_options.dup
38
+ user_rpc_options.override_retry = true
39
+ end
40
+ user_rpc_options
41
+ end
42
+
43
+ def initialize(client)
44
+ super(nil)
45
+ @client = client
46
+ end
47
+
48
+ def start_workflow(input)
49
+ # TODO(cretz): Signal/update with start
50
+ req = Api::WorkflowService::V1::StartWorkflowExecutionRequest.new(
51
+ request_id: SecureRandom.uuid,
52
+ namespace: @client.namespace,
53
+ workflow_type: Api::Common::V1::WorkflowType.new(
54
+ name: Workflow::Definition._workflow_type_from_workflow_parameter(input.workflow)
55
+ ),
56
+ workflow_id: input.workflow_id,
57
+ task_queue: Api::TaskQueue::V1::TaskQueue.new(name: input.task_queue.to_s),
58
+ input: @client.data_converter.to_payloads(input.args),
59
+ workflow_execution_timeout: ProtoUtils.seconds_to_duration(input.execution_timeout),
60
+ workflow_run_timeout: ProtoUtils.seconds_to_duration(input.run_timeout),
61
+ workflow_task_timeout: ProtoUtils.seconds_to_duration(input.task_timeout),
62
+ identity: @client.connection.identity,
63
+ workflow_id_reuse_policy: input.id_reuse_policy,
64
+ workflow_id_conflict_policy: input.id_conflict_policy,
65
+ retry_policy: input.retry_policy&._to_proto,
66
+ cron_schedule: input.cron_schedule,
67
+ memo: ProtoUtils.memo_to_proto(input.memo, @client.data_converter),
68
+ search_attributes: input.search_attributes&._to_proto,
69
+ workflow_start_delay: ProtoUtils.seconds_to_duration(input.start_delay),
70
+ request_eager_execution: input.request_eager_start,
71
+ header: ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
72
+ )
73
+
74
+ # Send request
75
+ begin
76
+ resp = @client.workflow_service.start_workflow_execution(
77
+ req,
78
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
79
+ )
80
+ rescue Error::RPCError => e
81
+ # Unpack and raise already started if that's the error, otherwise default raise
82
+ if e.code == Error::RPCError::Code::ALREADY_EXISTS && e.grpc_status.details.first
83
+ details = e.grpc_status.details.first.unpack(
84
+ Api::ErrorDetails::V1::WorkflowExecutionAlreadyStartedFailure
85
+ )
86
+ if details
87
+ raise Error::WorkflowAlreadyStartedError.new(
88
+ workflow_id: req.workflow_id,
89
+ workflow_type: req.workflow_type.name,
90
+ run_id: details.run_id
91
+ )
92
+ end
93
+ end
94
+ raise
95
+ end
96
+
97
+ # Return handle
98
+ Temporalio::Client::WorkflowHandle.new(
99
+ client: @client,
100
+ id: input.workflow_id,
101
+ run_id: nil,
102
+ result_run_id: resp.run_id,
103
+ first_execution_run_id: resp.run_id
104
+ )
105
+ end
106
+
107
+ def list_workflows(input)
108
+ Enumerator.new do |yielder|
109
+ req = Api::WorkflowService::V1::ListWorkflowExecutionsRequest.new(
110
+ namespace: @client.namespace,
111
+ query: input.query || ''
112
+ )
113
+ loop do
114
+ resp = @client.workflow_service.list_workflow_executions(
115
+ req,
116
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
117
+ )
118
+ resp.executions.each do |raw_info|
119
+ yielder << Temporalio::Client::WorkflowExecution.new(raw_info, @client.data_converter)
120
+ end
121
+ break if resp.next_page_token.empty?
122
+
123
+ req.next_page_token = resp.next_page_token
124
+ end
125
+ end
126
+ end
127
+
128
+ def count_workflows(input)
129
+ resp = @client.workflow_service.count_workflow_executions(
130
+ Api::WorkflowService::V1::CountWorkflowExecutionsRequest.new(
131
+ namespace: @client.namespace,
132
+ query: input.query || ''
133
+ ),
134
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
135
+ )
136
+ Temporalio::Client::WorkflowExecutionCount.new(
137
+ resp.count,
138
+ resp.groups.map do |group|
139
+ Temporalio::Client::WorkflowExecutionCount::AggregationGroup.new(
140
+ group.count,
141
+ group.group_values.map { |payload| SearchAttributes._value_from_payload(payload) }
142
+ )
143
+ end
144
+ )
145
+ end
146
+
147
+ def describe_workflow(input)
148
+ resp = @client.workflow_service.describe_workflow_execution(
149
+ Api::WorkflowService::V1::DescribeWorkflowExecutionRequest.new(
150
+ namespace: @client.namespace,
151
+ execution: Api::Common::V1::WorkflowExecution.new(
152
+ workflow_id: input.workflow_id,
153
+ run_id: input.run_id || ''
154
+ )
155
+ ),
156
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
157
+ )
158
+ Temporalio::Client::WorkflowExecution::Description.new(resp, @client.data_converter)
159
+ end
160
+
161
+ def fetch_workflow_history_events(input)
162
+ Enumerator.new do |yielder|
163
+ req = Api::WorkflowService::V1::GetWorkflowExecutionHistoryRequest.new(
164
+ namespace: @client.namespace,
165
+ execution: Api::Common::V1::WorkflowExecution.new(
166
+ workflow_id: input.workflow_id,
167
+ run_id: input.run_id || ''
168
+ ),
169
+ wait_new_event: input.wait_new_event,
170
+ history_event_filter_type: input.event_filter_type,
171
+ skip_archival: input.skip_archival
172
+ )
173
+ loop do
174
+ resp = @client.workflow_service.get_workflow_execution_history(
175
+ req,
176
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
177
+ )
178
+ resp.history&.events&.each { |event| yielder << event }
179
+ break if resp.next_page_token.empty?
180
+
181
+ req.next_page_token = resp.next_page_token
182
+ end
183
+ end
184
+ end
185
+
186
+ def signal_workflow(input)
187
+ @client.workflow_service.signal_workflow_execution(
188
+ Api::WorkflowService::V1::SignalWorkflowExecutionRequest.new(
189
+ namespace: @client.namespace,
190
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
191
+ workflow_id: input.workflow_id,
192
+ run_id: input.run_id || ''
193
+ ),
194
+ signal_name: Workflow::Definition::Signal._name_from_parameter(input.signal),
195
+ input: @client.data_converter.to_payloads(input.args),
196
+ header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter),
197
+ identity: @client.connection.identity,
198
+ request_id: SecureRandom.uuid
199
+ ),
200
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
201
+ )
202
+ nil
203
+ end
204
+
205
+ def query_workflow(input)
206
+ begin
207
+ resp = @client.workflow_service.query_workflow(
208
+ Api::WorkflowService::V1::QueryWorkflowRequest.new(
209
+ namespace: @client.namespace,
210
+ execution: Api::Common::V1::WorkflowExecution.new(
211
+ workflow_id: input.workflow_id,
212
+ run_id: input.run_id || ''
213
+ ),
214
+ query: Api::Query::V1::WorkflowQuery.new(
215
+ query_type: Workflow::Definition::Query._name_from_parameter(input.query),
216
+ query_args: @client.data_converter.to_payloads(input.args),
217
+ header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
218
+ ),
219
+ query_reject_condition: input.reject_condition || 0
220
+ ),
221
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
222
+ )
223
+ rescue Error::RPCError => e
224
+ # If the status is INVALID_ARGUMENT, we can assume it's a query failed
225
+ # error
226
+ raise Error::WorkflowQueryFailedError, e.message if e.code == Error::RPCError::Code::INVALID_ARGUMENT
227
+
228
+ raise
229
+ end
230
+ unless resp.query_rejected.nil?
231
+ raise Error::WorkflowQueryRejectedError.new(status: ProtoUtils.enum_to_int(
232
+ Api::Enums::V1::WorkflowExecutionStatus, resp.query_rejected.status
233
+ ))
234
+ end
235
+
236
+ results = @client.data_converter.from_payloads(resp.query_result)
237
+ warn("Expected 0 or 1 query result, got #{results.size}") if results.size > 1
238
+ results&.first
239
+ end
240
+
241
+ def start_workflow_update(input)
242
+ if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::ADMITTED
243
+ raise ArgumentError, 'ADMITTED wait stage not supported'
244
+ end
245
+
246
+ req = Api::WorkflowService::V1::UpdateWorkflowExecutionRequest.new(
247
+ namespace: @client.namespace,
248
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
249
+ workflow_id: input.workflow_id,
250
+ run_id: input.run_id || ''
251
+ ),
252
+ request: Api::Update::V1::Request.new(
253
+ meta: Api::Update::V1::Meta.new(
254
+ update_id: input.update_id,
255
+ identity: @client.connection.identity
256
+ ),
257
+ input: Api::Update::V1::Input.new(
258
+ name: Workflow::Definition::Update._name_from_parameter(input.update),
259
+ args: @client.data_converter.to_payloads(input.args),
260
+ header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
261
+ )
262
+ ),
263
+ wait_policy: Api::Update::V1::WaitPolicy.new(
264
+ lifecycle_stage: input.wait_for_stage
265
+ )
266
+ )
267
+
268
+ # Repeatedly try to invoke start until the update reaches user-provided
269
+ # wait stage or is at least ACCEPTED (as of the time of this writing,
270
+ # the user cannot specify sooner than ACCEPTED)
271
+ # @type var resp: untyped
272
+ resp = nil
273
+ loop do
274
+ resp = @client.workflow_service.update_workflow_execution(
275
+ req,
276
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
277
+ )
278
+
279
+ # We're only done if the response stage is after the requested stage
280
+ # or the response stage is accepted
281
+ if resp.stage >= req.wait_policy.lifecycle_stage ||
282
+ resp.stage >= Temporalio::Client::WorkflowUpdateWaitStage::ACCEPTED
283
+ break
284
+ end
285
+ rescue Error::RPCError => e
286
+ # Deadline exceeded or cancel is a special error type
287
+ if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELLED
288
+ raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
289
+ end
290
+
291
+ raise
292
+ end
293
+
294
+ # If the user wants to wait until completed, we must poll until outcome
295
+ # if not already there
296
+ if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED && !resp.outcome
297
+ resp.outcome = @client._impl.poll_workflow_update(
298
+ Temporalio::Client::Interceptor::PollWorkflowUpdateInput.new(
299
+ workflow_id: input.workflow_id,
300
+ run_id: input.run_id,
301
+ update_id: input.update_id,
302
+ rpc_options: input.rpc_options
303
+ )
304
+ )
305
+ end
306
+
307
+ Temporalio::Client::WorkflowUpdateHandle.new(
308
+ client: @client,
309
+ id: input.update_id,
310
+ workflow_id: input.workflow_id,
311
+ workflow_run_id: input.run_id,
312
+ known_outcome: resp.outcome
313
+ )
314
+ end
315
+
316
+ def poll_workflow_update(input)
317
+ req = Api::WorkflowService::V1::PollWorkflowExecutionUpdateRequest.new(
318
+ namespace: @client.namespace,
319
+ update_ref: Api::Update::V1::UpdateRef.new(
320
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
321
+ workflow_id: input.workflow_id,
322
+ run_id: input.run_id || ''
323
+ ),
324
+ update_id: input.update_id
325
+ ),
326
+ identity: @client.connection.identity,
327
+ wait_policy: Api::Update::V1::WaitPolicy.new(
328
+ lifecycle_stage: Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED
329
+ )
330
+ )
331
+
332
+ # Continue polling as long as we have no outcome
333
+ loop do
334
+ resp = @client.workflow_service.poll_workflow_execution_update(
335
+ req,
336
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
337
+ )
338
+ return resp.outcome if resp.outcome
339
+ rescue Error::RPCError => e
340
+ # Deadline exceeded or cancel is a special error type
341
+ if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELLED
342
+ raise Error::WorkflowUpdateRPCTimeoutOrCanceledError
343
+ end
344
+
345
+ raise
346
+ end
347
+ end
348
+
349
+ def cancel_workflow(input)
350
+ @client.workflow_service.request_cancel_workflow_execution(
351
+ Api::WorkflowService::V1::RequestCancelWorkflowExecutionRequest.new(
352
+ namespace: @client.namespace,
353
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
354
+ workflow_id: input.workflow_id,
355
+ run_id: input.run_id || ''
356
+ ),
357
+ first_execution_run_id: input.first_execution_run_id,
358
+ identity: @client.connection.identity,
359
+ request_id: SecureRandom.uuid
360
+ ),
361
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
362
+ )
363
+ nil
364
+ end
365
+
366
+ def terminate_workflow(input)
367
+ @client.workflow_service.terminate_workflow_execution(
368
+ Api::WorkflowService::V1::TerminateWorkflowExecutionRequest.new(
369
+ namespace: @client.namespace,
370
+ workflow_execution: Api::Common::V1::WorkflowExecution.new(
371
+ workflow_id: input.workflow_id,
372
+ run_id: input.run_id || ''
373
+ ),
374
+ reason: input.reason || '',
375
+ first_execution_run_id: input.first_execution_run_id,
376
+ details: @client.data_converter.to_payloads(input.details),
377
+ identity: @client.connection.identity
378
+ ),
379
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
380
+ )
381
+ nil
382
+ end
383
+
384
+ def create_schedule(input)
385
+ if input.schedule.state.limited_actions && input.schedule.state.remaining_actions.zero?
386
+ raise 'Must set limited actions to false if there are no remaining actions set'
387
+ end
388
+ if !input.schedule.state.limited_actions && !input.schedule.state.remaining_actions.zero?
389
+ raise 'Must set limited actions to true if there are remaining actions set'
390
+ end
391
+
392
+ @client.workflow_service.create_schedule(
393
+ Api::WorkflowService::V1::CreateScheduleRequest.new(
394
+ namespace: @client.namespace,
395
+ schedule_id: input.id,
396
+ schedule: input.schedule._to_proto(@client.data_converter),
397
+ initial_patch: if input.trigger_immediately || !input.backfills.empty?
398
+ Api::Schedule::V1::SchedulePatch.new(
399
+ trigger_immediately: if input.trigger_immediately
400
+ Api::Schedule::V1::TriggerImmediatelyRequest.new(
401
+ overlap_policy: input.schedule.policy.overlap
402
+ )
403
+ end,
404
+ backfill_request: input.backfills.map(&:_to_proto)
405
+ )
406
+ end,
407
+ identity: @client.connection.identity,
408
+ request_id: SecureRandom.uuid,
409
+ memo: ProtoUtils.memo_to_proto(input.memo, @client.data_converter),
410
+ search_attributes: input.search_attributes&._to_proto
411
+ ),
412
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
413
+ )
414
+ Temporalio::Client::ScheduleHandle.new(client: @client, id: input.id)
415
+ rescue Error::RPCError => e
416
+ # Unpack and raise already started if that's the error, otherwise default raise
417
+ details = if e.code == Error::RPCError::Code::ALREADY_EXISTS && e.grpc_status.details.first
418
+ e.grpc_status.details.first.unpack(Api::ErrorDetails::V1::WorkflowExecutionAlreadyStartedFailure)
419
+ end
420
+ raise Error::ScheduleAlreadyRunningError if details
421
+
422
+ raise
423
+ end
424
+
425
+ def list_schedules(input)
426
+ Enumerator.new do |yielder|
427
+ req = Api::WorkflowService::V1::ListSchedulesRequest.new(
428
+ namespace: @client.namespace,
429
+ query: input.query || ''
430
+ )
431
+ loop do
432
+ resp = @client.workflow_service.list_schedules(
433
+ req,
434
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
435
+ )
436
+ resp.schedules.each do |raw_entry|
437
+ yielder << Temporalio::Client::Schedule::List::Description.new(
438
+ raw_entry:,
439
+ data_converter: @client.data_converter
440
+ )
441
+ end
442
+ break if resp.next_page_token.empty?
443
+
444
+ req.next_page_token = resp.next_page_token
445
+ end
446
+ end
447
+ end
448
+
449
+ def backfill_schedule(input)
450
+ @client.workflow_service.patch_schedule(
451
+ Api::WorkflowService::V1::PatchScheduleRequest.new(
452
+ namespace: @client.namespace,
453
+ schedule_id: input.id,
454
+ patch: Api::Schedule::V1::SchedulePatch.new(
455
+ backfill_request: input.backfills.map(&:_to_proto)
456
+ ),
457
+ identity: @client.connection.identity,
458
+ request_id: SecureRandom.uuid
459
+ ),
460
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
461
+ )
462
+ nil
463
+ end
464
+
465
+ def delete_schedule(input)
466
+ @client.workflow_service.delete_schedule(
467
+ Api::WorkflowService::V1::DeleteScheduleRequest.new(
468
+ namespace: @client.namespace,
469
+ schedule_id: input.id,
470
+ identity: @client.connection.identity
471
+ ),
472
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
473
+ )
474
+ nil
475
+ end
476
+
477
+ def describe_schedule(input)
478
+ Temporalio::Client::Schedule::Description.new(
479
+ id: input.id,
480
+ raw_description: @client.workflow_service.describe_schedule(
481
+ Api::WorkflowService::V1::DescribeScheduleRequest.new(
482
+ namespace: @client.namespace,
483
+ schedule_id: input.id
484
+ ),
485
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
486
+ ),
487
+ data_converter: @client.data_converter
488
+ )
489
+ end
490
+
491
+ def pause_schedule(input)
492
+ @client.workflow_service.patch_schedule(
493
+ Api::WorkflowService::V1::PatchScheduleRequest.new(
494
+ namespace: @client.namespace,
495
+ schedule_id: input.id,
496
+ patch: Api::Schedule::V1::SchedulePatch.new(pause: input.note),
497
+ identity: @client.connection.identity,
498
+ request_id: SecureRandom.uuid
499
+ ),
500
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
501
+ )
502
+ nil
503
+ end
504
+
505
+ def trigger_schedule(input)
506
+ @client.workflow_service.patch_schedule(
507
+ Api::WorkflowService::V1::PatchScheduleRequest.new(
508
+ namespace: @client.namespace,
509
+ schedule_id: input.id,
510
+ patch: Api::Schedule::V1::SchedulePatch.new(
511
+ trigger_immediately: Api::Schedule::V1::TriggerImmediatelyRequest.new(
512
+ overlap_policy: input.overlap || 0
513
+ )
514
+ ),
515
+ identity: @client.connection.identity,
516
+ request_id: SecureRandom.uuid
517
+ ),
518
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
519
+ )
520
+ nil
521
+ end
522
+
523
+ def unpause_schedule(input)
524
+ @client.workflow_service.patch_schedule(
525
+ Api::WorkflowService::V1::PatchScheduleRequest.new(
526
+ namespace: @client.namespace,
527
+ schedule_id: input.id,
528
+ patch: Api::Schedule::V1::SchedulePatch.new(unpause: input.note),
529
+ identity: @client.connection.identity,
530
+ request_id: SecureRandom.uuid
531
+ ),
532
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
533
+ )
534
+ nil
535
+ end
536
+
537
+ def update_schedule(input)
538
+ # TODO(cretz): This is supposed to be a retry-conflict loop, but we do
539
+ # not yet have a way to know update failure is due to conflict token
540
+ # mismatch
541
+ update = input.updater.call(
542
+ Temporalio::Client::Schedule::Update::Input.new(
543
+ description: Temporalio::Client::Schedule::Description.new(
544
+ id: input.id,
545
+ raw_description: @client.workflow_service.describe_schedule(
546
+ Api::WorkflowService::V1::DescribeScheduleRequest.new(
547
+ namespace: @client.namespace,
548
+ schedule_id: input.id
549
+ ),
550
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
551
+ ),
552
+ data_converter: @client.data_converter
553
+ )
554
+ )
555
+ )
556
+ # Do nothing if update is nil, fail if not an expected update
557
+ return nil if update.nil?
558
+
559
+ unless update.is_a?(Temporalio::Client::Schedule::Update)
560
+ raise TypeError,
561
+ 'Expected result of update block to be a Schedule::Update'
562
+ end
563
+
564
+ @client.workflow_service.update_schedule(
565
+ Api::WorkflowService::V1::UpdateScheduleRequest.new(
566
+ namespace: @client.namespace,
567
+ schedule_id: input.id,
568
+ schedule: update.schedule._to_proto(@client.data_converter),
569
+ search_attributes: update.search_attributes&._to_proto,
570
+ identity: @client.connection.identity,
571
+ request_id: SecureRandom.uuid
572
+ ),
573
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
574
+ )
575
+ nil
576
+ end
577
+
578
+ def heartbeat_async_activity(input)
579
+ resp = if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
580
+ @client.workflow_service.record_activity_task_heartbeat_by_id(
581
+ Api::WorkflowService::V1::RecordActivityTaskHeartbeatByIdRequest.new(
582
+ workflow_id: input.task_token_or_id_reference.workflow_id,
583
+ run_id: input.task_token_or_id_reference.run_id,
584
+ activity_id: input.task_token_or_id_reference.activity_id,
585
+ namespace: @client.namespace,
586
+ identity: @client.connection.identity,
587
+ details: @client.data_converter.to_payloads(input.details)
588
+ ),
589
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
590
+ )
591
+ else
592
+ @client.workflow_service.record_activity_task_heartbeat(
593
+ Api::WorkflowService::V1::RecordActivityTaskHeartbeatRequest.new(
594
+ task_token: input.task_token_or_id_reference,
595
+ namespace: @client.namespace,
596
+ identity: @client.connection.identity,
597
+ details: @client.data_converter.to_payloads(input.details)
598
+ ),
599
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
600
+ )
601
+ end
602
+ raise Error::AsyncActivityCanceledError if resp.cancel_requested
603
+
604
+ nil
605
+ end
606
+
607
+ def complete_async_activity(input)
608
+ if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
609
+ @client.workflow_service.respond_activity_task_completed_by_id(
610
+ Api::WorkflowService::V1::RespondActivityTaskCompletedByIdRequest.new(
611
+ workflow_id: input.task_token_or_id_reference.workflow_id,
612
+ run_id: input.task_token_or_id_reference.run_id,
613
+ activity_id: input.task_token_or_id_reference.activity_id,
614
+ namespace: @client.namespace,
615
+ identity: @client.connection.identity,
616
+ result: @client.data_converter.to_payloads([input.result])
617
+ ),
618
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
619
+ )
620
+ else
621
+ @client.workflow_service.respond_activity_task_completed(
622
+ Api::WorkflowService::V1::RespondActivityTaskCompletedRequest.new(
623
+ task_token: input.task_token_or_id_reference,
624
+ namespace: @client.namespace,
625
+ identity: @client.connection.identity,
626
+ result: @client.data_converter.to_payloads([input.result])
627
+ ),
628
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
629
+ )
630
+ end
631
+ nil
632
+ end
633
+
634
+ def fail_async_activity(input)
635
+ if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
636
+ @client.workflow_service.respond_activity_task_failed_by_id(
637
+ Api::WorkflowService::V1::RespondActivityTaskFailedByIdRequest.new(
638
+ workflow_id: input.task_token_or_id_reference.workflow_id,
639
+ run_id: input.task_token_or_id_reference.run_id,
640
+ activity_id: input.task_token_or_id_reference.activity_id,
641
+ namespace: @client.namespace,
642
+ identity: @client.connection.identity,
643
+ failure: @client.data_converter.to_failure(input.error),
644
+ last_heartbeat_details: if input.last_heartbeat_details.empty?
645
+ nil
646
+ else
647
+ @client.data_converter.to_payloads(input.last_heartbeat_details)
648
+ end
649
+ ),
650
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
651
+ )
652
+ else
653
+ @client.workflow_service.respond_activity_task_failed(
654
+ Api::WorkflowService::V1::RespondActivityTaskFailedRequest.new(
655
+ task_token: input.task_token_or_id_reference,
656
+ namespace: @client.namespace,
657
+ identity: @client.connection.identity,
658
+ failure: @client.data_converter.to_failure(input.error),
659
+ last_heartbeat_details: if input.last_heartbeat_details.empty?
660
+ nil
661
+ else
662
+ @client.data_converter.to_payloads(input.last_heartbeat_details)
663
+ end
664
+ ),
665
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
666
+ )
667
+ end
668
+ nil
669
+ end
670
+
671
+ def report_cancellation_async_activity(input)
672
+ if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
673
+ @client.workflow_service.respond_activity_task_canceled_by_id(
674
+ Api::WorkflowService::V1::RespondActivityTaskCanceledByIdRequest.new(
675
+ workflow_id: input.task_token_or_id_reference.workflow_id,
676
+ run_id: input.task_token_or_id_reference.run_id,
677
+ activity_id: input.task_token_or_id_reference.activity_id,
678
+ namespace: @client.namespace,
679
+ identity: @client.connection.identity,
680
+ details: @client.data_converter.to_payloads(input.details)
681
+ ),
682
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
683
+ )
684
+ else
685
+ @client.workflow_service.respond_activity_task_canceled(
686
+ Api::WorkflowService::V1::RespondActivityTaskCanceledRequest.new(
687
+ task_token: input.task_token_or_id_reference,
688
+ namespace: @client.namespace,
689
+ identity: @client.connection.identity,
690
+ details: @client.data_converter.to_payloads(input.details)
691
+ ),
692
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
693
+ )
694
+ end
695
+ nil
696
+ end
697
+ end
698
+ end
699
+ end
700
+ end