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