amit-temporalio 0.3.0-x86_64-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 (175) 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/api/activity_result/activity_result.rb +34 -0
  105. data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +31 -0
  106. data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +33 -0
  107. data/lib/temporalio/internal/bridge/api/common/common.rb +26 -0
  108. data/lib/temporalio/internal/bridge/api/core_interface.rb +40 -0
  109. data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +27 -0
  110. data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +33 -0
  111. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +56 -0
  112. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +57 -0
  113. data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +30 -0
  114. data/lib/temporalio/internal/bridge/api.rb +3 -0
  115. data/lib/temporalio/internal/bridge/client.rb +95 -0
  116. data/lib/temporalio/internal/bridge/runtime.rb +53 -0
  117. data/lib/temporalio/internal/bridge/temporalio_bridge.bundle +0 -0
  118. data/lib/temporalio/internal/bridge/testing.rb +66 -0
  119. data/lib/temporalio/internal/bridge/worker.rb +85 -0
  120. data/lib/temporalio/internal/bridge.rb +36 -0
  121. data/lib/temporalio/internal/client/implementation.rb +700 -0
  122. data/lib/temporalio/internal/metric.rb +122 -0
  123. data/lib/temporalio/internal/proto_utils.rb +133 -0
  124. data/lib/temporalio/internal/worker/activity_worker.rb +376 -0
  125. data/lib/temporalio/internal/worker/multi_runner.rb +213 -0
  126. data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +54 -0
  127. data/lib/temporalio/internal/worker/workflow_instance/context.rb +333 -0
  128. data/lib/temporalio/internal/worker/workflow_instance/details.rb +44 -0
  129. data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +32 -0
  130. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +22 -0
  131. data/lib/temporalio/internal/worker/workflow_instance/handler_execution.rb +25 -0
  132. data/lib/temporalio/internal/worker/workflow_instance/handler_hash.rb +41 -0
  133. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +97 -0
  134. data/lib/temporalio/internal/worker/workflow_instance/inbound_implementation.rb +62 -0
  135. data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +415 -0
  136. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +37 -0
  137. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_metric.rb +40 -0
  138. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +163 -0
  139. data/lib/temporalio/internal/worker/workflow_instance.rb +730 -0
  140. data/lib/temporalio/internal/worker/workflow_worker.rb +236 -0
  141. data/lib/temporalio/internal.rb +7 -0
  142. data/lib/temporalio/metric.rb +109 -0
  143. data/lib/temporalio/retry_policy.rb +74 -0
  144. data/lib/temporalio/runtime.rb +314 -0
  145. data/lib/temporalio/scoped_logger.rb +96 -0
  146. data/lib/temporalio/search_attributes.rb +343 -0
  147. data/lib/temporalio/testing/activity_environment.rb +136 -0
  148. data/lib/temporalio/testing/workflow_environment.rb +383 -0
  149. data/lib/temporalio/testing.rb +10 -0
  150. data/lib/temporalio/version.rb +5 -0
  151. data/lib/temporalio/worker/activity_executor/fiber.rb +49 -0
  152. data/lib/temporalio/worker/activity_executor/thread_pool.rb +46 -0
  153. data/lib/temporalio/worker/activity_executor.rb +55 -0
  154. data/lib/temporalio/worker/interceptor.rb +362 -0
  155. data/lib/temporalio/worker/thread_pool.rb +237 -0
  156. data/lib/temporalio/worker/tuner.rb +189 -0
  157. data/lib/temporalio/worker/workflow_executor/thread_pool.rb +230 -0
  158. data/lib/temporalio/worker/workflow_executor.rb +26 -0
  159. data/lib/temporalio/worker/workflow_replayer.rb +343 -0
  160. data/lib/temporalio/worker.rb +569 -0
  161. data/lib/temporalio/workflow/activity_cancellation_type.rb +20 -0
  162. data/lib/temporalio/workflow/child_workflow_cancellation_type.rb +21 -0
  163. data/lib/temporalio/workflow/child_workflow_handle.rb +43 -0
  164. data/lib/temporalio/workflow/definition.rb +566 -0
  165. data/lib/temporalio/workflow/external_workflow_handle.rb +41 -0
  166. data/lib/temporalio/workflow/future.rb +151 -0
  167. data/lib/temporalio/workflow/handler_unfinished_policy.rb +13 -0
  168. data/lib/temporalio/workflow/info.rb +82 -0
  169. data/lib/temporalio/workflow/parent_close_policy.rb +19 -0
  170. data/lib/temporalio/workflow/update_info.rb +20 -0
  171. data/lib/temporalio/workflow.rb +529 -0
  172. data/lib/temporalio/workflow_history.rb +47 -0
  173. data/lib/temporalio.rb +11 -0
  174. data/temporalio.gemspec +28 -0
  175. metadata +236 -0
@@ -0,0 +1,236 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'temporalio/api/payload_visitor'
4
+ require 'temporalio/error'
5
+ require 'temporalio/internal/worker/workflow_instance'
6
+ require 'temporalio/scoped_logger'
7
+ require 'temporalio/workflow'
8
+ require 'temporalio/workflow/definition'
9
+ require 'timeout'
10
+
11
+ module Temporalio
12
+ module Internal
13
+ module Worker
14
+ # Worker for handling workflow activations. Most activation work is delegated to the workflow executor.
15
+ class WorkflowWorker
16
+ def self.workflow_definitions(workflows)
17
+ workflows.each_with_object({}) do |workflow, hash|
18
+ # Load definition
19
+ defn = begin
20
+ if workflow.is_a?(Workflow::Definition::Info)
21
+ workflow
22
+ else
23
+ Workflow::Definition::Info.from_class(workflow)
24
+ end
25
+ rescue StandardError
26
+ raise ArgumentError, "Failed loading workflow #{workflow}"
27
+ end
28
+
29
+ # Confirm name not in use
30
+ raise ArgumentError, "Multiple workflows named #{defn.name || '<dynamic>'}" if hash.key?(defn.name)
31
+
32
+ hash[defn.name] = defn
33
+ end
34
+ end
35
+
36
+ def self.bridge_workflow_failure_exception_type_options(
37
+ workflow_failure_exception_types:,
38
+ workflow_definitions:
39
+ )
40
+ as_fail = workflow_failure_exception_types.any? do |t|
41
+ t.is_a?(Class) && t >= Workflow::NondeterminismError
42
+ end
43
+ as_fail_for_types = workflow_definitions.values.map do |defn|
44
+ next unless defn.failure_exception_types.any? { |t| t.is_a?(Class) && t >= Workflow::NondeterminismError }
45
+
46
+ # If they tried to do this on a dynamic workflow and haven't already set worker-level option, warn
47
+ unless defn.name || as_fail
48
+ warn('Note, dynamic workflows cannot trap non-determinism errors, so worker-level ' \
49
+ 'workflow_failure_exception_types should be set to capture that if that is the intention')
50
+ end
51
+ defn.name
52
+ end.compact
53
+ [as_fail, as_fail_for_types]
54
+ end
55
+
56
+ def initialize(
57
+ bridge_worker:,
58
+ namespace:,
59
+ task_queue:,
60
+ workflow_definitions:,
61
+ workflow_executor:,
62
+ logger:,
63
+ data_converter:,
64
+ metric_meter:,
65
+ workflow_interceptors:,
66
+ disable_eager_activity_execution:,
67
+ illegal_workflow_calls:,
68
+ workflow_failure_exception_types:,
69
+ workflow_payload_codec_thread_pool:,
70
+ debug_mode:,
71
+ on_eviction: nil
72
+ )
73
+ @executor = workflow_executor
74
+
75
+ payload_codec = data_converter.payload_codec
76
+ @workflow_payload_codec_thread_pool = workflow_payload_codec_thread_pool
77
+ if !Fiber.current_scheduler && payload_codec && !@workflow_payload_codec_thread_pool
78
+ raise ArgumentError, 'Must have workflow payload codec thread pool if providing codec and not using fibers'
79
+ end
80
+
81
+ # If there is a payload codec, we need to build encoding and decoding visitors
82
+ if payload_codec
83
+ @payload_encoding_visitor = Api::PayloadVisitor.new(skip_search_attributes: true) do |payload_or_payloads|
84
+ apply_codec_on_payload_visit(payload_or_payloads) { |payloads| payload_codec.encode(payloads) }
85
+ end
86
+ @payload_decoding_visitor = Api::PayloadVisitor.new(skip_search_attributes: true) do |payload_or_payloads|
87
+ apply_codec_on_payload_visit(payload_or_payloads) { |payloads| payload_codec.decode(payloads) }
88
+ end
89
+ end
90
+
91
+ @state = State.new(
92
+ workflow_definitions:,
93
+ bridge_worker:,
94
+ logger:,
95
+ metric_meter:,
96
+ data_converter:,
97
+ deadlock_timeout: debug_mode ? nil : 2.0,
98
+ # TODO(cretz): Make this more performant for the default set?
99
+ illegal_calls: WorkflowInstance::IllegalCallTracer.frozen_validated_illegal_calls(
100
+ illegal_workflow_calls || {}
101
+ ),
102
+ namespace:,
103
+ task_queue:,
104
+ disable_eager_activity_execution:,
105
+ workflow_interceptors:,
106
+ workflow_failure_exception_types: workflow_failure_exception_types.map do |t|
107
+ unless t.is_a?(Class) && t < Exception
108
+ raise ArgumentError, 'All failure types must classes inheriting Exception'
109
+ end
110
+
111
+ t
112
+ end.freeze
113
+ )
114
+ @state.on_eviction = on_eviction if on_eviction
115
+
116
+ # Validate worker
117
+ @executor._validate_worker(self, @state)
118
+ end
119
+
120
+ def handle_activation(runner:, activation:, decoded:)
121
+ # Encode in background if not encoded but it needs to be
122
+ if @payload_encoding_visitor && !decoded
123
+ if Fiber.current_scheduler
124
+ Fiber.schedule { decode_activation(runner, activation) }
125
+ else
126
+ @workflow_payload_codec_thread_pool.execute { decode_activation(runner, activation) }
127
+ end
128
+ else
129
+ @executor._activate(activation, @state) do |activation_completion|
130
+ runner.apply_workflow_activation_complete(workflow_worker: self, activation_completion:, encoded: false)
131
+ end
132
+ end
133
+ rescue Exception => e # rubocop:disable Lint/RescueException
134
+ # Should never happen, executors are expected to trap things
135
+ @state.logger.error("Failed issuing activation on workflow run ID: #{activation.run_id}")
136
+ @state.logger.error(e)
137
+ end
138
+
139
+ def handle_activation_complete(runner:, activation_completion:, encoded:, completion_complete_queue:)
140
+ if @payload_encoding_visitor && !encoded
141
+ if Fiber.current_scheduler
142
+ Fiber.schedule { encode_activation_completion(runner, activation_completion) }
143
+ else
144
+ @workflow_payload_codec_thread_pool.execute do
145
+ encode_activation_completion(runner, activation_completion)
146
+ end
147
+ end
148
+ else
149
+ @state.bridge_worker.async_complete_workflow_activation(
150
+ activation_completion.run_id, activation_completion.to_proto, completion_complete_queue
151
+ )
152
+ end
153
+ end
154
+
155
+ def on_shutdown_complete
156
+ @state.evict_all
157
+ end
158
+
159
+ private
160
+
161
+ def decode_activation(runner, activation)
162
+ @payload_decoding_visitor.run(activation)
163
+ runner.apply_workflow_activation_decoded(workflow_worker: self, activation:)
164
+ end
165
+
166
+ def encode_activation_completion(runner, activation_completion)
167
+ @payload_encoding_visitor.run(activation_completion)
168
+ runner.apply_workflow_activation_complete(workflow_worker: self, activation_completion:, encoded: true)
169
+ end
170
+
171
+ def apply_codec_on_payload_visit(payload_or_payloads, &)
172
+ case payload_or_payloads
173
+ when Temporalio::Api::Common::V1::Payload
174
+ new_payloads = yield [payload_or_payloads]
175
+ payload_or_payloads.metadata = new_payloads.first.metadata
176
+ payload_or_payloads.data = new_payloads.first.data
177
+ when Enumerable
178
+ payload_or_payloads.replace(yield payload_or_payloads) # steep:ignore
179
+ else
180
+ raise 'Unrecognized visitor type'
181
+ end
182
+ end
183
+
184
+ class State
185
+ attr_reader :workflow_definitions, :bridge_worker, :logger, :metric_meter, :data_converter, :deadlock_timeout,
186
+ :illegal_calls, :namespace, :task_queue, :disable_eager_activity_execution,
187
+ :workflow_interceptors, :workflow_failure_exception_types
188
+
189
+ attr_writer :on_eviction
190
+
191
+ def initialize(
192
+ workflow_definitions:, bridge_worker:, logger:, metric_meter:, data_converter:, deadlock_timeout:,
193
+ illegal_calls:, namespace:, task_queue:, disable_eager_activity_execution:,
194
+ workflow_interceptors:, workflow_failure_exception_types:
195
+ )
196
+ @workflow_definitions = workflow_definitions
197
+ @bridge_worker = bridge_worker
198
+ @logger = logger
199
+ @metric_meter = metric_meter
200
+ @data_converter = data_converter
201
+ @deadlock_timeout = deadlock_timeout
202
+ @illegal_calls = illegal_calls
203
+ @namespace = namespace
204
+ @task_queue = task_queue
205
+ @disable_eager_activity_execution = disable_eager_activity_execution
206
+ @workflow_interceptors = workflow_interceptors
207
+ @workflow_failure_exception_types = workflow_failure_exception_types
208
+
209
+ @running_workflows = {}
210
+ @running_workflows_mutex = Mutex.new
211
+ end
212
+
213
+ # This can never be called at the same time for the same run ID on the same state object
214
+ def get_or_create_running_workflow(run_id, &)
215
+ instance = @running_workflows_mutex.synchronize { @running_workflows[run_id] }
216
+ # If instance is not there, we create it out of lock then store it under lock
217
+ unless instance
218
+ instance = yield
219
+ @running_workflows_mutex.synchronize { @running_workflows[run_id] = instance }
220
+ end
221
+ instance
222
+ end
223
+
224
+ def evict_running_workflow(run_id, cache_remove_job)
225
+ @running_workflows_mutex.synchronize { @running_workflows.delete(run_id) }
226
+ @on_eviction&.call(run_id, cache_remove_job)
227
+ end
228
+
229
+ def evict_all
230
+ @running_workflows_mutex.synchronize { @running_workflows.clear }
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Temporalio
4
+ # @!visibility private
5
+ module Internal
6
+ end
7
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'temporalio/internal/metric'
4
+
5
+ module Temporalio
6
+ # Metric that can be recorded from a metric meter. This is obtained via {Meter.create_metric}. The metric meter is
7
+ # obtained via workflow environment, activity context, or from the {Runtime} if in neither of those. This class is
8
+ # effectively abstract and will fail if `initialize` is attempted.
9
+ class Metric
10
+ # @!visibility private
11
+ def initialize
12
+ raise NotImplementedError, 'Metric is abstract, implementations override initialize'
13
+ end
14
+
15
+ # Record a value for the metric. For counters, this adds to any existing. For histograms, this records into proper
16
+ # buckets. For gauges, this sets the value. The value type must match the expectation.
17
+ #
18
+ # @param value [Numeric] Value to record. For counters and duration-based histograms, this value cannot be negative.
19
+ # @param additional_attributes [Hash{String, Symbol => String, Integer, Float, Boolean}, nil] Additional attributes
20
+ # on this specific record. For better performance for attribute reuse, users are encouraged to use
21
+ # {with_additional_attributes} to make a copy of this metric with those attributes.
22
+ def record(value, additional_attributes: nil)
23
+ raise NotImplementedError
24
+ end
25
+
26
+ # Create a copy of this metric but with the given additional attributes. This is more performant than providing
27
+ # attributes on each {record} call.
28
+ #
29
+ # @param additional_attributes [Hash{String, Symbol => String, Integer, Float, Boolean}] Attributes to set on the
30
+ # resulting metric.
31
+ # @return [Metric] Copy of this metric with the additional attributes.
32
+ def with_additional_attributes(additional_attributes)
33
+ raise NotImplementedError
34
+ end
35
+
36
+ # @return [:counter, :histogram, :gauge] Metric type.
37
+ def metric_type
38
+ raise NotImplementedError
39
+ end
40
+
41
+ # @return [String] Metric name.
42
+ def name
43
+ raise NotImplementedError
44
+ end
45
+
46
+ # @return [String, nil] Metric description.
47
+ def description
48
+ raise NotImplementedError
49
+ end
50
+
51
+ # @return [String, nil] Metric unit.
52
+ def unit
53
+ raise NotImplementedError
54
+ end
55
+
56
+ # @return [:integer, :float, :duration] Metric value type.
57
+ def value_type
58
+ raise NotImplementedError
59
+ end
60
+
61
+ # Meter for creating metrics to record values on. This is obtained via workflow environment, activity context, or
62
+ # from the {Runtime} if in neither of those. This class is effectively abstract and will fail if `initialize` is
63
+ # attempted.
64
+ class Meter
65
+ # @return [Meter] A no-op instance of {Meter}.
66
+ def self.null
67
+ Internal::Metric::NullMeter.instance
68
+ end
69
+
70
+ # @!visibility private
71
+ def initialize
72
+ raise NotImplementedError, 'Meter is abstract, implementations override initialize'
73
+ end
74
+
75
+ # Create a new metric. Only certain metric types are accepted and only value types can work with certain metric
76
+ # types.
77
+ #
78
+ # @param metric_type [:counter, :histogram, :gauge] Metric type. Counters can only have `:integer` value types,
79
+ # histograms can have `:integer`, `:float`, or :duration` value types, and gauges can have `:integer` or
80
+ # `:float` value types.
81
+ # @param name [String] Metric name.
82
+ # @param description [String, nil] Metric description.
83
+ # @param unit [String, nil] Metric unit.
84
+ # @param value_type [:integer, :float, :duration] Metric value type. `:integer` works for all metric types,
85
+ # `:float` works for `:histogram` and `:gauge` metric types, and `:duration` only works for `:histogram` metric
86
+ # types.
87
+ # @return [Metric] Created metric.
88
+ def create_metric(
89
+ metric_type,
90
+ name,
91
+ description: nil,
92
+ unit: nil,
93
+ value_type: :integer
94
+ )
95
+ raise NotImplementedError
96
+ end
97
+
98
+ # Create a copy of this meter but with the given additional attributes. This is more performant than providing
99
+ # attributes on each {record} call.
100
+ #
101
+ # @param additional_attributes [Hash{String, Symbol => String, Integer, Float, Boolean}] Attributes to set on the
102
+ # resulting meter.
103
+ # @return [Meter] Copy of this meter with the additional attributes.
104
+ def with_additional_attributes(additional_attributes)
105
+ raise NotImplementedError
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'temporalio/internal/proto_utils'
4
+
5
+ module Temporalio
6
+ RetryPolicy = Data.define(
7
+ :initial_interval,
8
+ :backoff_coefficient,
9
+ :max_interval,
10
+ :max_attempts,
11
+ :non_retryable_error_types
12
+ )
13
+
14
+ # Options for retrying workflows and activities.
15
+ #
16
+ # @!attribute initial_interval
17
+ # @return [Float] Backoff interval in seconds for the first retry. Default 1.0.
18
+ # @!attribute backoff_coefficient
19
+ # @return [Float] Coefficient to multiply previous backoff interval by to get new interval. Default 2.0.
20
+ # @!attribute max_interval
21
+ # @return [Float, nil] Maximum backoff interval in seconds between retries. Default 100x `initial_interval`.
22
+ # @!attribute max_attempts
23
+ # @return [Integer] Maximum number of attempts. If `0`, the default, there is no maximum.
24
+ # @!attribute non_retryable_error_types
25
+ # @return [Array<String>, nil] List of error types that are not retryable.
26
+ class RetryPolicy
27
+ # @!visibility private
28
+ def self._from_proto(raw_policy)
29
+ RetryPolicy.new(
30
+ initial_interval: Internal::ProtoUtils.duration_to_seconds(raw_policy.initial_interval) || raise, # Never nil
31
+ backoff_coefficient: raw_policy.backoff_coefficient,
32
+ max_interval: Internal::ProtoUtils.duration_to_seconds(raw_policy.maximum_interval),
33
+ max_attempts: raw_policy.maximum_attempts,
34
+ non_retryable_error_types: raw_policy.non_retryable_error_types&.to_a
35
+ )
36
+ end
37
+
38
+ # Create retry policy.
39
+ #
40
+ # @param initial_interval [Float] Backoff interval in seconds for the first retry. Default 1.0.
41
+ # @param backoff_coefficient [Float] Coefficient to multiply previous backoff interval by to get new interval.
42
+ # Default 2.0.
43
+ # @param max_interval [Float, nil] Maximum backoff interval in seconds between retries. Default 100x
44
+ # `initial_interval`.
45
+ # @param max_attempts [Integer] Maximum number of attempts. If `0`, the default, there is no maximum.
46
+ # @param non_retryable_error_types [Array<String>, nil] List of error types that are not retryable.
47
+ def initialize(
48
+ initial_interval: 1.0,
49
+ backoff_coefficient: 2.0,
50
+ max_interval: nil,
51
+ max_attempts: 0,
52
+ non_retryable_error_types: nil
53
+ )
54
+ super
55
+ end
56
+
57
+ # @!visibility private
58
+ def _to_proto
59
+ raise 'Initial interval cannot be negative' if initial_interval.negative?
60
+ raise 'Backoff coefficient cannot be less than 1' if backoff_coefficient < 1
61
+ raise 'Max interval cannot be negative' if max_interval&.negative?
62
+ raise 'Max interval cannot be less than initial interval' if max_interval && max_interval < initial_interval
63
+ raise 'Max attempts cannot be negative' if max_attempts.negative?
64
+
65
+ Api::Common::V1::RetryPolicy.new(
66
+ initial_interval: Internal::ProtoUtils.seconds_to_duration(initial_interval),
67
+ backoff_coefficient:,
68
+ maximum_interval: Internal::ProtoUtils.seconds_to_duration(max_interval),
69
+ maximum_attempts: max_attempts,
70
+ non_retryable_error_types:
71
+ )
72
+ end
73
+ end
74
+ end