temporalio 0.2.0-x86_64-linux → 0.4.0-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/Gemfile +27 -0
  4. data/Rakefile +101 -0
  5. data/lib/temporalio/activity/complete_async_error.rb +1 -1
  6. data/lib/temporalio/activity/context.rb +18 -2
  7. data/lib/temporalio/activity/definition.rb +180 -65
  8. data/lib/temporalio/activity/info.rb +25 -21
  9. data/lib/temporalio/activity.rb +2 -59
  10. data/lib/temporalio/api/activity/v1/message.rb +25 -0
  11. data/lib/temporalio/api/batch/v1/message.rb +6 -1
  12. data/lib/temporalio/api/cloud/account/v1/message.rb +28 -0
  13. data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +34 -1
  14. data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +1 -1
  15. data/lib/temporalio/api/cloud/identity/v1/message.rb +6 -1
  16. data/lib/temporalio/api/cloud/namespace/v1/message.rb +8 -1
  17. data/lib/temporalio/api/cloud/nexus/v1/message.rb +31 -0
  18. data/lib/temporalio/api/cloud/operation/v1/message.rb +2 -1
  19. data/lib/temporalio/api/cloud/region/v1/message.rb +2 -1
  20. data/lib/temporalio/api/cloud/resource/v1/message.rb +23 -0
  21. data/lib/temporalio/api/cloud/sink/v1/message.rb +24 -0
  22. data/lib/temporalio/api/cloud/usage/v1/message.rb +31 -0
  23. data/lib/temporalio/api/command/v1/message.rb +1 -1
  24. data/lib/temporalio/api/common/v1/message.rb +8 -1
  25. data/lib/temporalio/api/deployment/v1/message.rb +38 -0
  26. data/lib/temporalio/api/enums/v1/batch_operation.rb +1 -1
  27. data/lib/temporalio/api/enums/v1/common.rb +1 -1
  28. data/lib/temporalio/api/enums/v1/deployment.rb +23 -0
  29. data/lib/temporalio/api/enums/v1/event_type.rb +1 -1
  30. data/lib/temporalio/api/enums/v1/failed_cause.rb +1 -1
  31. data/lib/temporalio/api/enums/v1/nexus.rb +21 -0
  32. data/lib/temporalio/api/enums/v1/reset.rb +1 -1
  33. data/lib/temporalio/api/enums/v1/workflow.rb +2 -1
  34. data/lib/temporalio/api/errordetails/v1/message.rb +3 -1
  35. data/lib/temporalio/api/failure/v1/message.rb +3 -1
  36. data/lib/temporalio/api/history/v1/message.rb +3 -1
  37. data/lib/temporalio/api/nexus/v1/message.rb +3 -2
  38. data/lib/temporalio/api/operatorservice/v1/service.rb +1 -1
  39. data/lib/temporalio/api/payload_visitor.rb +1581 -0
  40. data/lib/temporalio/api/query/v1/message.rb +2 -1
  41. data/lib/temporalio/api/schedule/v1/message.rb +2 -1
  42. data/lib/temporalio/api/taskqueue/v1/message.rb +4 -1
  43. data/lib/temporalio/api/testservice/v1/request_response.rb +31 -0
  44. data/lib/temporalio/api/testservice/v1/service.rb +23 -0
  45. data/lib/temporalio/api/workflow/v1/message.rb +9 -1
  46. data/lib/temporalio/api/workflowservice/v1/request_response.rb +46 -2
  47. data/lib/temporalio/api/workflowservice/v1/service.rb +1 -1
  48. data/lib/temporalio/api.rb +2 -0
  49. data/lib/temporalio/cancellation.rb +34 -14
  50. data/lib/temporalio/client/async_activity_handle.rb +12 -37
  51. data/lib/temporalio/client/connection/cloud_service.rb +309 -231
  52. data/lib/temporalio/client/connection/operator_service.rb +36 -84
  53. data/lib/temporalio/client/connection/service.rb +6 -5
  54. data/lib/temporalio/client/connection/test_service.rb +111 -0
  55. data/lib/temporalio/client/connection/workflow_service.rb +474 -441
  56. data/lib/temporalio/client/connection.rb +90 -44
  57. data/lib/temporalio/client/interceptor.rb +199 -60
  58. data/lib/temporalio/client/schedule.rb +991 -0
  59. data/lib/temporalio/client/schedule_handle.rb +126 -0
  60. data/lib/temporalio/client/with_start_workflow_operation.rb +115 -0
  61. data/lib/temporalio/client/workflow_execution.rb +26 -10
  62. data/lib/temporalio/client/workflow_handle.rb +41 -98
  63. data/lib/temporalio/client/workflow_update_handle.rb +3 -5
  64. data/lib/temporalio/client.rb +247 -44
  65. data/lib/temporalio/common_enums.rb +17 -0
  66. data/lib/temporalio/contrib/open_telemetry.rb +470 -0
  67. data/lib/temporalio/converters/data_converter.rb +4 -7
  68. data/lib/temporalio/converters/failure_converter.rb +5 -3
  69. data/lib/temporalio/converters/payload_converter/composite.rb +4 -0
  70. data/lib/temporalio/converters/payload_converter.rb +6 -8
  71. data/lib/temporalio/converters/raw_value.rb +20 -0
  72. data/lib/temporalio/error/failure.rb +1 -1
  73. data/lib/temporalio/error.rb +11 -2
  74. data/lib/temporalio/internal/bridge/3.2/temporalio_bridge.so +0 -0
  75. data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.so +0 -0
  76. data/lib/temporalio/internal/bridge/{3.1 → 3.4}/temporalio_bridge.so +0 -0
  77. data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +1 -1
  78. data/lib/temporalio/internal/bridge/api/common/common.rb +2 -1
  79. data/lib/temporalio/internal/bridge/api/core_interface.rb +5 -1
  80. data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +33 -0
  81. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +5 -1
  82. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +4 -1
  83. data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +2 -1
  84. data/lib/temporalio/internal/bridge/client.rb +11 -6
  85. data/lib/temporalio/internal/bridge/runtime.rb +3 -0
  86. data/lib/temporalio/internal/bridge/testing.rb +23 -0
  87. data/lib/temporalio/internal/bridge/worker.rb +2 -0
  88. data/lib/temporalio/internal/bridge.rb +1 -1
  89. data/lib/temporalio/internal/client/implementation.rb +468 -71
  90. data/lib/temporalio/internal/metric.rb +122 -0
  91. data/lib/temporalio/internal/proto_utils.rb +118 -7
  92. data/lib/temporalio/internal/worker/activity_worker.rb +69 -29
  93. data/lib/temporalio/internal/worker/multi_runner.rb +53 -9
  94. data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +54 -0
  95. data/lib/temporalio/internal/worker/workflow_instance/context.rb +383 -0
  96. data/lib/temporalio/internal/worker/workflow_instance/details.rb +46 -0
  97. data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +32 -0
  98. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +22 -0
  99. data/lib/temporalio/internal/worker/workflow_instance/handler_execution.rb +25 -0
  100. data/lib/temporalio/internal/worker/workflow_instance/handler_hash.rb +41 -0
  101. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +97 -0
  102. data/lib/temporalio/internal/worker/workflow_instance/inbound_implementation.rb +62 -0
  103. data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +400 -0
  104. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +37 -0
  105. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_metric.rb +40 -0
  106. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +183 -0
  107. data/lib/temporalio/internal/worker/workflow_instance.rb +774 -0
  108. data/lib/temporalio/internal/worker/workflow_worker.rb +239 -0
  109. data/lib/temporalio/metric.rb +109 -0
  110. data/lib/temporalio/retry_policy.rb +37 -14
  111. data/lib/temporalio/runtime/metric_buffer.rb +94 -0
  112. data/lib/temporalio/runtime.rb +160 -79
  113. data/lib/temporalio/search_attributes.rb +93 -37
  114. data/lib/temporalio/testing/activity_environment.rb +44 -16
  115. data/lib/temporalio/testing/workflow_environment.rb +276 -7
  116. data/lib/temporalio/version.rb +1 -1
  117. data/lib/temporalio/worker/activity_executor/thread_pool.rb +9 -217
  118. data/lib/temporalio/worker/activity_executor.rb +3 -3
  119. data/lib/temporalio/worker/interceptor.rb +343 -66
  120. data/lib/temporalio/worker/thread_pool.rb +237 -0
  121. data/lib/temporalio/worker/tuner.rb +38 -0
  122. data/lib/temporalio/worker/workflow_executor/thread_pool.rb +235 -0
  123. data/lib/temporalio/worker/workflow_executor.rb +26 -0
  124. data/lib/temporalio/worker/workflow_replayer.rb +350 -0
  125. data/lib/temporalio/worker.rb +235 -58
  126. data/lib/temporalio/workflow/activity_cancellation_type.rb +20 -0
  127. data/lib/temporalio/workflow/child_workflow_cancellation_type.rb +21 -0
  128. data/lib/temporalio/workflow/child_workflow_handle.rb +43 -0
  129. data/lib/temporalio/workflow/definition.rb +598 -0
  130. data/lib/temporalio/workflow/external_workflow_handle.rb +41 -0
  131. data/lib/temporalio/workflow/future.rb +151 -0
  132. data/lib/temporalio/workflow/handler_unfinished_policy.rb +13 -0
  133. data/lib/temporalio/workflow/info.rb +104 -0
  134. data/lib/temporalio/workflow/parent_close_policy.rb +19 -0
  135. data/lib/temporalio/workflow/update_info.rb +20 -0
  136. data/lib/temporalio/workflow.rb +575 -0
  137. data/lib/temporalio/workflow_history.rb +26 -1
  138. data/lib/temporalio.rb +4 -0
  139. data/temporalio.gemspec +4 -3
  140. metadata +77 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8877081295dc68cb265909db90c8fee95237dd16fa4166c6ee93acbf8351382
4
- data.tar.gz: 45d18b6fce606c6890c078436933fc35062e114160a52db41d8e70d71a2e0f46
3
+ metadata.gz: afb9c2d7688901ad1860ad3b5ed99b500a00b57009383cf0e33339ef87bee34c
4
+ data.tar.gz: 58d4ae50ac869600d694812f92b51eae4ad26791d86e606d3d99e1e803531b8a
5
5
  SHA512:
6
- metadata.gz: 0df865f90b92080f31577f0bc33f442a7d00226ab9fe8b73d94d20f32feb936aa9b9ef4bbaa870beb0763fa95f82a739dc8f5dbf8026acb3df622312752ebef5
7
- data.tar.gz: 851306b1152377ea05d3ae380f90949e58943dd15703a17ba16d5b2e8b2e12f4953e9d89d535ab6b2f1180947b61a8d86a4ee93dd5ebb5b04e233075cbd48706
6
+ metadata.gz: 6f74af200ca5ff5c770804a74c5207ee960694749c2a9ec69cccf4c94478cff717f557cdce63eef8b460290929a2d5848740b80d33dba77a5821fb7e81083cc2
7
+ data.tar.gz: bbca6375df8d2a64a64bdc487d45bfefc6176dab73f81271383481d6a7958009fc65e4c8a63aadebff3afbce421f74ae1175b56e0e1c7dc98eaf518ca96f62ff
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --readme README.md
2
+ --protected
data/Gemfile ADDED
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :development do
8
+ gem 'activemodel'
9
+ gem 'activerecord'
10
+ gem 'async'
11
+ gem 'base64'
12
+ gem 'grpc', '~> 1.69'
13
+ gem 'grpc-tools', '~> 1.69'
14
+ gem 'minitest'
15
+ # We are intentionally not pinning OTel versions here so that CI tests the latest. This also means that the OTel
16
+ # contrib library also does not require specific versions, we are relying on the compatibility rigor of OTel.
17
+ gem 'opentelemetry-api'
18
+ gem 'opentelemetry-sdk'
19
+ gem 'rake'
20
+ gem 'rake-compiler'
21
+ gem 'rbs', '~> 3.5.3'
22
+ gem 'rb_sys', '~> 0.9.63'
23
+ gem 'rubocop'
24
+ gem 'sqlite3'
25
+ gem 'steep', '~> 1.7.1'
26
+ gem 'yard'
27
+ end
data/Rakefile ADDED
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Lint/MissingCopEnableDirective, Style/DocumentationMethod
4
+
5
+ require 'bundler/gem_tasks'
6
+ require 'rb_sys/cargo/metadata'
7
+ require 'rb_sys/extensiontask'
8
+
9
+ task build: :compile
10
+
11
+ GEMSPEC = Gem::Specification.load('temporalio.gemspec')
12
+
13
+ begin
14
+ RbSys::ExtensionTask.new('temporalio_bridge', GEMSPEC) do |ext|
15
+ ext.lib_dir = 'lib/temporalio/internal/bridge'
16
+ end
17
+ rescue RbSys::CargoMetadataError
18
+ raise 'Source gem cannot be installed directly, must be a supported platform'
19
+ end
20
+
21
+ require 'rake/testtask'
22
+
23
+ Rake::TestTask.new(:test) do |t|
24
+ t.warning = false
25
+ t.libs << 'test'
26
+ t.libs << 'lib'
27
+ t.test_files = FileList['test/**/*_test.rb']
28
+ end
29
+
30
+ def add_protoc_to_path
31
+ tools_spec = Gem::Specification.find_by_name('grpc-tools')
32
+ cpu = RbConfig::CONFIG['host_cpu']
33
+ cpu = 'x86_64' if cpu == 'x64'
34
+ os = RbConfig::CONFIG['host_os']
35
+ os = 'windows' if os.start_with?('mingw')
36
+ protoc_path = "#{tools_spec.gem_dir}/bin/#{cpu}-#{os}"
37
+ separator = os == 'windows' ? ';' : ':'
38
+ ENV['PATH'] = "#{ENV.fetch('PATH', nil)}#{separator}#{protoc_path}"
39
+ end
40
+
41
+ add_protoc_to_path
42
+
43
+ require 'rubocop/rake_task'
44
+
45
+ RuboCop::RakeTask.new
46
+
47
+ require 'steep/rake_task'
48
+
49
+ Steep::RakeTask.new
50
+
51
+ require 'yard'
52
+
53
+ module CustomizeYardWarnings # rubocop:disable Style/Documentation
54
+ def process
55
+ super
56
+ rescue YARD::Parser::UndocumentableError
57
+ # We ignore if it's an API warning
58
+ last_file = statement.last.file
59
+ raise unless (last_file.start_with?('lib/temporalio/api/') && last_file.count('/') > 3) ||
60
+ last_file.start_with?('lib/temporalio/internal/bridge/api/')
61
+ end
62
+ end
63
+
64
+ YARD::Handlers::Ruby::ConstantHandler.prepend(CustomizeYardWarnings)
65
+
66
+ YARD::Rake::YardocTask.new { |t| t.options = ['--fail-on-warning'] }
67
+
68
+ Rake::Task[:yard].enhance([:copy_parent_files]) do
69
+ rm ['LICENSE', 'README.md']
70
+ end
71
+
72
+ namespace :proto do
73
+ desc 'Generate API and Core protobufs'
74
+ task :generate do
75
+ require_relative 'extra/proto_gen'
76
+ ProtoGen.new.run
77
+ end
78
+ end
79
+
80
+ namespace :rbs do
81
+ desc 'RBS tasks'
82
+ task :install_collection do
83
+ sh 'rbs collection install'
84
+ end
85
+ end
86
+
87
+ # We have to copy some parent files to this dir for gem
88
+ task :copy_parent_files do
89
+ cp '../LICENSE', 'LICENSE'
90
+ cp '../README.md', 'README.md'
91
+ end
92
+ Rake::Task[:build].enhance([:copy_parent_files]) do
93
+ rm ['LICENSE', 'README.md']
94
+ end
95
+
96
+ task :rust_lint do
97
+ sh 'cargo', 'clippy', '-p', 'temporalio_bridge', '--no-deps', '--', '-Dwarnings'
98
+ sh 'cargo', 'fmt', '--check'
99
+ end
100
+
101
+ task default: ['rubocop', 'yard', 'rbs:install_collection', 'steep', 'rust_lint', 'compile', 'test']
@@ -3,7 +3,7 @@
3
3
  require 'temporalio/error'
4
4
 
5
5
  module Temporalio
6
- class Activity
6
+ module Activity
7
7
  # Error raised inside an activity to mark that the activity will be completed asynchronously.
8
8
  class CompleteAsyncError < Error
9
9
  end
@@ -3,7 +3,7 @@
3
3
  require 'temporalio/error'
4
4
 
5
5
  module Temporalio
6
- class Activity
6
+ module Activity
7
7
  # Context accessible only within an activity. Use {current} to get the current context. Contexts are fiber or thread
8
8
  # local so may not be available in a newly started thread from an activity and may have to be propagated manually.
9
9
  class Context
@@ -48,6 +48,12 @@ module Temporalio
48
48
  raise NotImplementedError
49
49
  end
50
50
 
51
+ # @return [Object, nil] Activity class instance. This should always be present except for advanced cases where the
52
+ # definition was manually created without any instance getter/creator.
53
+ def instance
54
+ raise NotImplementedError
55
+ end
56
+
51
57
  # Record a heartbeat on the activity.
52
58
  #
53
59
  # Heartbeats should be used for all non-immediately-returning, non-local activities and they are required to
@@ -101,7 +107,17 @@ module Temporalio
101
107
  }.freeze
102
108
  end
103
109
 
104
- # TODO(cretz): metric meter
110
+ # @return [Metric::Meter] Metric meter to create metrics on, with some activity-specific attributes already set.
111
+ # @raise [RuntimeError] Called within a {Testing::ActivityEnvironment} and it was not set.
112
+ def metric_meter
113
+ raise NotImplementedError
114
+ end
115
+
116
+ # @return [Client] Temporal client this activity worker is running in.
117
+ # @raise [RuntimeError] Called within a {Testing::ActivityEnvironment} and it was not set.
118
+ def client
119
+ raise NotImplementedError
120
+ end
105
121
  end
106
122
  end
107
123
  end
@@ -1,76 +1,191 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'temporalio/internal/proto_utils'
4
+
3
5
  module Temporalio
4
- class Activity
5
- # Definition of an activity. Activities are usually classes/instances that extend {Activity}, but definitions can
6
- # also be manually created with a proc/block.
6
+ module Activity
7
+ # Base class for all activities.
8
+ #
9
+ # Activities can be given to a worker as instances of this class, which will call execute on the same instance for
10
+ # each execution, or given to the worker as the class itself which instantiates the activity for each execution.
11
+ #
12
+ # All activities must implement {execute}. Inside execute, {Activity::Context.current} can be used to access the
13
+ # current context to get information, issue heartbeats, etc.
14
+ #
15
+ # By default, the activity is named as its unqualified class name. This can be customized with {activity_name}.
16
+ #
17
+ # By default, the activity uses the `:default` executor which is usually the thread-pool based executor. This can be
18
+ # customized with {activity_executor}.
19
+ #
20
+ # By default, upon cancellation {::Thread.raise} or {::Fiber.raise} is called with a {Error::CanceledError}. This
21
+ # can be disabled by passing `false` to {activity_cancel_raise}.
22
+ #
23
+ # See documentation for more detail on activities.
7
24
  class Definition
8
- # @return [String, Symbol] Name of the activity.
9
- attr_reader :name
10
-
11
- # @return [Proc] Proc for the activity.
12
- attr_reader :proc
13
-
14
- # @return [Symbol] Name of the executor. Default is `:default`.
15
- attr_reader :executor
16
-
17
- # @return [Boolean] Whether to raise in thread/fiber on cancellation. Default is `true`.
18
- attr_reader :cancel_raise
19
-
20
- # Obtain a definition representing the given activity, which can be a class, instance, or definition.
21
- #
22
- # @param activity [Activity, Class<Activity>, Definition] Activity to get definition for.
23
- # @return Definition Obtained definition.
24
- def self.from_activity(activity)
25
- # Class means create each time, instance means just call, definition
26
- # does nothing special
27
- case activity
28
- when Class
29
- raise ArgumentError, "Class '#{activity}' does not extend Activity" unless activity < Activity
30
-
31
- details = activity._activity_definition_details
32
- new(
33
- name: details[:activity_name],
34
- executor: details[:activity_executor],
35
- cancel_raise: details[:activity_cancel_raise],
36
- # Instantiate and call
37
- proc: proc { |*args| activity.new.execute(*args) }
38
- )
39
- when Activity
40
- details = activity.class._activity_definition_details
41
- new(
42
- name: details[:activity_name],
43
- executor: details[:activity_executor],
44
- cancel_raise: details[:activity_cancel_raise],
45
- # Just call
46
- proc: proc { |*args| activity.execute(*args) }
47
- )
48
- when Activity::Definition
49
- activity
50
- else
51
- raise ArgumentError, "#{activity} is not an activity class, instance, or definition"
25
+ class << self
26
+ protected
27
+
28
+ # Override the activity name which is defaulted to the unqualified class name.
29
+ #
30
+ # @param name [String, Symbol] Name to use.
31
+ def activity_name(name)
32
+ if !name.is_a?(Symbol) && !name.is_a?(String)
33
+ raise ArgumentError,
34
+ 'Activity name must be a symbol or string'
35
+ end
36
+
37
+ @activity_name = name.to_s
38
+ end
39
+
40
+ # Override the activity executor which is defaulted to `:default`.
41
+ #
42
+ # @param executor_name [Symbol] Executor to use.
43
+ def activity_executor(executor_name)
44
+ raise ArgumentError, 'Executor name must be a symbol' unless executor_name.is_a?(Symbol)
45
+
46
+ @activity_executor = executor_name
47
+ end
48
+
49
+ # Override whether the activity uses Thread/Fiber raise for cancellation which is defaulted to true.
50
+ #
51
+ # @param cancel_raise [Boolean] Whether to raise.
52
+ def activity_cancel_raise(cancel_raise)
53
+ unless cancel_raise.is_a?(TrueClass) || cancel_raise.is_a?(FalseClass)
54
+ raise ArgumentError, 'Must be a boolean'
55
+ end
56
+
57
+ @activity_cancel_raise = cancel_raise
58
+ end
59
+
60
+ # Set an activity as dynamic. Dynamic activities do not have names and handle any activity that is not otherwise
61
+ # registered. A worker can only have one dynamic activity. It is often useful to use {activity_raw_args} with
62
+ # this.
63
+ #
64
+ # @param value [Boolean] Whether the activity is dynamic.
65
+ def activity_dynamic(value = true) # rubocop:disable Style/OptionalBooleanParameter
66
+ raise ArgumentError, 'Must be a boolean' unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
67
+
68
+ @activity_dynamic = value
69
+ end
70
+
71
+ # Have activity arguments delivered to `execute` as {Converters::RawValue}s. These are wrappers for the raw
72
+ # payloads that have not been converted to types (but they have been decoded by the codec if present). They can
73
+ # be converted with {Context#payload_converter}.
74
+ #
75
+ # @param value [Boolean] Whether the activity accepts raw arguments.
76
+ def activity_raw_args(value = true) # rubocop:disable Style/OptionalBooleanParameter
77
+ raise ArgumentError, 'Must be a boolean' unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
78
+
79
+ @activity_raw_args = value
52
80
  end
53
81
  end
54
82
 
55
- # Manually create activity definition. Most users will use an instance/class of {Activity}.
56
- #
57
- # @param name [String, Symbol] Name of the activity.
58
- # @param proc [Proc, nil] Proc for the activity, or can give block.
59
- # @param executor [Symbol] Name of the executor.
60
- # @param cancel_raise [Boolean] Whether to raise in thread/fiber on cancellation.
61
- # @yield Use this block as the activity. Cannot be present with `proc`.
62
- def initialize(name:, proc: nil, executor: :default, cancel_raise: true, &block)
63
- @name = name
64
- if proc.nil?
65
- raise ArgumentError, 'Must give proc or block' unless block_given?
66
-
67
- proc = block
68
- elsif block_given?
69
- raise ArgumentError, 'Cannot give proc and block'
83
+ # @!visibility private
84
+ def self._activity_definition_details
85
+ activity_name = @activity_name
86
+ raise 'Cannot have activity name specified for dynamic activity' if activity_name && @activity_dynamic
87
+
88
+ # Default to unqualified class name if not dynamic
89
+ activity_name ||= name.to_s.split('::').last unless @activity_dynamic
90
+ {
91
+ activity_name:,
92
+ activity_executor: @activity_executor || :default,
93
+ activity_cancel_raise: @activity_cancel_raise.nil? || @activity_cancel_raise,
94
+ activity_raw_args: @activity_raw_args.nil? ? false : @activity_raw_args
95
+ }
96
+ end
97
+
98
+ # Implementation of the activity. The arguments should be positional and this should return the value on success
99
+ # or raise an error on failure.
100
+ def execute(*args)
101
+ raise NotImplementedError, 'Activity did not implement "execute"'
102
+ end
103
+
104
+ # Definition info of an activity. Activities are usually classes/instances that extend {Definition}, but
105
+ # definitions can also be manually created with a block via {initialize} here.
106
+ class Info
107
+ # @return [String, Symbol, nil] Name of the activity, or nil if the activity is dynamic.
108
+ attr_reader :name
109
+
110
+ # @return [Object, Proc, nil] The pre-created instance or the proc to create/return it.
111
+ attr_reader :instance
112
+
113
+ # @return [Proc] Proc for the activity. Should use {Context#instance} to access the instance.
114
+ attr_reader :proc
115
+
116
+ # @return [Symbol] Name of the executor. Default is `:default`.
117
+ attr_reader :executor
118
+
119
+ # @return [Boolean] Whether to raise in thread/fiber on cancellation. Default is `true`.
120
+ attr_reader :cancel_raise
121
+
122
+ # @return [Boolean] Whether to use {Converters::RawValue}s as arguments.
123
+ attr_reader :raw_args
124
+
125
+ # Obtain definition info representing the given activity, which can be a class, instance, or definition info.
126
+ #
127
+ # @param activity [Definition, Class<Definition>, Info] Activity to get info for.
128
+ # @return Info Obtained definition info.
129
+ def self.from_activity(activity)
130
+ # Class means create each time, instance means just call, definition
131
+ # does nothing special
132
+ case activity
133
+ when Class
134
+ unless activity < Definition
135
+ raise ArgumentError,
136
+ "Class '#{activity}' does not extend Temporalio::Activity::Definition"
137
+ end
138
+
139
+ details = activity._activity_definition_details
140
+ new(
141
+ name: details[:activity_name],
142
+ instance: proc { activity.new },
143
+ executor: details[:activity_executor],
144
+ cancel_raise: details[:activity_cancel_raise],
145
+ raw_args: details[:activity_raw_args]
146
+ ) { |*args| Context.current.instance&.execute(*args) }
147
+ when Definition
148
+ details = activity.class._activity_definition_details
149
+ new(
150
+ name: details[:activity_name],
151
+ instance: activity,
152
+ executor: details[:activity_executor],
153
+ cancel_raise: details[:activity_cancel_raise],
154
+ raw_args: details[:activity_raw_args]
155
+ ) { |*args| Context.current.instance&.execute(*args) }
156
+ when Info
157
+ activity
158
+ else
159
+ raise ArgumentError, "#{activity} is not an activity class, instance, or definition info"
160
+ end
161
+ end
162
+
163
+ # Manually create activity definition info. Most users will use an instance/class of {Definition}.
164
+ #
165
+ # @param name [String, Symbol, nil] Name of the activity or nil for dynamic activity.
166
+ # @param instance [Object, Proc, nil] The pre-created instance or the proc to create/return it.
167
+ # @param executor [Symbol] Name of the executor.
168
+ # @param cancel_raise [Boolean] Whether to raise in thread/fiber on cancellation.
169
+ # @param raw_args [Boolean] Whether to use {Converters::RawValue}s as arguments.
170
+ # @yield Use this block as the activity.
171
+ def initialize(
172
+ name:,
173
+ instance: nil,
174
+ executor: :default,
175
+ cancel_raise: true,
176
+ raw_args: false,
177
+ &block
178
+ )
179
+ @name = name
180
+ @instance = instance
181
+ raise ArgumentError, 'Must give block' unless block_given?
182
+
183
+ @proc = block
184
+ @executor = executor
185
+ @cancel_raise = cancel_raise
186
+ @raw_args = raw_args
187
+ Internal::ProtoUtils.assert_non_reserved_name(name)
70
188
  end
71
- @proc = proc
72
- @executor = executor
73
- @cancel_raise = cancel_raise
74
189
  end
75
190
  end
76
191
  end
@@ -1,7 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Temporalio
4
- class Activity
4
+ module Activity
5
+ Info = Data.define(
6
+ :activity_id,
7
+ :activity_type,
8
+ :attempt,
9
+ :current_attempt_scheduled_time,
10
+ :heartbeat_details,
11
+ :heartbeat_timeout,
12
+ :local?,
13
+ :schedule_to_close_timeout,
14
+ :scheduled_time,
15
+ :start_to_close_timeout,
16
+ :started_time,
17
+ :task_queue,
18
+ :task_token,
19
+ :workflow_id,
20
+ :workflow_namespace,
21
+ :workflow_run_id,
22
+ :workflow_type
23
+ )
24
+
5
25
  # Information about an activity.
6
26
  #
7
27
  # @!attribute activity_id
@@ -39,25 +59,9 @@ module Temporalio
39
59
  # @return [String] Workflow run ID that started this activity.
40
60
  # @!attribute workflow_type
41
61
  # @return [String] Workflow type name that started this activity.
42
- Info = Struct.new(
43
- :activity_id,
44
- :activity_type,
45
- :attempt,
46
- :current_attempt_scheduled_time,
47
- :heartbeat_details,
48
- :heartbeat_timeout,
49
- :local?,
50
- :schedule_to_close_timeout,
51
- :scheduled_time,
52
- :start_to_close_timeout,
53
- :started_time,
54
- :task_queue,
55
- :task_token,
56
- :workflow_id,
57
- :workflow_namespace,
58
- :workflow_run_id,
59
- :workflow_type,
60
- keyword_init: true
61
- )
62
+ #
63
+ # @note WARNING: This class may have required parameters added to its constructor. Users should not instantiate this
64
+ # class or it may break in incompatible ways.
65
+ class Info; end # rubocop:disable Lint/EmptyClass
62
66
  end
63
67
  end
@@ -6,64 +6,7 @@ require 'temporalio/activity/definition'
6
6
  require 'temporalio/activity/info'
7
7
 
8
8
  module Temporalio
9
- # Base class for all activities.
10
- #
11
- # Activities can be given to a worker as instances of this class, which will call execute on the same instance for
12
- # each execution, or given to the worker as the class itself which instantiates the activity for each execution.
13
- #
14
- # All activities must implement {execute}. Inside execute, {Activity::Context.current} can be used to access the
15
- # current context to get information, issue heartbeats, etc.
16
- #
17
- # By default, the activity is named as its unqualified class name. This can be customized with {activity_name}.
18
- #
19
- # By default, the activity uses the `:default` executor which is usually the thread-pool based executor. This can be
20
- # customized with {activity_executor}.
21
- #
22
- # By default, upon cancellation {::Thread.raise} or {::Fiber.raise} is called with a {Error::CanceledError}. This can
23
- # be disabled by passing `false` to {activity_cancel_raise}.
24
- #
25
- # See documentation for more detail on activities.
26
- class Activity
27
- # Override the activity name which is defaulted to the unqualified class name.
28
- #
29
- # @param name [String, Symbol] Name to use.
30
- def self.activity_name(name)
31
- raise ArgumentError, 'Activity name must be a symbol or string' if !name.is_a?(Symbol) && !name.is_a?(String)
32
-
33
- @activity_name = name.to_s
34
- end
35
-
36
- # Override the activity executor which is defaulted to `:default`.
37
- #
38
- # @param executor_name [Symbol] Executor to use.
39
- def self.activity_executor(executor_name)
40
- raise ArgumentError, 'Executor name must be a symbol' unless executor_name.is_a?(Symbol)
41
-
42
- @activity_executor = executor_name
43
- end
44
-
45
- # Override whether the activity uses Thread/Fiber raise for cancellation which is defaulted to true.
46
- #
47
- # @param cancel_raise [Boolean] Whether to raise.
48
- def self.activity_cancel_raise(cancel_raise)
49
- raise ArgumentError, 'Must be a boolean' unless cancel_raise.is_a?(TrueClass) || cancel_raise.is_a?(FalseClass)
50
-
51
- @activity_cancel_raise = cancel_raise
52
- end
53
-
54
- # @!visibility private
55
- def self._activity_definition_details
56
- {
57
- activity_name: @activity_name || name.to_s.split('::').last,
58
- activity_executor: @activity_executor || :default,
59
- activity_cancel_raise: @activity_cancel_raise.nil? ? true : @activity_cancel_raise
60
- }
61
- end
62
-
63
- # Implementation of the activity. The arguments should be positional and this should return the value on success or
64
- # raise an error on failure.
65
- def execute(*args)
66
- raise NotImplementedError, 'Activity did not implement "execute"'
67
- end
9
+ # All activity related classes.
10
+ module Activity
68
11
  end
69
12
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: temporal/api/activity/v1/message.proto
4
+
5
+ require 'google/protobuf'
6
+
7
+ require 'temporalio/api/common/v1/message'
8
+ require 'temporalio/api/taskqueue/v1/message'
9
+ require 'google/protobuf/duration_pb'
10
+
11
+
12
+ descriptor_data = "\n&temporal/api/activity/v1/message.proto\x12\x18temporal.api.activity.v1\x1a$temporal/api/common/v1/message.proto\x1a\'temporal/api/taskqueue/v1/message.proto\x1a\x1egoogle/protobuf/duration.proto\"\xf3\x02\n\x0f\x41\x63tivityOptions\x12\x38\n\ntask_queue\x18\x01 \x01(\x0b\x32$.temporal.api.taskqueue.v1.TaskQueue\x12<\n\x19schedule_to_close_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x06 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicyB\x93\x01\n\x1bio.temporal.api.activity.v1B\x0cMessageProtoP\x01Z\'go.temporal.io/api/activity/v1;activity\xaa\x02\x1aTemporalio.Api.Activity.V1\xea\x02\x1dTemporalio::Api::Activity::V1b\x06proto3"
13
+
14
+ pool = Google::Protobuf::DescriptorPool.generated_pool
15
+ pool.add_serialized_file(descriptor_data)
16
+
17
+ module Temporalio
18
+ module Api
19
+ module Activity
20
+ module V1
21
+ ActivityOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.activity.v1.ActivityOptions").msgclass
22
+ end
23
+ end
24
+ end
25
+ end
@@ -4,13 +4,16 @@
4
4
 
5
5
  require 'google/protobuf'
6
6
 
7
+ require 'google/protobuf/duration_pb'
8
+ require 'google/protobuf/field_mask_pb'
7
9
  require 'google/protobuf/timestamp_pb'
8
10
  require 'temporalio/api/common/v1/message'
9
11
  require 'temporalio/api/enums/v1/batch_operation'
10
12
  require 'temporalio/api/enums/v1/reset'
13
+ require 'temporalio/api/workflow/v1/message'
11
14
 
12
15
 
13
- descriptor_data = "\n#temporal/api/batch/v1/message.proto\x12\x15temporal.api.batch.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a+temporal/api/enums/v1/batch_operation.proto\x1a!temporal/api/enums/v1/reset.proto\"\xbf\x01\n\x12\x42\x61tchOperationInfo\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\x39\n\x05state\x18\x02 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"`\n\x19\x42\x61tchOperationTermination\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x02 \x01(\t\"\x99\x01\n\x14\x42\x61tchOperationSignal\x12\x0e\n\x06signal\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x10\n\x08identity\x18\x04 \x01(\t\".\n\x1a\x42\x61tchOperationCancellation\x12\x10\n\x08identity\x18\x01 \x01(\t\"*\n\x16\x42\x61tchOperationDeletion\x12\x10\n\x08identity\x18\x01 \x01(\t\"\xd9\x01\n\x13\x42\x61tchOperationReset\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x35\n\x07options\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.ResetOptions\x12\x34\n\nreset_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.ResetType\x12\x43\n\x12reset_reapply_type\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyTypeB\x84\x01\n\x18io.temporal.api.batch.v1B\x0cMessageProtoP\x01Z!go.temporal.io/api/batch/v1;batch\xaa\x02\x17Temporalio.Api.Batch.V1\xea\x02\x1aTemporalio::Api::Batch::V1b\x06proto3"
16
+ descriptor_data = "\n#temporal/api/batch/v1/message.proto\x12\x15temporal.api.batch.v1\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a+temporal/api/enums/v1/batch_operation.proto\x1a!temporal/api/enums/v1/reset.proto\x1a&temporal/api/workflow/v1/message.proto\"\xbf\x01\n\x12\x42\x61tchOperationInfo\x12\x0e\n\x06job_id\x18\x01 \x01(\t\x12\x39\n\x05state\x18\x02 \x01(\x0e\x32*.temporal.api.enums.v1.BatchOperationState\x12.\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"`\n\x19\x42\x61tchOperationTermination\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x10\n\x08identity\x18\x02 \x01(\t\"\x99\x01\n\x14\x42\x61tchOperationSignal\x12\x0e\n\x06signal\x18\x01 \x01(\t\x12/\n\x05input\x18\x02 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12.\n\x06header\x18\x03 \x01(\x0b\x32\x1e.temporal.api.common.v1.Header\x12\x10\n\x08identity\x18\x04 \x01(\t\".\n\x1a\x42\x61tchOperationCancellation\x12\x10\n\x08identity\x18\x01 \x01(\t\"*\n\x16\x42\x61tchOperationDeletion\x12\x10\n\x08identity\x18\x01 \x01(\t\"\xd9\x01\n\x13\x42\x61tchOperationReset\x12\x10\n\x08identity\x18\x03 \x01(\t\x12\x35\n\x07options\x18\x04 \x01(\x0b\x32$.temporal.api.common.v1.ResetOptions\x12\x34\n\nreset_type\x18\x01 \x01(\x0e\x32 .temporal.api.enums.v1.ResetType\x12\x43\n\x12reset_reapply_type\x18\x02 \x01(\x0e\x32\'.temporal.api.enums.v1.ResetReapplyType\"\xc9\x01\n,BatchOperationUpdateWorkflowExecutionOptions\x12\x10\n\x08identity\x18\x01 \x01(\t\x12V\n\x1aworkflow_execution_options\x18\x02 \x01(\x0b\x32\x32.temporal.api.workflow.v1.WorkflowExecutionOptions\x12/\n\x0bupdate_mask\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"\xc0\x01\n\x1f\x42\x61tchOperationUnpauseActivities\x12\x10\n\x08identity\x18\x01 \x01(\t\x12\x0e\n\x04type\x18\x02 \x01(\tH\x00\x12\x13\n\tmatch_all\x18\x03 \x01(\x08H\x00\x12\x16\n\x0ereset_attempts\x18\x04 \x01(\x08\x12\x17\n\x0freset_heartbeat\x18\x05 \x01(\x08\x12)\n\x06jitter\x18\x06 \x01(\x0b\x32\x19.google.protobuf.DurationB\n\n\x08\x61\x63tivityB\x84\x01\n\x18io.temporal.api.batch.v1B\x0cMessageProtoP\x01Z!go.temporal.io/api/batch/v1;batch\xaa\x02\x17Temporalio.Api.Batch.V1\xea\x02\x1aTemporalio::Api::Batch::V1b\x06proto3"
14
17
 
15
18
  pool = Google::Protobuf::DescriptorPool.generated_pool
16
19
  pool.add_serialized_file(descriptor_data)
@@ -25,6 +28,8 @@ module Temporalio
25
28
  BatchOperationCancellation = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.batch.v1.BatchOperationCancellation").msgclass
26
29
  BatchOperationDeletion = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.batch.v1.BatchOperationDeletion").msgclass
27
30
  BatchOperationReset = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.batch.v1.BatchOperationReset").msgclass
31
+ BatchOperationUpdateWorkflowExecutionOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.batch.v1.BatchOperationUpdateWorkflowExecutionOptions").msgclass
32
+ BatchOperationUnpauseActivities = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.batch.v1.BatchOperationUnpauseActivities").msgclass
28
33
  end
29
34
  end
30
35
  end