temporalio 0.5.0-arm64-darwin → 1.0.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/temporalio/activity/info.rb +5 -0
  3. data/lib/temporalio/api/batch/v1/message.rb +4 -1
  4. data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +12 -1
  5. data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +1 -1
  6. data/lib/temporalio/api/cloud/connectivityrule/v1/message.rb +29 -0
  7. data/lib/temporalio/api/cloud/identity/v1/message.rb +1 -1
  8. data/lib/temporalio/api/cloud/namespace/v1/message.rb +2 -1
  9. data/lib/temporalio/api/cloud/operation/v1/message.rb +1 -1
  10. data/lib/temporalio/api/common/v1/message.rb +2 -1
  11. data/lib/temporalio/api/enums/v1/batch_operation.rb +1 -1
  12. data/lib/temporalio/api/enums/v1/task_queue.rb +2 -1
  13. data/lib/temporalio/api/history/v1/message.rb +1 -1
  14. data/lib/temporalio/api/payload_visitor.rb +19 -1
  15. data/lib/temporalio/api/sdk/v1/worker_config.rb +23 -0
  16. data/lib/temporalio/api/taskqueue/v1/message.rb +5 -1
  17. data/lib/temporalio/api/worker/v1/message.rb +2 -1
  18. data/lib/temporalio/api/workflowservice/v1/request_response.rb +10 -1
  19. data/lib/temporalio/api/workflowservice/v1/service.rb +1 -1
  20. data/lib/temporalio/cancellation.rb +16 -12
  21. data/lib/temporalio/client/async_activity_handle.rb +1 -0
  22. data/lib/temporalio/client/connection/cloud_service.rb +75 -0
  23. data/lib/temporalio/client/connection/workflow_service.rb +45 -0
  24. data/lib/temporalio/client/connection.rb +2 -1
  25. data/lib/temporalio/contrib/open_telemetry.rb +9 -13
  26. data/lib/temporalio/converters/payload_converter/json_plain.rb +22 -5
  27. data/lib/temporalio/env_config.rb +343 -0
  28. data/lib/temporalio/error.rb +5 -1
  29. data/lib/temporalio/internal/bridge/3.2/temporalio_bridge.bundle +0 -0
  30. data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.bundle +0 -0
  31. data/lib/temporalio/internal/bridge/3.4/temporalio_bridge.bundle +0 -0
  32. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +1 -1
  33. data/lib/temporalio/internal/bridge/worker.rb +50 -0
  34. data/lib/temporalio/internal/client/implementation.rb +7 -2
  35. data/lib/temporalio/internal/worker/activity_worker.rb +1 -0
  36. data/lib/temporalio/internal/worker/workflow_instance/context.rb +7 -4
  37. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +2 -0
  38. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +18 -11
  39. data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +6 -5
  40. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +5 -2
  41. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +10 -4
  42. data/lib/temporalio/internal/worker/workflow_instance.rb +77 -80
  43. data/lib/temporalio/priority.rb +47 -6
  44. data/lib/temporalio/scoped_logger.rb +1 -1
  45. data/lib/temporalio/testing/activity_environment.rb +1 -0
  46. data/lib/temporalio/version.rb +1 -1
  47. data/lib/temporalio/worker/illegal_workflow_call_validator.rb +9 -0
  48. data/lib/temporalio/worker/interceptor.rb +1 -0
  49. data/lib/temporalio/worker/tuner.rb +185 -16
  50. data/lib/temporalio/worker.rb +10 -1
  51. data/lib/temporalio/workflow/definition.rb +4 -6
  52. data/lib/temporalio/workflow/info.rb +3 -0
  53. data/lib/temporalio/workflow.rb +80 -6
  54. metadata +5 -2
@@ -22,10 +22,11 @@ module Temporalio
22
22
  end
23
23
 
24
24
  # @!visibility private
25
- def _to_bridge_options
25
+ def _to_bridge_options(_tuner)
26
26
  Internal::Bridge::Worker::TunerSlotSupplierOptions.new(
27
27
  fixed_size: slots,
28
- resource_based: nil
28
+ resource_based: nil,
29
+ custom: nil
29
30
  )
30
31
  end
31
32
  end
@@ -36,7 +37,7 @@ module Temporalio
36
37
  class ResourceBased < SlotSupplier
37
38
  attr_reader :tuner_options, :slot_options
38
39
 
39
- # Create a reosurce-based slot supplier.
40
+ # Create a resource-based slot supplier.
40
41
  #
41
42
  # @param tuner_options [ResourceBasedTunerOptions] General tuner options.
42
43
  # @param slot_options [ResourceBasedSlotOptions] Slot-supplier-specific tuner options.
@@ -46,7 +47,7 @@ module Temporalio
46
47
  end
47
48
 
48
49
  # @!visibility private
49
- def _to_bridge_options
50
+ def _to_bridge_options(_tuner)
50
51
  Internal::Bridge::Worker::TunerSlotSupplierOptions.new(
51
52
  fixed_size: nil,
52
53
  resource_based: Internal::Bridge::Worker::TunerResourceBasedSlotSupplierOptions.new(
@@ -55,14 +56,175 @@ module Temporalio
55
56
  min_slots: slot_options.min_slots,
56
57
  max_slots: slot_options.max_slots,
57
58
  ramp_throttle: slot_options.ramp_throttle
59
+ ),
60
+ custom: nil
61
+ )
62
+ end
63
+ end
64
+
65
+ # A slot supplier that has callbacks invoked to handle slot supplying.
66
+ #
67
+ # Users should be cautious when implementing this and make sure it is heavily tested and the documentation for
68
+ # every method is well understood.
69
+ #
70
+ # @note WARNING: This API is experimental.
71
+ class Custom < SlotSupplier
72
+ # Context provided for slot reservation on custom slot supplier.
73
+ #
74
+ # @!attribute slot_type
75
+ # @return [:workflow, :activity, :local_activity, :nexus] Slot type.
76
+ # @!attribute task_queue
77
+ # @return [String] Task queue.
78
+ # @!attribute worker_identity
79
+ # @return [String] Worker identity.
80
+ # @!attribute worker_deployment_name
81
+ # @return [String] Worker deployment name or empty string if not applicable.
82
+ # @!attribute worker_build_id
83
+ # @return [String] Worker build ID or empty string if not applicable.
84
+ # @!attribute sticky?
85
+ # @return [Boolean] True if this reservation is for a sticky workflow task.
86
+ ReserveContext = Data.define(
87
+ :slot_type,
88
+ :task_queue,
89
+ :worker_identity,
90
+ :worker_deployment_name,
91
+ :worker_build_id,
92
+ :sticky?
93
+ )
94
+
95
+ # Context provided for marking a slot used.
96
+ #
97
+ # @!attribute slot_info
98
+ # @return [SlotInfo::Workflow, SlotInfo::Activity, SlotInfo::LocalActivity, SlotInfo::Nexus] Information
99
+ # about the slot. This is never nil.
100
+ # @!attribute permit
101
+ # @return [Object] Object that was provided as the permit on reserve.
102
+ MarkUsedContext = Data.define(
103
+ :slot_info,
104
+ :permit
105
+ )
106
+
107
+ # Context provided for releasing a slot.
108
+ #
109
+ # @!attribute slot_info
110
+ # @return [SlotInfo::Workflow, SlotInfo::Activity, SlotInfo::LocalActivity, SlotInfo::Nexus, nil]
111
+ # Information about the slot. This may be nil if the slot was never used.
112
+ # @!attribute permit
113
+ # @return [Object] Object that was provided as the permit on reserve.
114
+ ReleaseContext = Data.define(
115
+ :slot_info,
116
+ :permit
117
+ )
118
+
119
+ # Reserve a slot.
120
+ #
121
+ # This can/should block and must provide the permit to the (code) block. The permit is any object (including
122
+ # nil) that will be given on the context for mark_slot_used and release_slot.
123
+ #
124
+ # Just returning from this call is not enough to reserve the slot, a permit must be provided to the block
125
+ # (e.g. via yield or block.call). If the call completes, the system will still wait on the block (so this can
126
+ # be backgrounded by passing the block to something else). Reservations may be canceled via the given
127
+ # cancellation. Users can do things like add_cancel_callback, but it is very important that the code in the
128
+ # callback is fast as it is run on the same reactor thread as many other Temporal Ruby worker calls.
129
+ #
130
+ # @note WARNING: This call should never raise an exception. Any exception raised is ignored and this is called
131
+ # again after 1 second.
132
+ #
133
+ # @param context [ReserveContext] Contextual information about this reserve call.
134
+ # @param cancellation [Cancellation] Cancellation that is canceled when the reservation is no longer being
135
+ # asked for.
136
+ # @yield [Object] Confirm reservation and provide a permit.
137
+ def reserve_slot(context, cancellation, &)
138
+ raise NotImplementedError
139
+ end
140
+
141
+ # Try to reserve a slot.
142
+ #
143
+ # @note WARNING: This should never block, this should return immediately with a permit, or nil if the
144
+ # reservation could not occur.
145
+ #
146
+ # @note WARNING: This call should never raise an exception. Any exception raised is ignored and the slot
147
+ # reservation attempt fails (i.e. same as if this method returned nil).
148
+ #
149
+ # @param context [ReserveContext] Contextual information about this reserve call.
150
+ # @return [Object, nil] A non-nil object to perform the reservation successfully, a nil to fail the
151
+ # reservation.
152
+ def try_reserve_slot(context)
153
+ raise NotImplementedError
154
+ end
155
+
156
+ # Mark a slot as used.
157
+ #
158
+ # Due to the nature of Temporal polling, slots are reserved before they are used and may never get used. This
159
+ # call is made as just a notification when a slot is actually used.
160
+ #
161
+ # @note WARNING: This should never block, this should return immediately.
162
+ #
163
+ # @note WARNING: This call should never raise an exception. Any exception raised is ignored.
164
+ #
165
+ # @param context [MarkUsedContext] Contextual information about this reserve call.
166
+ def mark_slot_used(context)
167
+ raise NotImplementedError
168
+ end
169
+
170
+ # Release a previously reserved slot.
171
+ #
172
+ # @note WARNING: This should never block, this should return immediately.
173
+ #
174
+ # @note WARNING: This call should never raise an exception. Any exception raised is ignored.
175
+ #
176
+ # @param context [ReleaseContext] Contextual information about this reserve call.
177
+ def release_slot(context)
178
+ raise NotImplementedError
179
+ end
180
+
181
+ # @!visibility private
182
+ def _to_bridge_options(tuner)
183
+ Internal::Bridge::Worker::TunerSlotSupplierOptions.new(
184
+ fixed_size: nil,
185
+ resource_based: nil,
186
+ custom: Internal::Bridge::Worker::CustomSlotSupplier.new(
187
+ slot_supplier: self,
188
+ thread_pool: tuner.custom_slot_supplier_thread_pool
58
189
  )
59
190
  )
60
191
  end
192
+
193
+ # Slot information.
194
+ module SlotInfo
195
+ # Information about a workflow slot.
196
+ #
197
+ # @!attribute workflow_type
198
+ # @return [String] Workflow type.
199
+ # @!attribute sticky?
200
+ # @return [Boolean] Whether the slot was for a sticky task.
201
+ Workflow = Data.define(:workflow_type, :sticky?)
202
+
203
+ # Information about an activity slot.
204
+ #
205
+ # @!attribute activity_type
206
+ # @return [String] Activity type.
207
+ Activity = Data.define(:activity_type)
208
+
209
+ # Information about a local activity slot.
210
+ #
211
+ # @!attribute activity_type
212
+ # @return [String] Activity type.
213
+ LocalActivity = Data.define(:activity_type)
214
+
215
+ # Information about a Nexus slot.
216
+ #
217
+ # @!attribute service
218
+ # @return [String] Nexus service.
219
+ # @!attribute operation
220
+ # @return [String] Nexus operation.
221
+ Nexus = Data.define(:service, :operation)
222
+ end
61
223
  end
62
224
 
63
225
  # @!visibility private
64
- def _to_bridge_options
65
- raise ArgumentError, 'Tuner slot suppliers must be instances of Fixed or ResourceBased'
226
+ def _to_bridge_options(_tuner)
227
+ raise ArgumentError, 'Tuner slot suppliers must be instances of Fixed, ResourceBased, or Custom'
66
228
  end
67
229
  end
68
230
 
@@ -75,10 +237,9 @@ module Temporalio
75
237
  # @!attribute target_cpu_usage
76
238
  # @return [Float] A value between 0 and 1 that represents the target (system) CPU usage. This can be set to 1.0
77
239
  # if desired, but it's recommended to leave some headroom for other processes.
78
- ResourceBasedTunerOptions = Struct.new(
240
+ ResourceBasedTunerOptions = Data.define(
79
241
  :target_memory_usage,
80
- :target_cpu_usage,
81
- keyword_init: true
242
+ :target_cpu_usage
82
243
  )
83
244
 
84
245
  # Options for a specific slot type being used with {SlotSupplier::ResourceBased}.
@@ -94,11 +255,10 @@ module Temporalio
94
255
  #
95
256
  # This value matters because how many resources a task will use cannot be determined ahead of time, and thus
96
257
  # the system should wait to see how much resources are used before issuing more slots.
97
- ResourceBasedSlotOptions = Struct.new(
258
+ ResourceBasedSlotOptions = Data.define(
98
259
  :min_slots,
99
260
  :max_slots,
100
- :ramp_throttle,
101
- keyword_init: true
261
+ :ramp_throttle
102
262
  )
103
263
 
104
264
  # Create a fixed-size tuner with the provided number of slots.
@@ -161,27 +321,36 @@ module Temporalio
161
321
  # @return [SlotSupplier] Slot supplier for local activities.
162
322
  attr_reader :local_activity_slot_supplier
163
323
 
324
+ # @return [ThreadPool, nil] Thread pool for custom slot suppliers.
325
+ attr_reader :custom_slot_supplier_thread_pool
326
+
164
327
  # Create a tuner from 3 slot suppliers.
165
328
  #
166
329
  # @param workflow_slot_supplier [SlotSupplier] Slot supplier for workflows.
167
330
  # @param activity_slot_supplier [SlotSupplier] Slot supplier for activities.
168
331
  # @param local_activity_slot_supplier [SlotSupplier] Slot supplier for local activities.
332
+ # @param custom_slot_supplier_thread_pool [ThreadPool, nil] Thread pool to make all custom slot supplier calls on.
333
+ # If there are no custom slot suppliers, this parameter is ignored. Technically users may set this to nil which
334
+ # will not use a thread pool to make slot supplier calls, but that is dangerous and not advised because even the
335
+ # slightest blocking call can slow down the system.
169
336
  def initialize(
170
337
  workflow_slot_supplier:,
171
338
  activity_slot_supplier:,
172
- local_activity_slot_supplier:
339
+ local_activity_slot_supplier:,
340
+ custom_slot_supplier_thread_pool: ThreadPool.default
173
341
  )
174
342
  @workflow_slot_supplier = workflow_slot_supplier
175
343
  @activity_slot_supplier = activity_slot_supplier
176
344
  @local_activity_slot_supplier = local_activity_slot_supplier
345
+ @custom_slot_supplier_thread_pool = custom_slot_supplier_thread_pool
177
346
  end
178
347
 
179
348
  # @!visibility private
180
349
  def _to_bridge_options
181
350
  Internal::Bridge::Worker::TunerOptions.new(
182
- workflow_slot_supplier: workflow_slot_supplier._to_bridge_options,
183
- activity_slot_supplier: activity_slot_supplier._to_bridge_options,
184
- local_activity_slot_supplier: local_activity_slot_supplier._to_bridge_options
351
+ workflow_slot_supplier: workflow_slot_supplier._to_bridge_options(self),
352
+ activity_slot_supplier: activity_slot_supplier._to_bridge_options(self),
353
+ local_activity_slot_supplier: local_activity_slot_supplier._to_bridge_options(self)
185
354
  )
186
355
  end
187
356
  end
@@ -267,7 +267,11 @@ module Temporalio
267
267
  #:write
268
268
  ],
269
269
  'Kernel' => %i[abort at_exit autoload autoload? eval exec exit fork gets load open rand readline readlines
270
- spawn srand system test trap],
270
+ sleep spawn srand system test trap],
271
+ # Loggers use mutexes in ways that can hang workflows, so users need to disable the durable scheduler to use
272
+ # them
273
+ 'Logger' => :all,
274
+ 'Monitor' => :all,
271
275
  'Net::HTTP' => :all,
272
276
  'Pathname' => :all,
273
277
  # TODO(cretz): Investigate why clock_gettime called from Timeout thread affects this code at all. Stack trace
@@ -282,9 +286,14 @@ module Temporalio
282
286
  'Signal' => :all,
283
287
  'Socket' => :all,
284
288
  'Tempfile' => :all,
289
+ 'Timeout' => :all,
285
290
  'Thread' => %i[abort_on_exception= exit fork handle_interrupt ignore_deadlock= kill new pass
286
291
  pending_interrupt? report_on_exception= start stop initialize join name= priority= raise run
287
292
  terminate thread_variable_set wakeup],
293
+ 'Thread::ConditionVariable' => :all,
294
+ 'Thread::Mutex' => IllegalWorkflowCallValidator.known_safe_mutex_validator,
295
+ 'Thread::SizedQueue' => :all,
296
+ 'Thread::Queue' => :all,
288
297
  'Time' => IllegalWorkflowCallValidator.default_time_validators
289
298
  } #: Hash[String, :all | Array[Symbol]]
290
299
  hash.each_value(&:freeze)
@@ -280,7 +280,7 @@ module Temporalio
280
280
  @workflow_update_validators ||= {}
281
281
  @defined_methods ||= []
282
282
 
283
- defn, hash, other_hashes =
283
+ defn, hash =
284
284
  case handler[:type]
285
285
  when :init
286
286
  raise "workflow_init was applied to #{method_name} instead of initialize" if method_name != :initialize
@@ -306,7 +306,7 @@ module Temporalio
306
306
  raw_args: handler[:raw_args],
307
307
  unfinished_policy: handler[:unfinished_policy],
308
308
  arg_hints: handler[:arg_hints]
309
- ), @workflow_signals, [@workflow_queries, @workflow_updates]]
309
+ ), @workflow_signals]
310
310
  when :query
311
311
  [Query.new(
312
312
  name: handler[:dynamic] ? nil : (handler[:name] || method_name).to_s,
@@ -315,7 +315,7 @@ module Temporalio
315
315
  raw_args: handler[:raw_args],
316
316
  arg_hints: handler[:arg_hints],
317
317
  result_hint: handler[:result_hint]
318
- ), @workflow_queries, [@workflow_signals, @workflow_updates]]
318
+ ), @workflow_queries]
319
319
  when :update
320
320
  [Update.new(
321
321
  name: handler[:dynamic] ? nil : (handler[:name] || method_name).to_s,
@@ -325,7 +325,7 @@ module Temporalio
325
325
  unfinished_policy: handler[:unfinished_policy],
326
326
  arg_hints: handler[:arg_hints],
327
327
  result_hint: handler[:result_hint]
328
- ), @workflow_updates, [@workflow_signals, @workflow_queries]]
328
+ ), @workflow_updates]
329
329
  when :dynamic_options
330
330
  raise 'Dynamic options method already set' if @dynamic_options_method
331
331
 
@@ -341,8 +341,6 @@ module Temporalio
341
341
  if other && other.to_invoke != method_name
342
342
  raise "Workflow #{handler[:type].name} #{defn.name || '<dynamic>'} defined on " \
343
343
  "different methods #{other.to_invoke} and #{method_name}"
344
- elsif defn.name && other_hashes.any? { |h| h.include?(defn.name) }
345
- raise "Workflow signal #{defn.name} already defined as a different handler type"
346
344
  end
347
345
  hash[defn.name] = defn
348
346
 
@@ -7,6 +7,7 @@ module Temporalio
7
7
  :continued_run_id,
8
8
  :cron_schedule,
9
9
  :execution_timeout,
10
+ :first_execution_run_id,
10
11
  :headers,
11
12
  :last_failure,
12
13
  :last_result,
@@ -35,6 +36,8 @@ module Temporalio
35
36
  # @return [String, nil] Cron schedule if applicable.
36
37
  # @!attribute execution_timeout
37
38
  # @return [Float, nil] Execution timeout for the workflow.
39
+ # @!attribute first_execution_run_id
40
+ # @return [String] The very first run ID the workflow ever had, following continuation chains.
38
41
  # @!attribute headers
39
42
  # @return [Hash<String, Api::Common::V1::Payload>] Headers.
40
43
  # @!attribute last_failure
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'random/formatter'
4
4
  require 'temporalio/error'
5
+ require 'temporalio/internal/worker/workflow_instance'
5
6
  require 'temporalio/priority'
6
7
  require 'temporalio/workflow/activity_cancellation_type'
7
8
  require 'temporalio/workflow/child_workflow_cancellation_type'
@@ -207,14 +208,16 @@ module Temporalio
207
208
  #
208
209
  # @param activity [Class<Activity::Definition>, Symbol, String] Activity definition class or name.
209
210
  # @param args [Array<Object>] Arguments to the activity.
211
+ # @param summary [String, nil] Single-line summary for this activity that may appear in CLI/UI. This can be in
212
+ # single-line Temporal markdown format. This is currently experimental.
210
213
  # @param schedule_to_close_timeout [Float, nil] Max amount of time the activity can take from first being scheduled
211
214
  # to being completed before it times out. This is inclusive of all retries.
212
215
  # @param schedule_to_start_timeout [Float, nil] Max amount of time the activity can take to be started from first
213
216
  # being scheduled.
214
217
  # @param start_to_close_timeout [Float, nil] Max amount of time a single activity run can take from when it starts
215
218
  # to when it completes. This is per retry.
216
- # @param retry_policy [RetryPolicy] How an activity is retried on failure. If unset, a server-defined default is
217
- # used. Set maximum attempts to 1 to disable retries.
219
+ # @param retry_policy [RetryPolicy, nil] How an activity is retried on failure. If unset, a default policy is used.
220
+ # Set maximum attempts to 1 to disable retries.
218
221
  # @param local_retry_threshold [Float, nil] If the activity is retrying and backoff would exceed this value, a timer
219
222
  # is scheduled and the activity is retried after. Otherwise, backoff will happen internally within the task.
220
223
  # Defaults to 1 minute.
@@ -237,6 +240,7 @@ module Temporalio
237
240
  def self.execute_local_activity(
238
241
  activity,
239
242
  *args,
243
+ summary: nil,
240
244
  schedule_to_close_timeout: nil,
241
245
  schedule_to_start_timeout: nil,
242
246
  start_to_close_timeout: nil,
@@ -250,7 +254,7 @@ module Temporalio
250
254
  )
251
255
  _current.execute_local_activity(
252
256
  activity, *args,
253
- schedule_to_close_timeout:, schedule_to_start_timeout:, start_to_close_timeout:,
257
+ summary:, schedule_to_close_timeout:, schedule_to_start_timeout:, start_to_close_timeout:,
254
258
  retry_policy:, local_retry_threshold:, cancellation:, cancellation_type:,
255
259
  activity_id:, arg_hints:, result_hint:
256
260
  )
@@ -537,26 +541,72 @@ module Temporalio
537
541
  # Run a block of code with illegal call tracing disabled. Users should be cautious about using this as it can
538
542
  # often signify unsafe code.
539
543
  #
544
+ # If this is invoked outside of a workflow, it just runs the block.
545
+ #
540
546
  # @yield Block to run with call tracing disabled
541
547
  #
542
548
  # @return [Object] Result of the block.
543
549
  def self.illegal_call_tracing_disabled(&)
544
- Workflow._current.illegal_call_tracing_disabled(&)
550
+ if Workflow.in_workflow?
551
+ Workflow._current.illegal_call_tracing_disabled(&)
552
+ else
553
+ yield
554
+ end
545
555
  end
546
556
 
547
557
  # Run a block of code with IO enabled. Specifically this allows the `io_wait` call of the fiber scheduler to work.
548
558
  # Users should be cautious about using this as it can often signify unsafe code. Note, this is often only
549
559
  # applicable to network code as file IO and most process-based IO does not go through scheduler `io_wait`.
560
+ #
561
+ # If this is invoked outside of a workflow, it just runs the block.
550
562
  def self.io_enabled(&)
551
- Workflow._current.io_enabled(&)
563
+ if Workflow.in_workflow?
564
+ Workflow._current.io_enabled(&)
565
+ else
566
+ yield
567
+ end
552
568
  end
553
569
 
554
570
  # Run a block of code with the durable/deterministic workflow Fiber scheduler off. This means fallback to default
555
571
  # fiber scheduler and no workflow helpers will be available in the block. This is usually only needed in advanced
556
572
  # situations where a third party library does something like use "Timeout" in a way that shouldn't be made
557
573
  # durable.
574
+ #
575
+ # If this is invoked outside of a workflow, it just runs the block.
576
+ #
577
+ # This implies {illegal_call_tracing_disabled}.
558
578
  def self.durable_scheduler_disabled(&)
559
- Workflow._current.durable_scheduler_disabled(&)
579
+ if Workflow.in_workflow?
580
+ Workflow._current.durable_scheduler_disabled(&)
581
+ else
582
+ yield
583
+ end
584
+ end
585
+
586
+ # @!visibility private
587
+ def self._wrap_ruby_class_as_legal(target_class)
588
+ Class.new do
589
+ define_method(:initialize) do |*args, **kwargs, &block|
590
+ @underlying = Unsafe.illegal_call_tracing_disabled do
591
+ target_class.new(*args, **kwargs, &block) # steep:ignore
592
+ end
593
+ end
594
+
595
+ # @!visibility private
596
+ def method_missing(name, ...)
597
+ if @underlying.respond_to?(name)
598
+ # Call with tracing disabled
599
+ Unsafe.illegal_call_tracing_disabled { @underlying.public_send(name, ...) }
600
+ else
601
+ super
602
+ end
603
+ end
604
+
605
+ # @!visibility private
606
+ def respond_to_missing?(name, include_all = false)
607
+ @underlying.respond_to?(name, include_all) || super
608
+ end
609
+ end
560
610
  end
561
611
  end
562
612
 
@@ -623,5 +673,29 @@ module Temporalio
623
673
  # error can still be used with configuring workflow failure exception types to change non-deterministic errors from
624
674
  # task failures to workflow failures.
625
675
  class NondeterminismError < Error; end
676
+
677
+ # Mutex is a workflow-safe wrapper around {::Mutex}.
678
+ #
679
+ # As of this writing, all methods on Mutex are safe for workflow use and are implicitly made deterministic by the
680
+ # Fiber scheduler. The primary reason this is wrapped as safe is to be able to catch unintentional uses of Mutex by
681
+ # non-workflow-safe code. However, users may prefer to use the more powerful {wait_condition} approach as a mutex
682
+ # (e.g. wait until a certain attribute is set to false then set it to true before continuing).
683
+ Mutex = Unsafe._wrap_ruby_class_as_legal(::Mutex)
684
+
685
+ # Queue is a workflow-safe wrapper around {::Queue}.
686
+ #
687
+ # As of this writing, all methods on Queue are safe for workflow use and are implicitly made deterministic by the
688
+ # Fiber scheduler. The primary reason this is wrapped as safe is to be able to catch unintentional uses of Queue by
689
+ # non-workflow-safe code. However, users may prefer to use the more powerful {wait_condition} approach as a queue
690
+ # (e.g. wait until an array is non-empty before continuing).
691
+ Queue = Unsafe._wrap_ruby_class_as_legal(::Queue)
692
+
693
+ # SizedQueue is a workflow-safe wrapper around {::SizedQueue}.
694
+ #
695
+ # As of this writing, all methods on SizedQueue are safe for workflow use and are implicitly made deterministic by
696
+ # the Fiber scheduler. The primary reason this is wrapped as safe is to be able to catch unintentional uses of
697
+ # SizedQueue by non-workflow-safe code. However, users may prefer to use the more powerful {wait_condition} approach
698
+ # as a queue (e.g. wait until an array is non-empty before continuing).
699
+ SizedQueue = Unsafe._wrap_ruby_class_as_legal(::SizedQueue)
626
700
  end
627
701
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: temporalio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 1.0.0
5
5
  platform: arm64-darwin
6
6
  authors:
7
7
  - Temporal Technologies Inc
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-07-24 00:00:00.000000000 Z
11
+ date: 2025-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -62,6 +62,7 @@ files:
62
62
  - lib/temporalio/api/cloud/cloudservice.rb
63
63
  - lib/temporalio/api/cloud/cloudservice/v1/request_response.rb
64
64
  - lib/temporalio/api/cloud/cloudservice/v1/service.rb
65
+ - lib/temporalio/api/cloud/connectivityrule/v1/message.rb
65
66
  - lib/temporalio/api/cloud/identity/v1/message.rb
66
67
  - lib/temporalio/api/cloud/namespace/v1/message.rb
67
68
  - lib/temporalio/api/cloud/nexus/v1/message.rb
@@ -107,6 +108,7 @@ files:
107
108
  - lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb
108
109
  - lib/temporalio/api/sdk/v1/task_complete_metadata.rb
109
110
  - lib/temporalio/api/sdk/v1/user_metadata.rb
111
+ - lib/temporalio/api/sdk/v1/worker_config.rb
110
112
  - lib/temporalio/api/sdk/v1/workflow_metadata.rb
111
113
  - lib/temporalio/api/taskqueue/v1/message.rb
112
114
  - lib/temporalio/api/testservice/v1/request_response.rb
@@ -154,6 +156,7 @@ files:
154
156
  - lib/temporalio/converters/payload_converter/json_plain.rb
155
157
  - lib/temporalio/converters/payload_converter/json_protobuf.rb
156
158
  - lib/temporalio/converters/raw_value.rb
159
+ - lib/temporalio/env_config.rb
157
160
  - lib/temporalio/error.rb
158
161
  - lib/temporalio/error/failure.rb
159
162
  - lib/temporalio/internal.rb