temporalio 1.1.0-aarch64-linux-musl → 1.2.0-aarch64-linux-musl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -4
  3. data/lib/temporalio/activity/definition.rb +6 -1
  4. data/lib/temporalio/api/activity/v1/message.rb +11 -2
  5. data/lib/temporalio/api/command/v1/message.rb +1 -1
  6. data/lib/temporalio/api/common/v1/message.rb +2 -1
  7. data/lib/temporalio/api/deployment/v1/message.rb +2 -1
  8. data/lib/temporalio/api/enums/v1/activity.rb +23 -0
  9. data/lib/temporalio/api/enums/v1/event_type.rb +1 -1
  10. data/lib/temporalio/api/enums/v1/failed_cause.rb +1 -1
  11. data/lib/temporalio/api/enums/v1/task_queue.rb +2 -1
  12. data/lib/temporalio/api/enums/v1/workflow.rb +3 -1
  13. data/lib/temporalio/api/errordetails/v1/message.rb +2 -1
  14. data/lib/temporalio/api/history/v1/message.rb +3 -1
  15. data/lib/temporalio/api/namespace/v1/message.rb +2 -1
  16. data/lib/temporalio/api/nexus/v1/message.rb +1 -1
  17. data/lib/temporalio/api/operatorservice/v1/request_response.rb +1 -1
  18. data/lib/temporalio/api/payload_visitor.rb +64 -0
  19. data/lib/temporalio/api/taskqueue/v1/message.rb +1 -1
  20. data/lib/temporalio/api/worker/v1/message.rb +1 -1
  21. data/lib/temporalio/api/workflow/v1/message.rb +2 -1
  22. data/lib/temporalio/api/workflowservice/v1/request_response.rb +23 -1
  23. data/lib/temporalio/api/workflowservice/v1/service.rb +1 -1
  24. data/lib/temporalio/client/connection/workflow_service.rb +150 -0
  25. data/lib/temporalio/client/connection.rb +17 -3
  26. data/lib/temporalio/client/plugin.rb +42 -0
  27. data/lib/temporalio/client.rb +82 -13
  28. data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +4 -1
  29. data/lib/temporalio/converters/payload_converter/json_protobuf.rb +4 -1
  30. data/lib/temporalio/env_config.rb +2 -11
  31. data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.so +0 -0
  32. data/lib/temporalio/internal/bridge/3.4/temporalio_bridge.so +0 -0
  33. data/lib/temporalio/internal/bridge/{3.2 → 4.0}/temporalio_bridge.so +0 -0
  34. data/lib/temporalio/internal/bridge/api/core_interface.rb +3 -1
  35. data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +2 -1
  36. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +1 -1
  37. data/lib/temporalio/internal/bridge/worker.rb +1 -0
  38. data/lib/temporalio/internal/worker/workflow_instance/context.rb +4 -0
  39. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +1 -1
  40. data/lib/temporalio/internal/worker/workflow_instance/handler_hash.rb +1 -1
  41. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +8 -4
  42. data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +32 -11
  43. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +2 -1
  44. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_metric.rb +2 -1
  45. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +10 -1
  46. data/lib/temporalio/internal/worker/workflow_instance.rb +15 -11
  47. data/lib/temporalio/simple_plugin.rb +192 -0
  48. data/lib/temporalio/version.rb +1 -1
  49. data/lib/temporalio/worker/plugin.rb +88 -0
  50. data/lib/temporalio/worker/workflow_replayer.rb +28 -5
  51. data/lib/temporalio/worker.rb +116 -42
  52. data/lib/temporalio/workflow/definition.rb +3 -1
  53. data/lib/temporalio/workflow.rb +8 -1
  54. data/temporalio.gemspec +1 -1
  55. metadata +9 -5
@@ -15,6 +15,7 @@ require 'temporalio/worker/activity_executor'
15
15
  require 'temporalio/worker/deployment_options'
16
16
  require 'temporalio/worker/illegal_workflow_call_validator'
17
17
  require 'temporalio/worker/interceptor'
18
+ require 'temporalio/worker/plugin'
18
19
  require 'temporalio/worker/poller_behavior'
19
20
  require 'temporalio/worker/thread_pool'
20
21
  require 'temporalio/worker/tuner'
@@ -35,6 +36,7 @@ module Temporalio
35
36
  :tuner,
36
37
  :activity_executors,
37
38
  :workflow_executor,
39
+ :plugins,
38
40
  :interceptors,
39
41
  :identity,
40
42
  :logger,
@@ -122,6 +124,42 @@ module Temporalio
122
124
  raise_in_block_on_shutdown: Error::CanceledError.new('Workers finished'),
123
125
  wait_block_complete: true,
124
126
  &block
127
+ )
128
+ # We have to apply plugins. However, every plugin has a different worker. So we provide them the worker along with
129
+ # other options, but we disregard any mutation of the worker on the next call.
130
+ run_worker = proc do |options|
131
+ # @type var options: Plugin::RunWorkerOptions
132
+ _run_all_root(*workers,
133
+ cancellation: options.cancellation,
134
+ shutdown_signals: options.shutdown_signals,
135
+ raise_in_block_on_shutdown: options.raise_in_block_on_shutdown,
136
+ wait_block_complete:, &block)
137
+ end
138
+ plugins_with_workers = workers.flat_map { |w| w._plugins.map { |p| [p, w] } }
139
+ run_worker = plugins_with_workers.reverse_each.reduce(run_worker) do |next_call, plugin_with_worker|
140
+ plugin, worker = plugin_with_worker
141
+ proc do |options|
142
+ plugin.run_worker(options.with(worker:), next_call) # steep:ignore
143
+ end
144
+ end
145
+
146
+ run_worker.call(Plugin::RunWorkerOptions.new(
147
+ # Intentionally violating typing here because we set this on each call
148
+ worker: nil, # steep:ignore
149
+ cancellation:,
150
+ shutdown_signals:,
151
+ raise_in_block_on_shutdown:
152
+ ))
153
+ end
154
+
155
+ # @!visibility private
156
+ def self._run_all_root(
157
+ *workers,
158
+ cancellation:,
159
+ shutdown_signals:,
160
+ raise_in_block_on_shutdown:,
161
+ wait_block_complete:,
162
+ &block
125
163
  )
126
164
  # Confirm there is at least one and they are all workers
127
165
  raise ArgumentError, 'At least one worker required' if workers.empty?
@@ -301,6 +339,19 @@ module Temporalio
301
339
  end
302
340
  end
303
341
 
342
+ # @!visibility private
343
+ def self._validate_plugins!(plugins)
344
+ plugins.each do |plugin|
345
+ raise ArgumentError, "#{plugin.class} does not implement Worker::Plugin" unless plugin.is_a?(Plugin)
346
+
347
+ # Validate plugin has implemented expected methods
348
+ missing = Plugin.instance_methods(false).select { |m| plugin.method(m).owner == Plugin }
349
+ unless missing.empty?
350
+ raise ArgumentError, "#{plugin.class} missing the following worker plugin method(s): #{missing.join(', ')}"
351
+ end
352
+ end
353
+ end
354
+
304
355
  # @return [Options] Options for this worker which has the same attributes as {initialize}.
305
356
  attr_reader :options
306
357
 
@@ -315,6 +366,9 @@ module Temporalio
315
366
  # @param activity_executors [Hash<Symbol, Worker::ActivityExecutor>] Executors that activities can run within.
316
367
  # @param workflow_executor [WorkflowExecutor] Workflow executor that workflow tasks run within. This must be a
317
368
  # {WorkflowExecutor::ThreadPool} currently.
369
+ # @param plugins [Array<Plugin>] Plugins to use for configuring workers and intercepting the running of workers. Any
370
+ # plugins that were set on the client that include {Plugin} will automatically be applied to the worker and
371
+ # should not be configured explicitly via this option. WARNING: Plugins are experimental.
318
372
  # @param interceptors [Array<Interceptor::Activity, Interceptor::Workflow>] Interceptors specific to this worker.
319
373
  # Note, interceptors set on the client that include the {Interceptor::Activity} or {Interceptor::Workflow} module
320
374
  # are automatically included here, so no need to specify them again.
@@ -387,6 +441,7 @@ module Temporalio
387
441
  tuner: Tuner.create_fixed,
388
442
  activity_executors: ActivityExecutor.defaults,
389
443
  workflow_executor: WorkflowExecutor::ThreadPool.default,
444
+ plugins: [],
390
445
  interceptors: [],
391
446
  identity: nil,
392
447
  logger: client.options.logger,
@@ -411,8 +466,6 @@ module Temporalio
411
466
  activity_task_poller_behavior: PollerBehavior::SimpleMaximum.new(max_concurrent_activity_task_polls),
412
467
  debug_mode: %w[true 1].include?(ENV['TEMPORAL_DEBUG'].to_s.downcase)
413
468
  )
414
- raise ArgumentError, 'Must have at least one activity or workflow' if activities.empty? && workflows.empty?
415
-
416
469
  Internal::ProtoUtils.assert_non_reserved_name(task_queue)
417
470
 
418
471
  @options = Options.new(
@@ -423,6 +476,7 @@ module Temporalio
423
476
  tuner:,
424
477
  activity_executors:,
425
478
  workflow_executor:,
479
+ plugins:,
426
480
  interceptors:,
427
481
  identity:,
428
482
  logger:,
@@ -447,53 +501,68 @@ module Temporalio
447
501
  activity_task_poller_behavior:,
448
502
  debug_mode:
449
503
  ).freeze
504
+ # Collect applicable client plugins and worker plugins, then validate and apply to options
505
+ @plugins = client.options.plugins.grep(Plugin) + plugins
506
+ Worker._validate_plugins!(@plugins)
507
+ @options = @plugins.reduce(@options) { |options, plugin| plugin.configure_worker(options) }
508
+ # Initialize the worker for the given options
509
+ _initialize_from_options
510
+ end
511
+
512
+ # @!visibility private
513
+ def _initialize_from_options
514
+ if @options.activities.empty? && @options.workflows.empty?
515
+ raise ArgumentError, 'Must have at least one activity or workflow'
516
+ end
450
517
 
451
518
  should_enforce_versioning_behavior =
452
- deployment_options.use_worker_versioning &&
453
- deployment_options.default_versioning_behavior == VersioningBehavior::UNSPECIFIED
519
+ @options.deployment_options.use_worker_versioning &&
520
+ @options.deployment_options.default_versioning_behavior == VersioningBehavior::UNSPECIFIED
454
521
  # Preload workflow definitions and some workflow settings for the bridge
455
522
  workflow_definitions = Internal::Worker::WorkflowWorker.workflow_definitions(
456
- workflows,
457
- should_enforce_versioning_behavior: should_enforce_versioning_behavior
523
+ @options.workflows,
524
+ should_enforce_versioning_behavior:
458
525
  )
459
526
  nondeterminism_as_workflow_fail, nondeterminism_as_workflow_fail_for_types =
460
527
  Internal::Worker::WorkflowWorker.bridge_workflow_failure_exception_type_options(
461
- workflow_failure_exception_types:, workflow_definitions:
528
+ workflow_failure_exception_types: @options.workflow_failure_exception_types,
529
+ workflow_definitions:
462
530
  )
463
531
 
464
532
  # Create the bridge worker
465
533
  @bridge_worker = Internal::Bridge::Worker.new(
466
- client.connection._core_client,
534
+ @options.client.connection._core_client,
467
535
  Internal::Bridge::Worker::Options.new(
468
- namespace: client.namespace,
469
- task_queue:,
470
- tuner: tuner._to_bridge_options,
471
- identity_override: identity,
472
- max_cached_workflows:,
473
- workflow_task_poller_behavior: workflow_task_poller_behavior._to_bridge_options,
474
- nonsticky_to_sticky_poll_ratio:,
475
- activity_task_poller_behavior: activity_task_poller_behavior._to_bridge_options,
476
- enable_workflows: !workflows.empty?,
477
- enable_local_activities: !workflows.empty? && !activities.empty?,
478
- enable_remote_activities: !activities.empty? && !no_remote_activities,
536
+ namespace: @options.client.namespace,
537
+ task_queue: @options.task_queue,
538
+ tuner: @options.tuner._to_bridge_options,
539
+ identity_override: @options.identity,
540
+ max_cached_workflows: @options.max_cached_workflows,
541
+ workflow_task_poller_behavior: @options.workflow_task_poller_behavior._to_bridge_options,
542
+ nonsticky_to_sticky_poll_ratio: @options.nonsticky_to_sticky_poll_ratio,
543
+ activity_task_poller_behavior: @options.activity_task_poller_behavior._to_bridge_options,
544
+ enable_workflows: !@options.workflows.empty?,
545
+ enable_local_activities: !@options.workflows.empty? && !@options.activities.empty?,
546
+ enable_remote_activities: !@options.activities.empty? && !@options.no_remote_activities,
479
547
  enable_nexus: false,
480
- sticky_queue_schedule_to_start_timeout:,
481
- max_heartbeat_throttle_interval:,
482
- default_heartbeat_throttle_interval:,
483
- max_worker_activities_per_second: max_activities_per_second,
484
- max_task_queue_activities_per_second:,
485
- graceful_shutdown_period:,
548
+ sticky_queue_schedule_to_start_timeout: @options.sticky_queue_schedule_to_start_timeout,
549
+ max_heartbeat_throttle_interval: @options.max_heartbeat_throttle_interval,
550
+ default_heartbeat_throttle_interval: @options.default_heartbeat_throttle_interval,
551
+ max_worker_activities_per_second: @options.max_activities_per_second,
552
+ max_task_queue_activities_per_second: @options.max_task_queue_activities_per_second,
553
+ graceful_shutdown_period: @options.graceful_shutdown_period,
486
554
  nondeterminism_as_workflow_fail:,
487
555
  nondeterminism_as_workflow_fail_for_types:,
488
- deployment_options: deployment_options._to_bridge_options
556
+ deployment_options: @options.deployment_options._to_bridge_options,
557
+ plugins: (@options.client.options.plugins + @options.plugins).map(&:name).uniq.sort
489
558
  )
490
559
  )
491
560
 
492
561
  # Collect interceptors from client and params
493
- @activity_interceptors = (client.options.interceptors + interceptors).select do |i|
562
+ @activity_interceptors = (@options.client.options.interceptors + @options.interceptors).select do |i|
494
563
  i.is_a?(Interceptor::Activity)
495
564
  end
496
- @workflow_interceptors = (client.options.interceptors + interceptors).select do |i|
565
+ @workflow_interceptors = (@options.client.options.interceptors + @options.interceptors).select do |i|
497
566
  i.is_a?(Interceptor::Workflow)
498
567
  end
499
568
 
@@ -501,27 +570,27 @@ module Temporalio
501
570
  @worker_shutdown_cancellation = Cancellation.new
502
571
 
503
572
  # Create workers
504
- unless activities.empty?
573
+ unless @options.activities.empty?
505
574
  @activity_worker = Internal::Worker::ActivityWorker.new(worker: self,
506
575
  bridge_worker: @bridge_worker)
507
576
  end
508
- unless workflows.empty?
577
+ unless @options.workflows.empty?
509
578
  @workflow_worker = Internal::Worker::WorkflowWorker.new(
510
579
  bridge_worker: @bridge_worker,
511
- namespace: client.namespace,
512
- task_queue:,
580
+ namespace: @options.client.namespace,
581
+ task_queue: @options.task_queue,
513
582
  workflow_definitions:,
514
- workflow_executor:,
515
- logger:,
516
- data_converter: client.data_converter,
517
- metric_meter: client.connection.options.runtime.metric_meter,
583
+ workflow_executor: @options.workflow_executor,
584
+ logger: @options.logger,
585
+ data_converter: @options.client.data_converter,
586
+ metric_meter: @options.client.connection.options.runtime.metric_meter,
518
587
  workflow_interceptors: @workflow_interceptors,
519
- disable_eager_activity_execution:,
520
- illegal_workflow_calls:,
521
- workflow_failure_exception_types:,
522
- workflow_payload_codec_thread_pool:,
523
- unsafe_workflow_io_enabled:,
524
- debug_mode:,
588
+ disable_eager_activity_execution: @options.disable_eager_activity_execution,
589
+ illegal_workflow_calls: @options.illegal_workflow_calls,
590
+ workflow_failure_exception_types: @options.workflow_failure_exception_types,
591
+ workflow_payload_codec_thread_pool: @options.workflow_payload_codec_thread_pool,
592
+ unsafe_workflow_io_enabled: @options.unsafe_workflow_io_enabled,
593
+ debug_mode: @options.debug_mode,
525
594
  assert_valid_local_activity: ->(activity) { _assert_valid_local_activity(activity) }
526
595
  )
527
596
  end
@@ -643,5 +712,10 @@ module Temporalio
643
712
  "Activity #{activity} " \
644
713
  'is not registered on this worker, no available activities.'
645
714
  end
715
+
716
+ # @!visibility private
717
+ def _plugins
718
+ @plugins
719
+ end
646
720
  end
647
721
  end
@@ -102,7 +102,9 @@ module Temporalio
102
102
 
103
103
  # Just run this as if done manually
104
104
  workflow_query(description:)
105
- define_method(attr_name) { instance_variable_get("@#{attr_name}") }
105
+ define_method(attr_name) do
106
+ instance_variable_get("@#{attr_name}") # steep:ignore NoMethod
107
+ end
106
108
  end
107
109
  end
108
110
 
@@ -533,11 +533,18 @@ module Temporalio
533
533
  # Unsafe module contains only-in-workflow methods that are considered unsafe. These should not be used unless the
534
534
  # consequences are understood.
535
535
  module Unsafe
536
- # @return [Boolean] True if the workflow is replaying, false otherwise. Most code should not check this value.
536
+ # @return [Boolean] True if the workflow is replaying (including during queries and update validators), false
537
+ # otherwise. Most code should not check this value.
537
538
  def self.replaying?
538
539
  Workflow._current.replaying?
539
540
  end
540
541
 
542
+ # @return [Boolean] True if the workflow is replaying history events (excluding queries and update validators),
543
+ # false otherwise. Most code should not check this value.
544
+ def self.replaying_history_events?
545
+ Workflow._current.replaying_history_events?
546
+ end
547
+
541
548
  # Run a block of code with illegal call tracing disabled. Users should be cautious about using this as it can
542
549
  # often signify unsafe code.
543
550
  #
data/temporalio.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ['lib']
24
24
  spec.extensions = ['ext/Cargo.toml']
25
25
  spec.metadata['rubygems_mfa_required'] = 'true'
26
- spec.required_ruby_version = '>= 3.2.0'
26
+ spec.required_ruby_version = '>= 3.3.0'
27
27
 
28
28
  spec.add_dependency 'google-protobuf', '>= 3.25.0'
29
29
  spec.add_dependency 'logger'
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: 1.1.0
4
+ version: 1.2.0
5
5
  platform: aarch64-linux-musl
6
6
  authors:
7
7
  - Temporal Technologies Inc
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-12-08 00:00:00.000000000 Z
11
+ date: 2026-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -75,6 +75,7 @@ files:
75
75
  - lib/temporalio/api/common/v1/grpc_status.rb
76
76
  - lib/temporalio/api/common/v1/message.rb
77
77
  - lib/temporalio/api/deployment/v1/message.rb
78
+ - lib/temporalio/api/enums/v1/activity.rb
78
79
  - lib/temporalio/api/enums/v1/batch_operation.rb
79
80
  - lib/temporalio/api/enums/v1/command_type.rb
80
81
  - lib/temporalio/api/enums/v1/common.rb
@@ -131,6 +132,7 @@ files:
131
132
  - lib/temporalio/client/connection/test_service.rb
132
133
  - lib/temporalio/client/connection/workflow_service.rb
133
134
  - lib/temporalio/client/interceptor.rb
135
+ - lib/temporalio/client/plugin.rb
134
136
  - lib/temporalio/client/schedule.rb
135
137
  - lib/temporalio/client/schedule_handle.rb
136
138
  - lib/temporalio/client/with_start_workflow_operation.rb
@@ -161,9 +163,9 @@ files:
161
163
  - lib/temporalio/error/failure.rb
162
164
  - lib/temporalio/internal.rb
163
165
  - lib/temporalio/internal/bridge.rb
164
- - lib/temporalio/internal/bridge/3.2/temporalio_bridge.so
165
166
  - lib/temporalio/internal/bridge/3.3/temporalio_bridge.so
166
167
  - lib/temporalio/internal/bridge/3.4/temporalio_bridge.so
168
+ - lib/temporalio/internal/bridge/4.0/temporalio_bridge.so
167
169
  - lib/temporalio/internal/bridge/api.rb
168
170
  - lib/temporalio/internal/bridge/api/activity_result/activity_result.rb
169
171
  - lib/temporalio/internal/bridge/api/activity_task/activity_task.rb
@@ -206,6 +208,7 @@ files:
206
208
  - lib/temporalio/runtime/metric_buffer.rb
207
209
  - lib/temporalio/scoped_logger.rb
208
210
  - lib/temporalio/search_attributes.rb
211
+ - lib/temporalio/simple_plugin.rb
209
212
  - lib/temporalio/testing.rb
210
213
  - lib/temporalio/testing/activity_environment.rb
211
214
  - lib/temporalio/testing/workflow_environment.rb
@@ -218,6 +221,7 @@ files:
218
221
  - lib/temporalio/worker/deployment_options.rb
219
222
  - lib/temporalio/worker/illegal_workflow_call_validator.rb
220
223
  - lib/temporalio/worker/interceptor.rb
224
+ - lib/temporalio/worker/plugin.rb
221
225
  - lib/temporalio/worker/poller_behavior.rb
222
226
  - lib/temporalio/worker/thread_pool.rb
223
227
  - lib/temporalio/worker/tuner.rb
@@ -253,10 +257,10 @@ required_ruby_version: !ruby/object:Gem::Requirement
253
257
  requirements:
254
258
  - - ">="
255
259
  - !ruby/object:Gem::Version
256
- version: '3.2'
260
+ version: '3.3'
257
261
  - - "<"
258
262
  - !ruby/object:Gem::Version
259
- version: 3.5.dev
263
+ version: 4.1.dev
260
264
  required_rubygems_version: !ruby/object:Gem::Requirement
261
265
  requirements:
262
266
  - - ">="