temporalio 1.1.0 → 1.3.0

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +228 -194
  3. data/Cargo.toml +9 -1
  4. data/Gemfile +6 -4
  5. data/README.md +2 -2
  6. data/ext/Cargo.toml +5 -1
  7. data/lib/temporalio/activity/definition.rb +6 -1
  8. data/lib/temporalio/api/activity/v1/message.rb +11 -2
  9. data/lib/temporalio/api/command/v1/message.rb +1 -1
  10. data/lib/temporalio/api/common/v1/message.rb +2 -1
  11. data/lib/temporalio/api/deployment/v1/message.rb +2 -1
  12. data/lib/temporalio/api/enums/v1/activity.rb +23 -0
  13. data/lib/temporalio/api/enums/v1/event_type.rb +1 -1
  14. data/lib/temporalio/api/enums/v1/failed_cause.rb +1 -1
  15. data/lib/temporalio/api/enums/v1/task_queue.rb +2 -1
  16. data/lib/temporalio/api/enums/v1/workflow.rb +3 -1
  17. data/lib/temporalio/api/errordetails/v1/message.rb +2 -1
  18. data/lib/temporalio/api/history/v1/message.rb +3 -1
  19. data/lib/temporalio/api/namespace/v1/message.rb +2 -1
  20. data/lib/temporalio/api/nexus/v1/message.rb +1 -1
  21. data/lib/temporalio/api/operatorservice/v1/request_response.rb +1 -1
  22. data/lib/temporalio/api/payload_visitor.rb +64 -0
  23. data/lib/temporalio/api/taskqueue/v1/message.rb +1 -1
  24. data/lib/temporalio/api/worker/v1/message.rb +1 -1
  25. data/lib/temporalio/api/workflow/v1/message.rb +2 -1
  26. data/lib/temporalio/api/workflowservice/v1/request_response.rb +23 -1
  27. data/lib/temporalio/api/workflowservice/v1/service.rb +1 -1
  28. data/lib/temporalio/client/connection/workflow_service.rb +150 -0
  29. data/lib/temporalio/client/connection.rb +17 -3
  30. data/lib/temporalio/client/plugin.rb +42 -0
  31. data/lib/temporalio/client.rb +82 -15
  32. data/lib/temporalio/common_enums.rb +0 -2
  33. data/lib/temporalio/contrib/open_telemetry.rb +21 -0
  34. data/lib/temporalio/converters/failure_converter.rb +30 -0
  35. data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +4 -1
  36. data/lib/temporalio/converters/payload_converter/json_protobuf.rb +4 -1
  37. data/lib/temporalio/env_config.rb +3 -14
  38. data/lib/temporalio/error/failure.rb +66 -0
  39. data/lib/temporalio/internal/bridge/api/core_interface.rb +3 -1
  40. data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +2 -1
  41. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +1 -1
  42. data/lib/temporalio/internal/bridge/worker.rb +1 -0
  43. data/lib/temporalio/internal/worker/workflow_instance/context.rb +9 -0
  44. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +1 -1
  45. data/lib/temporalio/internal/worker/workflow_instance/handler_hash.rb +1 -1
  46. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +8 -4
  47. data/lib/temporalio/internal/worker/workflow_instance/nexus_client.rb +42 -0
  48. data/lib/temporalio/internal/worker/workflow_instance/nexus_operation_handle.rb +51 -0
  49. data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +100 -11
  50. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +2 -1
  51. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_metric.rb +2 -1
  52. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +10 -1
  53. data/lib/temporalio/internal/worker/workflow_instance.rb +26 -11
  54. data/lib/temporalio/simple_plugin.rb +192 -0
  55. data/lib/temporalio/testing/workflow_environment.rb +40 -0
  56. data/lib/temporalio/version.rb +1 -1
  57. data/lib/temporalio/versioning_override.rb +0 -2
  58. data/lib/temporalio/worker/deployment_options.rb +0 -2
  59. data/lib/temporalio/worker/interceptor.rb +27 -0
  60. data/lib/temporalio/worker/plugin.rb +88 -0
  61. data/lib/temporalio/worker/workflow_executor/thread_pool.rb +1 -1
  62. data/lib/temporalio/worker/workflow_replayer.rb +28 -5
  63. data/lib/temporalio/worker.rb +116 -43
  64. data/lib/temporalio/worker_deployment_version.rb +0 -2
  65. data/lib/temporalio/workflow/definition.rb +3 -4
  66. data/lib/temporalio/workflow/nexus_client.rb +81 -0
  67. data/lib/temporalio/workflow/nexus_operation_cancellation_type.rb +21 -0
  68. data/lib/temporalio/workflow/nexus_operation_handle.rb +37 -0
  69. data/lib/temporalio/workflow.rb +22 -1
  70. data/temporalio.gemspec +1 -1
  71. metadata +12 -3
@@ -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.
@@ -371,7 +425,6 @@ module Temporalio
371
425
  # scheduler will fail. Instead of setting this to true, users are encouraged to use {Workflow::Unsafe.io_enabled}
372
426
  # with a block for narrower enabling of IO.
373
427
  # @param deployment_options [DeploymentOptions, nil] Deployment options for the worker.
374
- # WARNING: This is an experimental feature and may change in the future.
375
428
  # @param workflow_task_poller_behavior [PollerBehavior] Specify the behavior of workflow task
376
429
  # polling. Defaults to a 5-poller maximum.
377
430
  # @param activity_task_poller_behavior [PollerBehavior] Specify the behavior of activity task
@@ -387,6 +440,7 @@ module Temporalio
387
440
  tuner: Tuner.create_fixed,
388
441
  activity_executors: ActivityExecutor.defaults,
389
442
  workflow_executor: WorkflowExecutor::ThreadPool.default,
443
+ plugins: [],
390
444
  interceptors: [],
391
445
  identity: nil,
392
446
  logger: client.options.logger,
@@ -411,8 +465,6 @@ module Temporalio
411
465
  activity_task_poller_behavior: PollerBehavior::SimpleMaximum.new(max_concurrent_activity_task_polls),
412
466
  debug_mode: %w[true 1].include?(ENV['TEMPORAL_DEBUG'].to_s.downcase)
413
467
  )
414
- raise ArgumentError, 'Must have at least one activity or workflow' if activities.empty? && workflows.empty?
415
-
416
468
  Internal::ProtoUtils.assert_non_reserved_name(task_queue)
417
469
 
418
470
  @options = Options.new(
@@ -423,6 +475,7 @@ module Temporalio
423
475
  tuner:,
424
476
  activity_executors:,
425
477
  workflow_executor:,
478
+ plugins:,
426
479
  interceptors:,
427
480
  identity:,
428
481
  logger:,
@@ -447,53 +500,68 @@ module Temporalio
447
500
  activity_task_poller_behavior:,
448
501
  debug_mode:
449
502
  ).freeze
503
+ # Collect applicable client plugins and worker plugins, then validate and apply to options
504
+ @plugins = client.options.plugins.grep(Plugin) + plugins
505
+ Worker._validate_plugins!(@plugins)
506
+ @options = @plugins.reduce(@options) { |options, plugin| plugin.configure_worker(options) }
507
+ # Initialize the worker for the given options
508
+ _initialize_from_options
509
+ end
510
+
511
+ # @!visibility private
512
+ def _initialize_from_options
513
+ if @options.activities.empty? && @options.workflows.empty?
514
+ raise ArgumentError, 'Must have at least one activity or workflow'
515
+ end
450
516
 
451
517
  should_enforce_versioning_behavior =
452
- deployment_options.use_worker_versioning &&
453
- deployment_options.default_versioning_behavior == VersioningBehavior::UNSPECIFIED
518
+ @options.deployment_options.use_worker_versioning &&
519
+ @options.deployment_options.default_versioning_behavior == VersioningBehavior::UNSPECIFIED
454
520
  # Preload workflow definitions and some workflow settings for the bridge
455
521
  workflow_definitions = Internal::Worker::WorkflowWorker.workflow_definitions(
456
- workflows,
457
- should_enforce_versioning_behavior: should_enforce_versioning_behavior
522
+ @options.workflows,
523
+ should_enforce_versioning_behavior:
458
524
  )
459
525
  nondeterminism_as_workflow_fail, nondeterminism_as_workflow_fail_for_types =
460
526
  Internal::Worker::WorkflowWorker.bridge_workflow_failure_exception_type_options(
461
- workflow_failure_exception_types:, workflow_definitions:
527
+ workflow_failure_exception_types: @options.workflow_failure_exception_types,
528
+ workflow_definitions:
462
529
  )
463
530
 
464
531
  # Create the bridge worker
465
532
  @bridge_worker = Internal::Bridge::Worker.new(
466
- client.connection._core_client,
533
+ @options.client.connection._core_client,
467
534
  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,
535
+ namespace: @options.client.namespace,
536
+ task_queue: @options.task_queue,
537
+ tuner: @options.tuner._to_bridge_options,
538
+ identity_override: @options.identity,
539
+ max_cached_workflows: @options.max_cached_workflows,
540
+ workflow_task_poller_behavior: @options.workflow_task_poller_behavior._to_bridge_options,
541
+ nonsticky_to_sticky_poll_ratio: @options.nonsticky_to_sticky_poll_ratio,
542
+ activity_task_poller_behavior: @options.activity_task_poller_behavior._to_bridge_options,
543
+ enable_workflows: !@options.workflows.empty?,
544
+ enable_local_activities: !@options.workflows.empty? && !@options.activities.empty?,
545
+ enable_remote_activities: !@options.activities.empty? && !@options.no_remote_activities,
479
546
  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:,
547
+ sticky_queue_schedule_to_start_timeout: @options.sticky_queue_schedule_to_start_timeout,
548
+ max_heartbeat_throttle_interval: @options.max_heartbeat_throttle_interval,
549
+ default_heartbeat_throttle_interval: @options.default_heartbeat_throttle_interval,
550
+ max_worker_activities_per_second: @options.max_activities_per_second,
551
+ max_task_queue_activities_per_second: @options.max_task_queue_activities_per_second,
552
+ graceful_shutdown_period: @options.graceful_shutdown_period,
486
553
  nondeterminism_as_workflow_fail:,
487
554
  nondeterminism_as_workflow_fail_for_types:,
488
- deployment_options: deployment_options._to_bridge_options
555
+ deployment_options: @options.deployment_options._to_bridge_options,
556
+ plugins: (@options.client.options.plugins + @options.plugins).map(&:name).uniq.sort
489
557
  )
490
558
  )
491
559
 
492
560
  # Collect interceptors from client and params
493
- @activity_interceptors = (client.options.interceptors + interceptors).select do |i|
561
+ @activity_interceptors = (@options.client.options.interceptors + @options.interceptors).select do |i|
494
562
  i.is_a?(Interceptor::Activity)
495
563
  end
496
- @workflow_interceptors = (client.options.interceptors + interceptors).select do |i|
564
+ @workflow_interceptors = (@options.client.options.interceptors + @options.interceptors).select do |i|
497
565
  i.is_a?(Interceptor::Workflow)
498
566
  end
499
567
 
@@ -501,27 +569,27 @@ module Temporalio
501
569
  @worker_shutdown_cancellation = Cancellation.new
502
570
 
503
571
  # Create workers
504
- unless activities.empty?
572
+ unless @options.activities.empty?
505
573
  @activity_worker = Internal::Worker::ActivityWorker.new(worker: self,
506
574
  bridge_worker: @bridge_worker)
507
575
  end
508
- unless workflows.empty?
576
+ unless @options.workflows.empty?
509
577
  @workflow_worker = Internal::Worker::WorkflowWorker.new(
510
578
  bridge_worker: @bridge_worker,
511
- namespace: client.namespace,
512
- task_queue:,
579
+ namespace: @options.client.namespace,
580
+ task_queue: @options.task_queue,
513
581
  workflow_definitions:,
514
- workflow_executor:,
515
- logger:,
516
- data_converter: client.data_converter,
517
- metric_meter: client.connection.options.runtime.metric_meter,
582
+ workflow_executor: @options.workflow_executor,
583
+ logger: @options.logger,
584
+ data_converter: @options.client.data_converter,
585
+ metric_meter: @options.client.connection.options.runtime.metric_meter,
518
586
  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:,
587
+ disable_eager_activity_execution: @options.disable_eager_activity_execution,
588
+ illegal_workflow_calls: @options.illegal_workflow_calls,
589
+ workflow_failure_exception_types: @options.workflow_failure_exception_types,
590
+ workflow_payload_codec_thread_pool: @options.workflow_payload_codec_thread_pool,
591
+ unsafe_workflow_io_enabled: @options.unsafe_workflow_io_enabled,
592
+ debug_mode: @options.debug_mode,
525
593
  assert_valid_local_activity: ->(activity) { _assert_valid_local_activity(activity) }
526
594
  )
527
595
  end
@@ -643,5 +711,10 @@ module Temporalio
643
711
  "Activity #{activity} " \
644
712
  'is not registered on this worker, no available activities.'
645
713
  end
714
+
715
+ # @!visibility private
716
+ def _plugins
717
+ @plugins
718
+ end
646
719
  end
647
720
  end
@@ -9,8 +9,6 @@ module Temporalio
9
9
  )
10
10
 
11
11
  # Represents the version of a specific worker deployment.
12
- #
13
- # WARNING: Experimental API.
14
12
  class WorkerDeploymentVersion
15
13
  # Parse a version from a canonical string, which must be in the format
16
14
  # `<deployment_name>.<build_id>`. Deployment name must not have a `.` in it.
@@ -102,14 +102,14 @@ 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
 
109
111
  # Set the versioning behavior of this workflow.
110
112
  #
111
- # WARNING: This method is experimental and may change in future versions.
112
- #
113
113
  # @param behavior [VersioningBehavior] The versioning behavior.
114
114
  def workflow_versioning_behavior(behavior)
115
115
  @versioning_behavior = behavior
@@ -730,7 +730,6 @@ module Temporalio
730
730
  # @!attribute versioning_behavior
731
731
  # Dynamic equivalent of {Definition.workflow_versioning_behavior}.
732
732
  # Will override any behavior set there if set.
733
- # WARNING: Deployment-based versioning is experimental and APIs may change.
734
733
  # @return [VersioningBehavior, nil] The versioning behavior
735
734
  #
736
735
  # @return [VersioningBehavior, nil] The versioning behavior
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Temporalio
4
+ module Workflow
5
+ # Client for executing Nexus operations from workflows.
6
+ #
7
+ # This is created via {Workflow.create_nexus_client}, it is never instantiated directly.
8
+ #
9
+ # WARNING: Nexus support is experimental.
10
+ class NexusClient
11
+ # @!visibility private
12
+ def initialize
13
+ raise NotImplementedError, 'Cannot instantiate a Nexus client directly'
14
+ end
15
+
16
+ # @return [String] Endpoint name for this client.
17
+ def endpoint
18
+ raise NotImplementedError
19
+ end
20
+
21
+ # @return [String] Service name for this client.
22
+ def service
23
+ raise NotImplementedError
24
+ end
25
+
26
+ # Start a Nexus operation and return a handle.
27
+ #
28
+ # @param operation [Symbol, String] Operation name.
29
+ # @param arg [Object] Argument for the operation.
30
+ # @param schedule_to_close_timeout [Float, nil] Total timeout for the operation in seconds.
31
+ # @param cancellation_type [NexusOperationCancellationType] How the operation will react to cancellation.
32
+ # @param summary [String, nil] Optional summary for the operation (appears in UI/CLI).
33
+ # @param cancellation [Cancellation] Cancellation for the operation.
34
+ # @param arg_hint [Object, nil] Converter hint for the argument.
35
+ # @param result_hint [Object, nil] Converter hint for the result.
36
+ # @return [NexusOperationHandle] Handle to the started operation.
37
+ def start_operation(
38
+ operation,
39
+ arg,
40
+ schedule_to_close_timeout: nil,
41
+ cancellation_type: NexusOperationCancellationType::WAIT_CANCELLATION_COMPLETED,
42
+ summary: nil,
43
+ cancellation: Workflow.cancellation,
44
+ arg_hint: nil,
45
+ result_hint: nil
46
+ )
47
+ raise NotImplementedError
48
+ end
49
+
50
+ # Execute a Nexus operation and wait for the result.
51
+ #
52
+ # This is a convenience method that calls {#start_operation} and immediately waits for the result.
53
+ #
54
+ # @param operation [Symbol, String] Operation name.
55
+ # @param arg [Object] Argument for the operation.
56
+ # @param schedule_to_close_timeout [Float, nil] Total timeout for the operation in seconds.
57
+ # @param cancellation_type [NexusOperationCancellationType] How the operation will react to cancellation.
58
+ # @param summary [String, nil] Optional summary for the operation (appears in UI/CLI).
59
+ # @param cancellation [Cancellation] Cancellation for the operation.
60
+ # @param arg_hint [Object, nil] Converter hint for the argument.
61
+ # @param result_hint [Object, nil] Converter hint for the result.
62
+ # @return [Object] Result of the operation.
63
+ # @raise [Error::NexusOperationError] Operation failed.
64
+ def execute_operation(
65
+ operation,
66
+ arg,
67
+ schedule_to_close_timeout: nil,
68
+ cancellation_type: NexusOperationCancellationType::WAIT_CANCELLATION_COMPLETED,
69
+ summary: nil,
70
+ cancellation: Workflow.cancellation,
71
+ arg_hint: nil,
72
+ result_hint: nil
73
+ )
74
+ start_operation(
75
+ operation, arg, schedule_to_close_timeout:, cancellation_type:, summary:, cancellation:,
76
+ arg_hint:, result_hint:
77
+ ).result
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'temporalio/internal/bridge/api'
4
+
5
+ module Temporalio
6
+ module Workflow
7
+ # How a Nexus operation should handle cancellation.
8
+ #
9
+ # WARNING: Nexus support is experimental.
10
+ module NexusOperationCancellationType
11
+ # Wait for cancellation to complete (default).
12
+ WAIT_CANCELLATION_COMPLETED = Internal::Bridge::Api::Nexus::NexusOperationCancellationType::WAIT_CANCELLATION_COMPLETED
13
+ # Abandon the operation without sending a cancellation request.
14
+ ABANDON = Internal::Bridge::Api::Nexus::NexusOperationCancellationType::ABANDON
15
+ # Send a cancellation request but do not wait for confirmation.
16
+ TRY_CANCEL = Internal::Bridge::Api::Nexus::NexusOperationCancellationType::TRY_CANCEL
17
+ # Wait for the server to confirm the cancellation request was delivered.
18
+ WAIT_CANCELLATION_REQUESTED = Internal::Bridge::Api::Nexus::NexusOperationCancellationType::WAIT_CANCELLATION_REQUESTED
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Temporalio
4
+ module Workflow
5
+ # Handle for interacting with a Nexus operation.
6
+ #
7
+ # This is created via {NexusClient#start_operation}, it is never instantiated directly.
8
+ #
9
+ # WARNING: Nexus support is experimental.
10
+ class NexusOperationHandle
11
+ # @!visibility private
12
+ def initialize
13
+ raise NotImplementedError, 'Cannot instantiate a Nexus operation handle directly'
14
+ end
15
+
16
+ # @return [String, nil] Operation token for async operations, nil for sync operations.
17
+ def operation_token
18
+ raise NotImplementedError
19
+ end
20
+
21
+ # @return [Object, nil] Hint for the result if any.
22
+ def result_hint
23
+ raise NotImplementedError
24
+ end
25
+
26
+ # Wait for the result.
27
+ #
28
+ # @param result_hint [Object, nil] Override the result hint, or if nil uses the one on the handle.
29
+ # @return [Object] Result of the Nexus operation.
30
+ #
31
+ # @raise [Error::NexusOperationError] Operation failed with +cause+ as the cause.
32
+ def result(result_hint: nil)
33
+ raise NotImplementedError
34
+ end
35
+ end
36
+ end
37
+ end
@@ -12,6 +12,9 @@ require 'temporalio/workflow/external_workflow_handle'
12
12
  require 'temporalio/workflow/future'
13
13
  require 'temporalio/workflow/handler_unfinished_policy'
14
14
  require 'temporalio/workflow/info'
15
+ require 'temporalio/workflow/nexus_client'
16
+ require 'temporalio/workflow/nexus_operation_cancellation_type'
17
+ require 'temporalio/workflow/nexus_operation_handle'
15
18
  require 'temporalio/workflow/parent_close_policy'
16
19
  require 'temporalio/workflow/update_info'
17
20
  require 'timeout'
@@ -40,6 +43,17 @@ module Temporalio
40
43
  _current.continue_as_new_suggested
41
44
  end
42
45
 
46
+ # Create a Nexus client for executing operations.
47
+ #
48
+ # WARNING: Nexus support is experimental.
49
+ #
50
+ # @param endpoint [Symbol, String] Endpoint name.
51
+ # @param service [Symbol, String] Service name.
52
+ # @return [NexusClient] Client for executing Nexus operations.
53
+ def self.create_nexus_client(endpoint:, service:)
54
+ _current.create_nexus_client(endpoint:, service:)
55
+ end
56
+
43
57
  # Get current details for this workflow that may appear in UI/CLI. Unlike static details set at start, this value
44
58
  # can be updated throughout the life of the workflow. This can be in Temporal markdown format and can span multiple
45
59
  # lines. This is currently experimental.
@@ -533,11 +547,18 @@ module Temporalio
533
547
  # Unsafe module contains only-in-workflow methods that are considered unsafe. These should not be used unless the
534
548
  # consequences are understood.
535
549
  module Unsafe
536
- # @return [Boolean] True if the workflow is replaying, false otherwise. Most code should not check this value.
550
+ # @return [Boolean] True if the workflow is replaying (including during queries and update validators), false
551
+ # otherwise. Most code should not check this value.
537
552
  def self.replaying?
538
553
  Workflow._current.replaying?
539
554
  end
540
555
 
556
+ # @return [Boolean] True if the workflow is replaying history events (excluding queries and update validators),
557
+ # false otherwise. Most code should not check this value.
558
+ def self.replaying_history_events?
559
+ Workflow._current.replaying_history_events?
560
+ end
561
+
541
562
  # Run a block of code with illegal call tracing disabled. Users should be cautious about using this as it can
542
563
  # often signify unsafe code.
543
564
  #
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,7 +1,7 @@
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.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Temporal Technologies Inc
@@ -79,6 +79,7 @@ files:
79
79
  - lib/temporalio/api/common/v1/grpc_status.rb
80
80
  - lib/temporalio/api/common/v1/message.rb
81
81
  - lib/temporalio/api/deployment/v1/message.rb
82
+ - lib/temporalio/api/enums/v1/activity.rb
82
83
  - lib/temporalio/api/enums/v1/batch_operation.rb
83
84
  - lib/temporalio/api/enums/v1/command_type.rb
84
85
  - lib/temporalio/api/enums/v1/common.rb
@@ -135,6 +136,7 @@ files:
135
136
  - lib/temporalio/client/connection/test_service.rb
136
137
  - lib/temporalio/client/connection/workflow_service.rb
137
138
  - lib/temporalio/client/interceptor.rb
139
+ - lib/temporalio/client/plugin.rb
138
140
  - lib/temporalio/client/schedule.rb
139
141
  - lib/temporalio/client/schedule_handle.rb
140
142
  - lib/temporalio/client/with_start_workflow_operation.rb
@@ -195,6 +197,8 @@ files:
195
197
  - lib/temporalio/internal/worker/workflow_instance/handler_hash.rb
196
198
  - lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb
197
199
  - lib/temporalio/internal/worker/workflow_instance/inbound_implementation.rb
200
+ - lib/temporalio/internal/worker/workflow_instance/nexus_client.rb
201
+ - lib/temporalio/internal/worker/workflow_instance/nexus_operation_handle.rb
198
202
  - lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb
199
203
  - lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb
200
204
  - lib/temporalio/internal/worker/workflow_instance/replay_safe_metric.rb
@@ -207,6 +211,7 @@ files:
207
211
  - lib/temporalio/runtime/metric_buffer.rb
208
212
  - lib/temporalio/scoped_logger.rb
209
213
  - lib/temporalio/search_attributes.rb
214
+ - lib/temporalio/simple_plugin.rb
210
215
  - lib/temporalio/testing.rb
211
216
  - lib/temporalio/testing/activity_environment.rb
212
217
  - lib/temporalio/testing/workflow_environment.rb
@@ -219,6 +224,7 @@ files:
219
224
  - lib/temporalio/worker/deployment_options.rb
220
225
  - lib/temporalio/worker/illegal_workflow_call_validator.rb
221
226
  - lib/temporalio/worker/interceptor.rb
227
+ - lib/temporalio/worker/plugin.rb
222
228
  - lib/temporalio/worker/poller_behavior.rb
223
229
  - lib/temporalio/worker/thread_pool.rb
224
230
  - lib/temporalio/worker/tuner.rb
@@ -235,6 +241,9 @@ files:
235
241
  - lib/temporalio/workflow/future.rb
236
242
  - lib/temporalio/workflow/handler_unfinished_policy.rb
237
243
  - lib/temporalio/workflow/info.rb
244
+ - lib/temporalio/workflow/nexus_client.rb
245
+ - lib/temporalio/workflow/nexus_operation_cancellation_type.rb
246
+ - lib/temporalio/workflow/nexus_operation_handle.rb
238
247
  - lib/temporalio/workflow/parent_close_policy.rb
239
248
  - lib/temporalio/workflow/update_info.rb
240
249
  - lib/temporalio/workflow_history.rb
@@ -253,14 +262,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
253
262
  requirements:
254
263
  - - ">="
255
264
  - !ruby/object:Gem::Version
256
- version: 3.2.0
265
+ version: 3.3.0
257
266
  required_rubygems_version: !ruby/object:Gem::Requirement
258
267
  requirements:
259
268
  - - ">="
260
269
  - !ruby/object:Gem::Version
261
270
  version: '0'
262
271
  requirements: []
263
- rubygems_version: 3.6.9
272
+ rubygems_version: 4.0.3
264
273
  specification_version: 4
265
274
  summary: Temporal.io Ruby SDK
266
275
  test_files: []