temporalio 0.2.0-x86_64-darwin → 0.3.0-x86_64-darwin

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/Gemfile +3 -3
  4. data/Rakefile +10 -296
  5. data/lib/temporalio/activity/complete_async_error.rb +1 -1
  6. data/lib/temporalio/activity/context.rb +5 -2
  7. data/lib/temporalio/activity/definition.rb +163 -65
  8. data/lib/temporalio/activity/info.rb +22 -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/cloud/account/v1/message.rb +28 -0
  12. data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +34 -1
  13. data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +1 -1
  14. data/lib/temporalio/api/cloud/identity/v1/message.rb +6 -1
  15. data/lib/temporalio/api/cloud/namespace/v1/message.rb +8 -1
  16. data/lib/temporalio/api/cloud/nexus/v1/message.rb +31 -0
  17. data/lib/temporalio/api/cloud/operation/v1/message.rb +2 -1
  18. data/lib/temporalio/api/cloud/region/v1/message.rb +2 -1
  19. data/lib/temporalio/api/cloud/resource/v1/message.rb +23 -0
  20. data/lib/temporalio/api/cloud/sink/v1/message.rb +24 -0
  21. data/lib/temporalio/api/cloud/usage/v1/message.rb +31 -0
  22. data/lib/temporalio/api/common/v1/message.rb +7 -1
  23. data/lib/temporalio/api/enums/v1/event_type.rb +1 -1
  24. data/lib/temporalio/api/enums/v1/failed_cause.rb +1 -1
  25. data/lib/temporalio/api/enums/v1/reset.rb +1 -1
  26. data/lib/temporalio/api/history/v1/message.rb +1 -1
  27. data/lib/temporalio/api/nexus/v1/message.rb +2 -2
  28. data/lib/temporalio/api/operatorservice/v1/service.rb +1 -1
  29. data/lib/temporalio/api/payload_visitor.rb +1513 -0
  30. data/lib/temporalio/api/schedule/v1/message.rb +2 -1
  31. data/lib/temporalio/api/testservice/v1/request_response.rb +31 -0
  32. data/lib/temporalio/api/testservice/v1/service.rb +23 -0
  33. data/lib/temporalio/api/workflow/v1/message.rb +1 -1
  34. data/lib/temporalio/api/workflowservice/v1/request_response.rb +17 -2
  35. data/lib/temporalio/api/workflowservice/v1/service.rb +1 -1
  36. data/lib/temporalio/api.rb +1 -0
  37. data/lib/temporalio/cancellation.rb +34 -14
  38. data/lib/temporalio/client/async_activity_handle.rb +12 -37
  39. data/lib/temporalio/client/connection/cloud_service.rb +309 -231
  40. data/lib/temporalio/client/connection/operator_service.rb +36 -84
  41. data/lib/temporalio/client/connection/service.rb +6 -5
  42. data/lib/temporalio/client/connection/test_service.rb +111 -0
  43. data/lib/temporalio/client/connection/workflow_service.rb +264 -441
  44. data/lib/temporalio/client/connection.rb +90 -44
  45. data/lib/temporalio/client/interceptor.rb +160 -60
  46. data/lib/temporalio/client/schedule.rb +967 -0
  47. data/lib/temporalio/client/schedule_handle.rb +126 -0
  48. data/lib/temporalio/client/workflow_execution.rb +7 -10
  49. data/lib/temporalio/client/workflow_handle.rb +38 -95
  50. data/lib/temporalio/client/workflow_update_handle.rb +3 -5
  51. data/lib/temporalio/client.rb +122 -42
  52. data/lib/temporalio/common_enums.rb +17 -0
  53. data/lib/temporalio/converters/data_converter.rb +4 -7
  54. data/lib/temporalio/converters/failure_converter.rb +5 -3
  55. data/lib/temporalio/converters/payload_converter/composite.rb +4 -0
  56. data/lib/temporalio/converters/payload_converter.rb +6 -8
  57. data/lib/temporalio/converters/raw_value.rb +20 -0
  58. data/lib/temporalio/error/failure.rb +1 -1
  59. data/lib/temporalio/error.rb +10 -2
  60. data/lib/temporalio/internal/bridge/3.2/temporalio_bridge.bundle +0 -0
  61. data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.bundle +0 -0
  62. data/lib/temporalio/internal/bridge/{3.1 → 3.4}/temporalio_bridge.bundle +0 -0
  63. data/lib/temporalio/internal/bridge/api/core_interface.rb +5 -1
  64. data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +33 -0
  65. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +5 -1
  66. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +4 -1
  67. data/lib/temporalio/internal/bridge/client.rb +11 -6
  68. data/lib/temporalio/internal/bridge/testing.rb +20 -0
  69. data/lib/temporalio/internal/bridge/worker.rb +2 -0
  70. data/lib/temporalio/internal/bridge.rb +1 -1
  71. data/lib/temporalio/internal/client/implementation.rb +245 -70
  72. data/lib/temporalio/internal/metric.rb +122 -0
  73. data/lib/temporalio/internal/proto_utils.rb +86 -7
  74. data/lib/temporalio/internal/worker/activity_worker.rb +52 -24
  75. data/lib/temporalio/internal/worker/multi_runner.rb +51 -7
  76. data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +54 -0
  77. data/lib/temporalio/internal/worker/workflow_instance/context.rb +329 -0
  78. data/lib/temporalio/internal/worker/workflow_instance/details.rb +44 -0
  79. data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +32 -0
  80. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +22 -0
  81. data/lib/temporalio/internal/worker/workflow_instance/handler_execution.rb +25 -0
  82. data/lib/temporalio/internal/worker/workflow_instance/handler_hash.rb +41 -0
  83. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +97 -0
  84. data/lib/temporalio/internal/worker/workflow_instance/inbound_implementation.rb +62 -0
  85. data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +415 -0
  86. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +37 -0
  87. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_metric.rb +40 -0
  88. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +163 -0
  89. data/lib/temporalio/internal/worker/workflow_instance.rb +730 -0
  90. data/lib/temporalio/internal/worker/workflow_worker.rb +196 -0
  91. data/lib/temporalio/metric.rb +109 -0
  92. data/lib/temporalio/retry_policy.rb +37 -14
  93. data/lib/temporalio/runtime.rb +118 -75
  94. data/lib/temporalio/search_attributes.rb +80 -37
  95. data/lib/temporalio/testing/activity_environment.rb +2 -2
  96. data/lib/temporalio/testing/workflow_environment.rb +251 -5
  97. data/lib/temporalio/version.rb +1 -1
  98. data/lib/temporalio/worker/activity_executor/thread_pool.rb +9 -217
  99. data/lib/temporalio/worker/activity_executor.rb +3 -3
  100. data/lib/temporalio/worker/interceptor.rb +340 -66
  101. data/lib/temporalio/worker/thread_pool.rb +237 -0
  102. data/lib/temporalio/worker/workflow_executor/thread_pool.rb +230 -0
  103. data/lib/temporalio/worker/workflow_executor.rb +26 -0
  104. data/lib/temporalio/worker.rb +201 -30
  105. data/lib/temporalio/workflow/activity_cancellation_type.rb +20 -0
  106. data/lib/temporalio/workflow/child_workflow_cancellation_type.rb +21 -0
  107. data/lib/temporalio/workflow/child_workflow_handle.rb +43 -0
  108. data/lib/temporalio/workflow/definition.rb +566 -0
  109. data/lib/temporalio/workflow/external_workflow_handle.rb +41 -0
  110. data/lib/temporalio/workflow/future.rb +151 -0
  111. data/lib/temporalio/workflow/handler_unfinished_policy.rb +13 -0
  112. data/lib/temporalio/workflow/info.rb +82 -0
  113. data/lib/temporalio/workflow/parent_close_policy.rb +19 -0
  114. data/lib/temporalio/workflow/update_info.rb +20 -0
  115. data/lib/temporalio/workflow.rb +523 -0
  116. data/lib/temporalio.rb +4 -0
  117. data/temporalio.gemspec +2 -2
  118. metadata +52 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 209ea74a531b7d0259dc1708d459875aefeabf8cd514052dde31fdb5ed901072
4
- data.tar.gz: '038fc31c03ba9e3d2b542ebc863c7dc85b61a477f906b615562efde503764f4f'
3
+ metadata.gz: 5f1a81b07962fce3108e67dac19312a43ce54590e6a00061e5a5983531dc90cd
4
+ data.tar.gz: 866a6688886a62c0f860ec178ba7f39fed50a58bc17d5be8c4ac9924a20f43be
5
5
  SHA512:
6
- metadata.gz: 0cb8f9adf5d9f0b25680abfb31aa6d1c89f46cdeb9ab30abc805461528e55c72777b49b4c2102335913d877eb1231a6db6bea97a4329a595e8e7f3753ccb70d0
7
- data.tar.gz: 86a1a7a7df4391bacb975be3e42e48662c85a6fffd6e8114eeee79f02ac4638cc83be4bdb6778a7b29dcf21c64a310977f48a1e3fa308bdd8d73e392bd94d286
6
+ metadata.gz: da2a253fccdcdb0bb1433a53b3b45ad56c9e0887e54cf768d1327cf49e1f138aa48629aee47b2b48d48709454fd991734036b941aad1726167ad5cff6ede6645
7
+ data.tar.gz: 1fcef7be35d1a64b421f115fb503338f198a3d349cba0900409fbd0d5d7b86a20c67015ee3dd4bf983207bfc89bba6dee8a0de09366bbe81b84b4e61bf51fdc8
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --readme README.md
2
+ --protected
data/Gemfile CHANGED
@@ -9,15 +9,15 @@ group :development do
9
9
  gem 'activerecord'
10
10
  gem 'async'
11
11
  gem 'base64'
12
- gem 'grpc', '>= 1.65.0.pre2'
13
- gem 'grpc-tools'
12
+ gem 'grpc', '~> 1.69'
13
+ gem 'grpc-tools', '~> 1.69'
14
14
  gem 'minitest'
15
15
  gem 'rake'
16
16
  gem 'rake-compiler'
17
17
  gem 'rbs', '~> 3.5.3'
18
18
  gem 'rb_sys', '~> 0.9.63'
19
19
  gem 'rubocop'
20
- gem 'sqlite3', '~> 1.4'
20
+ gem 'sqlite3'
21
21
  gem 'steep', '~> 1.7.1'
22
22
  gem 'yard'
23
23
  end
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Metrics/BlockLength, Lint/MissingCopEnableDirective, Style/DocumentationMethod
3
+ # rubocop:disable Lint/MissingCopEnableDirective, Style/DocumentationMethod
4
4
 
5
5
  require 'bundler/gem_tasks'
6
6
  require 'rb_sys/cargo/metadata'
@@ -55,8 +55,9 @@ module CustomizeYardWarnings # rubocop:disable Style/Documentation
55
55
  super
56
56
  rescue YARD::Parser::UndocumentableError
57
57
  # We ignore if it's an API warning
58
- raise unless statement.last.file.start_with?('lib/temporalio/api/') ||
59
- statement.last.file.start_with?('lib/temporalio/internal/bridge/api/')
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/')
60
61
  end
61
62
  end
62
63
 
@@ -64,302 +65,15 @@ YARD::Handlers::Ruby::ConstantHandler.prepend(CustomizeYardWarnings)
64
65
 
65
66
  YARD::Rake::YardocTask.new { |t| t.options = ['--fail-on-warning'] }
66
67
 
67
- require 'fileutils'
68
- require 'google/protobuf'
68
+ Rake::Task[:yard].enhance([:copy_parent_files]) do
69
+ rm ['LICENSE', 'README.md']
70
+ end
69
71
 
70
72
  namespace :proto do
71
73
  desc 'Generate API and Core protobufs'
72
74
  task :generate do
73
- # Remove all existing
74
- FileUtils.rm_rf('lib/temporalio/api')
75
-
76
- def generate_protos(api_protos)
77
- # Generate API to temp dir and move
78
- FileUtils.rm_rf('tmp-proto')
79
- FileUtils.mkdir_p('tmp-proto')
80
- sh 'bundle exec grpc_tools_ruby_protoc ' \
81
- '--proto_path=ext/sdk-core/sdk-core-protos/protos/api_upstream ' \
82
- '--proto_path=ext/sdk-core/sdk-core-protos/protos/api_cloud_upstream ' \
83
- '--proto_path=ext/additional_protos ' \
84
- '--ruby_out=tmp-proto ' \
85
- "#{api_protos.join(' ')}"
86
-
87
- # Walk all generated Ruby files and cleanup content and filename
88
- Dir.glob('tmp-proto/temporal/api/**/*.rb') do |path|
89
- # Fix up the import
90
- content = File.read(path)
91
- content.gsub!(%r{^require 'temporal/(.*)_pb'$}, "require 'temporalio/\\1'")
92
- File.write(path, content)
93
-
94
- # Remove _pb from the filename
95
- FileUtils.mv(path, path.sub('_pb', ''))
96
- end
97
-
98
- # Move from temp dir and remove temp dir
99
- FileUtils.cp_r('tmp-proto/temporal/api', 'lib/temporalio')
100
- FileUtils.rm_rf('tmp-proto')
101
- end
102
-
103
- # Generate from API with Google ones removed
104
- generate_protos(Dir.glob('ext/sdk-core/sdk-core-protos/protos/api_upstream/**/*.proto').reject do |proto|
105
- proto.include?('google')
106
- end)
107
-
108
- # Generate from Cloud API
109
- generate_protos(Dir.glob('ext/sdk-core/sdk-core-protos/protos/api_cloud_upstream/**/*.proto'))
110
-
111
- # Generate additional protos
112
- generate_protos(Dir.glob('ext/additional_protos/**/*.proto'))
113
-
114
- # Write files that will help with imports. We are requiring the
115
- # request_response and not the service because the service depends on Google
116
- # API annotations we don't want to have to depend on.
117
- File.write(
118
- 'lib/temporalio/api/cloud/cloudservice.rb',
119
- <<~TEXT
120
- # frozen_string_literal: true
121
-
122
- require 'temporalio/api/cloud/cloudservice/v1/request_response'
123
- TEXT
124
- )
125
- File.write(
126
- 'lib/temporalio/api/workflowservice.rb',
127
- <<~TEXT
128
- # frozen_string_literal: true
129
-
130
- require 'temporalio/api/workflowservice/v1/request_response'
131
- TEXT
132
- )
133
- File.write(
134
- 'lib/temporalio/api/operatorservice.rb',
135
- <<~TEXT
136
- # frozen_string_literal: true
137
-
138
- require 'temporalio/api/operatorservice/v1/request_response'
139
- TEXT
140
- )
141
- File.write(
142
- 'lib/temporalio/api.rb',
143
- <<~TEXT
144
- # frozen_string_literal: true
145
-
146
- require 'temporalio/api/cloud/cloudservice'
147
- require 'temporalio/api/common/v1/grpc_status'
148
- require 'temporalio/api/errordetails/v1/message'
149
- require 'temporalio/api/operatorservice'
150
- require 'temporalio/api/workflowservice'
151
-
152
- module Temporalio
153
- # Raw protocol buffer models.
154
- module Api
155
- end
156
- end
157
- TEXT
158
- )
159
-
160
- # Write the service classes that have the RPC calls
161
- def write_service_file(qualified_service_name:, file_name:, class_name:, service_enum:)
162
- # Do service lookup
163
- desc = Google::Protobuf::DescriptorPool.generated_pool.lookup(qualified_service_name)
164
- raise 'Failed finding service descriptor' unless desc
165
-
166
- # Open file to generate Ruby code
167
- File.open("lib/temporalio/client/connection/#{file_name}.rb", 'w') do |file|
168
- file.puts <<~TEXT
169
- # frozen_string_literal: true
170
-
171
- # Generated code. DO NOT EDIT!
172
-
173
- require 'temporalio/api'
174
- require 'temporalio/client/connection/service'
175
- require 'temporalio/internal/bridge/client'
176
-
177
- module Temporalio
178
- class Client
179
- class Connection
180
- # #{class_name} API.
181
- class #{class_name} < Service
182
- # @!visibility private
183
- def initialize(connection)
184
- super(connection, Internal::Bridge::Client::#{service_enum})
185
- end
186
- TEXT
187
-
188
- desc.each do |method|
189
- # Camel case to snake case
190
- rpc = method.name.gsub(/([A-Z])/, '_\1').downcase.delete_prefix('_')
191
- file.puts <<-TEXT
192
-
193
- # Calls #{class_name}.#{method.name} API call.
194
- #
195
- # @param request [#{method.input_type.msgclass}] API request.
196
- # @param rpc_retry [Boolean] Whether to implicitly retry known retryable errors.
197
- # @param rpc_metadata [Hash<String, String>, nil] Headers to include on the RPC call.
198
- # @param rpc_timeout [Float, nil] Number of seconds before timeout.
199
- # @return [#{method.output_type.msgclass}] API response.
200
- def #{rpc}(request, rpc_retry: false, rpc_metadata: nil, rpc_timeout: nil)
201
- invoke_rpc(
202
- rpc: '#{rpc}',
203
- request_class: #{method.input_type.msgclass},
204
- response_class: #{method.output_type.msgclass},
205
- request:,
206
- rpc_retry:,
207
- rpc_metadata:,
208
- rpc_timeout:
209
- )
210
- end
211
- TEXT
212
- end
213
-
214
- file.puts <<~TEXT
215
- end
216
- end
217
- end
218
- end
219
- TEXT
220
- end
221
-
222
- # Open file to generate RBS code
223
- # TODO(cretz): Improve this when RBS proto is supported
224
- File.open("sig/temporalio/client/connection/#{file_name}.rbs", 'w') do |file|
225
- file.puts <<~TEXT
226
- # Generated code. DO NOT EDIT!
227
-
228
- module Temporalio
229
- class Client
230
- class Connection
231
- class #{class_name} < Service
232
- def initialize: (Connection) -> void
233
- TEXT
234
-
235
- desc.each do |method|
236
- # Camel case to snake case
237
- rpc = method.name.gsub(/([A-Z])/, '_\1').downcase.delete_prefix('_')
238
- file.puts <<-TEXT
239
- def #{rpc}: (untyped request, ?rpc_retry: bool, ?rpc_metadata: Hash[String, String]?, ?rpc_timeout: Float?) -> untyped
240
- TEXT
241
- end
242
-
243
- file.puts <<~TEXT
244
- end
245
- end
246
- end
247
- end
248
- TEXT
249
- end
250
- end
251
-
252
- require './lib/temporalio/api/workflowservice/v1/service'
253
- write_service_file(
254
- qualified_service_name: 'temporal.api.workflowservice.v1.WorkflowService',
255
- file_name: 'workflow_service',
256
- class_name: 'WorkflowService',
257
- service_enum: 'SERVICE_WORKFLOW'
258
- )
259
- require './lib/temporalio/api/operatorservice/v1/service'
260
- write_service_file(
261
- qualified_service_name: 'temporal.api.operatorservice.v1.OperatorService',
262
- file_name: 'operator_service',
263
- class_name: 'OperatorService',
264
- service_enum: 'SERVICE_OPERATOR'
265
- )
266
- require './lib/temporalio/api/cloud/cloudservice/v1/service'
267
- write_service_file(
268
- qualified_service_name: 'temporal.api.cloud.cloudservice.v1.CloudService',
269
- file_name: 'cloud_service',
270
- class_name: 'CloudService',
271
- service_enum: 'SERVICE_CLOUD'
272
- )
273
-
274
- # Generate Rust code
275
- def generate_rust_match_arm(file:, qualified_service_name:, service_enum:, trait:)
276
- # Do service lookup
277
- desc = Google::Protobuf::DescriptorPool.generated_pool.lookup(qualified_service_name)
278
- file.puts <<~TEXT
279
- #{service_enum} => match call.rpc.as_str() {
280
- TEXT
281
-
282
- desc.to_a.sort_by(&:name).each do |method|
283
- # Camel case to snake case
284
- rpc = method.name.gsub(/([A-Z])/, '_\1').downcase.delete_prefix('_')
285
- file.puts <<~TEXT
286
- "#{rpc}" => rpc_call!(self, callback, call, #{trait}, #{rpc}),
287
- TEXT
288
- end
289
- file.puts <<~TEXT
290
- _ => Err(error!("Unknown RPC call {}", call.rpc)),
291
- },
292
- TEXT
293
- end
294
- File.open('ext/src/client_rpc_generated.rs', 'w') do |file|
295
- file.puts <<~TEXT
296
- // Generated code. DO NOT EDIT!
297
-
298
- use magnus::{Error, Ruby};
299
- use temporal_client::{CloudService, OperatorService, WorkflowService};
300
-
301
- use super::{error, rpc_call};
302
- use crate::{
303
- client::{Client, RpcCall, SERVICE_CLOUD, SERVICE_OPERATOR, SERVICE_WORKFLOW},
304
- util::AsyncCallback,
305
- };
306
-
307
- impl Client {
308
- pub fn invoke_rpc(&self, service: u8, callback: AsyncCallback, call: RpcCall) -> Result<(), Error> {
309
- match service {
310
- TEXT
311
- generate_rust_match_arm(
312
- file:,
313
- qualified_service_name: 'temporal.api.workflowservice.v1.WorkflowService',
314
- service_enum: 'SERVICE_WORKFLOW',
315
- trait: 'WorkflowService'
316
- )
317
- generate_rust_match_arm(
318
- file:,
319
- qualified_service_name: 'temporal.api.operatorservice.v1.OperatorService',
320
- service_enum: 'SERVICE_OPERATOR',
321
- trait: 'OperatorService'
322
- )
323
- generate_rust_match_arm(
324
- file:,
325
- qualified_service_name: 'temporal.api.cloud.cloudservice.v1.CloudService',
326
- service_enum: 'SERVICE_CLOUD',
327
- trait: 'CloudService'
328
- )
329
- file.puts <<~TEXT
330
- _ => Err(error!("Unknown service")),
331
- }
332
- }
333
- }
334
- TEXT
335
- end
336
- sh 'cargo', 'fmt', '--', 'ext/src/client_rpc_generated.rs'
337
-
338
- # Generate core protos
339
- FileUtils.rm_rf('lib/temporalio/internal/bridge/api')
340
- # Generate API to temp dir
341
- FileUtils.rm_rf('tmp-proto')
342
- FileUtils.mkdir_p('tmp-proto')
343
- sh 'bundle exec grpc_tools_ruby_protoc ' \
344
- '--proto_path=ext/sdk-core/sdk-core-protos/protos/api_upstream ' \
345
- '--proto_path=ext/sdk-core/sdk-core-protos/protos/local ' \
346
- '--ruby_out=tmp-proto ' \
347
- "#{Dir.glob('ext/sdk-core/sdk-core-protos/protos/local/**/*.proto').join(' ')}"
348
- # Walk all generated Ruby files and cleanup content and filename
349
- Dir.glob('tmp-proto/temporal/sdk/**/*.rb') do |path|
350
- # Fix up the imports
351
- content = File.read(path)
352
- content.gsub!(%r{^require 'temporal/(.*)_pb'$}, "require 'temporalio/\\1'")
353
- content.gsub!(%r{^require 'temporalio/sdk/core/(.*)'$}, "require 'temporalio/internal/bridge/api/\\1'")
354
- File.write(path, content)
355
-
356
- # Remove _pb from the filename
357
- FileUtils.mv(path, path.sub('_pb', ''))
358
- end
359
- # Move from temp dir and remove temp dir
360
- FileUtils.mkdir_p('lib/temporalio/internal/bridge/api')
361
- FileUtils.cp_r(Dir.glob('tmp-proto/temporal/sdk/core/*'), 'lib/temporalio/internal/bridge/api')
362
- FileUtils.rm_rf('tmp-proto')
75
+ require_relative 'extra/proto_gen'
76
+ ProtoGen.new.run
363
77
  end
364
78
  end
365
79
 
@@ -380,7 +94,7 @@ Rake::Task[:build].enhance([:copy_parent_files]) do
380
94
  end
381
95
 
382
96
  task :rust_lint do
383
- sh 'cargo', 'clippy'
97
+ sh 'cargo', 'clippy', '--', '-Dwarnings'
384
98
  sh 'cargo', 'fmt', '--check'
385
99
  end
386
100
 
@@ -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
@@ -101,7 +101,10 @@ module Temporalio
101
101
  }.freeze
102
102
  end
103
103
 
104
- # TODO(cretz): metric meter
104
+ # @return [Metric::Meter] Metric meter to create metrics on, with some activity-specific attributes already set.
105
+ def metric_meter
106
+ raise NotImplementedError
107
+ end
105
108
  end
106
109
  end
107
110
  end
@@ -1,76 +1,174 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  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.
4
+ module Activity
5
+ # Base class for all activities.
6
+ #
7
+ # Activities can be given to a worker as instances of this class, which will call execute on the same instance for
8
+ # each execution, or given to the worker as the class itself which instantiates the activity for each execution.
9
+ #
10
+ # All activities must implement {execute}. Inside execute, {Activity::Context.current} can be used to access the
11
+ # current context to get information, issue heartbeats, etc.
12
+ #
13
+ # By default, the activity is named as its unqualified class name. This can be customized with {activity_name}.
14
+ #
15
+ # By default, the activity uses the `:default` executor which is usually the thread-pool based executor. This can be
16
+ # customized with {activity_executor}.
17
+ #
18
+ # By default, upon cancellation {::Thread.raise} or {::Fiber.raise} is called with a {Error::CanceledError}. This
19
+ # can be disabled by passing `false` to {activity_cancel_raise}.
20
+ #
21
+ # See documentation for more detail on activities.
7
22
  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"
23
+ class << self
24
+ protected
25
+
26
+ # Override the activity name which is defaulted to the unqualified class name.
27
+ #
28
+ # @param name [String, Symbol] Name to use.
29
+ def activity_name(name)
30
+ if !name.is_a?(Symbol) && !name.is_a?(String)
31
+ raise ArgumentError,
32
+ 'Activity name must be a symbol or string'
33
+ end
34
+
35
+ @activity_name = name.to_s
36
+ end
37
+
38
+ # Override the activity executor which is defaulted to `:default`.
39
+ #
40
+ # @param executor_name [Symbol] Executor to use.
41
+ def activity_executor(executor_name)
42
+ raise ArgumentError, 'Executor name must be a symbol' unless executor_name.is_a?(Symbol)
43
+
44
+ @activity_executor = executor_name
45
+ end
46
+
47
+ # Override whether the activity uses Thread/Fiber raise for cancellation which is defaulted to true.
48
+ #
49
+ # @param cancel_raise [Boolean] Whether to raise.
50
+ def activity_cancel_raise(cancel_raise)
51
+ unless cancel_raise.is_a?(TrueClass) || cancel_raise.is_a?(FalseClass)
52
+ raise ArgumentError, 'Must be a boolean'
53
+ end
54
+
55
+ @activity_cancel_raise = cancel_raise
56
+ end
57
+
58
+ # Set an activity as dynamic. Dynamic activities do not have names and handle any activity that is not otherwise
59
+ # registered. A worker can only have one dynamic activity. It is often useful to use {activity_raw_args} with
60
+ # this.
61
+ #
62
+ # @param value [Boolean] Whether the activity is dynamic.
63
+ def activity_dynamic(value = true) # rubocop:disable Style/OptionalBooleanParameter
64
+ raise ArgumentError, 'Must be a boolean' unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
65
+
66
+ @activity_dynamic = value
67
+ end
68
+
69
+ # Have activity arguments delivered to `execute` as {Converters::RawValue}s. These are wrappers for the raw
70
+ # payloads that have not been converted to types (but they have been decoded by the codec if present). They can
71
+ # be converted with {Context#payload_converter}.
72
+ #
73
+ # @param value [Boolean] Whether the activity accepts raw arguments.
74
+ def activity_raw_args(value = true) # rubocop:disable Style/OptionalBooleanParameter
75
+ raise ArgumentError, 'Must be a boolean' unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
76
+
77
+ @activity_raw_args = value
52
78
  end
53
79
  end
54
80
 
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'
81
+ # @!visibility private
82
+ def self._activity_definition_details
83
+ activity_name = @activity_name
84
+ raise 'Cannot have activity name specified for dynamic activity' if activity_name && @activity_dynamic
85
+
86
+ # Default to unqualified class name if not dynamic
87
+ activity_name ||= name.to_s.split('::').last unless @activity_dynamic
88
+ {
89
+ activity_name:,
90
+ activity_executor: @activity_executor || :default,
91
+ activity_cancel_raise: @activity_cancel_raise.nil? ? true : @activity_cancel_raise,
92
+ activity_raw_args: @activity_raw_args.nil? ? false : @activity_raw_args
93
+ }
94
+ end
95
+
96
+ # Implementation of the activity. The arguments should be positional and this should return the value on success
97
+ # or raise an error on failure.
98
+ def execute(*args)
99
+ raise NotImplementedError, 'Activity did not implement "execute"'
100
+ end
101
+
102
+ # Definition info of an activity. Activities are usually classes/instances that extend {Definition}, but
103
+ # definitions can also be manually created with a block via {initialize} here.
104
+ class Info
105
+ # @return [String, Symbol, nil] Name of the activity, or nil if the activity is dynamic.
106
+ attr_reader :name
107
+
108
+ # @return [Proc] Proc for the activity.
109
+ attr_reader :proc
110
+
111
+ # @return [Symbol] Name of the executor. Default is `:default`.
112
+ attr_reader :executor
113
+
114
+ # @return [Boolean] Whether to raise in thread/fiber on cancellation. Default is `true`.
115
+ attr_reader :cancel_raise
116
+
117
+ # @return [Boolean] Whether to use {Converters::RawValue}s as arguments.
118
+ attr_reader :raw_args
119
+
120
+ # Obtain definition info representing the given activity, which can be a class, instance, or definition info.
121
+ #
122
+ # @param activity [Definition, Class<Definition>, Info] Activity to get info for.
123
+ # @return Info Obtained definition info.
124
+ def self.from_activity(activity)
125
+ # Class means create each time, instance means just call, definition
126
+ # does nothing special
127
+ case activity
128
+ when Class
129
+ unless activity < Definition
130
+ raise ArgumentError,
131
+ "Class '#{activity}' does not extend Temporalio::Activity::Definition"
132
+ end
133
+
134
+ details = activity._activity_definition_details
135
+ new(
136
+ name: details[:activity_name],
137
+ executor: details[:activity_executor],
138
+ cancel_raise: details[:activity_cancel_raise],
139
+ raw_args: details[:activity_raw_args]
140
+ ) { |*args| activity.new.execute(*args) } # Instantiate and call
141
+ when Definition
142
+ details = activity.class._activity_definition_details
143
+ new(
144
+ name: details[:activity_name],
145
+ executor: details[:activity_executor],
146
+ cancel_raise: details[:activity_cancel_raise],
147
+ raw_args: details[:activity_raw_args]
148
+ ) { |*args| activity.execute(*args) } # Just and call
149
+ when Info
150
+ activity
151
+ else
152
+ raise ArgumentError, "#{activity} is not an activity class, instance, or definition info"
153
+ end
154
+ end
155
+
156
+ # Manually create activity definition info. Most users will use an instance/class of {Definition}.
157
+ #
158
+ # @param name [String, Symbol, nil] Name of the activity or nil for dynamic activity.
159
+ # @param executor [Symbol] Name of the executor.
160
+ # @param cancel_raise [Boolean] Whether to raise in thread/fiber on cancellation.
161
+ # @param raw_args [Boolean] Whether to use {Converters::RawValue}s as arguments.
162
+ # @yield Use this block as the activity.
163
+ def initialize(name:, executor: :default, cancel_raise: true, raw_args: false, &block)
164
+ @name = name
165
+ raise ArgumentError, 'Must give block' unless block_given?
166
+
167
+ @proc = block
168
+ @executor = executor
169
+ @cancel_raise = cancel_raise
170
+ @raw_args = raw_args
70
171
  end
71
- @proc = proc
72
- @executor = executor
73
- @cancel_raise = cancel_raise
74
172
  end
75
173
  end
76
174
  end