temporal-ruby 0.0.1.pre.pre1 → 0.0.1

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +23 -3
  4. data/lib/gen/temporal/api/command/v1/message_pb.rb +1 -1
  5. data/lib/gen/temporal/api/enums/v1/common_pb.rb +7 -0
  6. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +5 -6
  7. data/lib/gen/temporal/api/version/v1/message_pb.rb +19 -8
  8. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +19 -8
  9. data/lib/gen/temporal/api/workflowservice/v1/service_services_pb.rb +0 -3
  10. data/lib/temporal.rb +104 -0
  11. data/lib/temporal/activity/context.rb +5 -1
  12. data/lib/temporal/activity/poller.rb +26 -9
  13. data/lib/temporal/activity/task_processor.rb +33 -20
  14. data/lib/temporal/client/converter/base.rb +35 -0
  15. data/lib/temporal/client/converter/composite.rb +49 -0
  16. data/lib/temporal/client/converter/payload/bytes.rb +30 -0
  17. data/lib/temporal/client/converter/payload/json.rb +28 -0
  18. data/lib/temporal/client/converter/payload/nil.rb +27 -0
  19. data/lib/temporal/client/grpc_client.rb +102 -27
  20. data/lib/temporal/client/retryer.rb +49 -0
  21. data/lib/temporal/client/serializer.rb +2 -0
  22. data/lib/temporal/client/serializer/cancel_timer.rb +2 -2
  23. data/lib/temporal/client/serializer/complete_workflow.rb +6 -4
  24. data/lib/temporal/client/serializer/continue_as_new.rb +37 -0
  25. data/lib/temporal/client/serializer/fail_workflow.rb +2 -2
  26. data/lib/temporal/client/serializer/failure.rb +4 -2
  27. data/lib/temporal/client/serializer/record_marker.rb +6 -4
  28. data/lib/temporal/client/serializer/request_activity_cancellation.rb +2 -2
  29. data/lib/temporal/client/serializer/retry_policy.rb +24 -0
  30. data/lib/temporal/client/serializer/schedule_activity.rb +8 -20
  31. data/lib/temporal/client/serializer/start_child_workflow.rb +9 -20
  32. data/lib/temporal/client/serializer/start_timer.rb +2 -2
  33. data/lib/temporal/concerns/payloads.rb +51 -0
  34. data/lib/temporal/configuration.rb +31 -4
  35. data/lib/temporal/error_handler.rb +11 -0
  36. data/lib/temporal/errors.rb +24 -0
  37. data/lib/temporal/execution_options.rb +9 -1
  38. data/lib/temporal/json.rb +3 -1
  39. data/lib/temporal/logger.rb +17 -0
  40. data/lib/temporal/metadata.rb +11 -3
  41. data/lib/temporal/metadata/activity.rb +15 -2
  42. data/lib/temporal/metadata/workflow.rb +8 -0
  43. data/lib/temporal/metadata/workflow_task.rb +11 -0
  44. data/lib/temporal/retry_policy.rb +6 -9
  45. data/lib/temporal/saga/concern.rb +1 -1
  46. data/lib/temporal/testing.rb +1 -0
  47. data/lib/temporal/testing/future_registry.rb +1 -1
  48. data/lib/temporal/testing/local_activity_context.rb +1 -1
  49. data/lib/temporal/testing/local_workflow_context.rb +38 -14
  50. data/lib/temporal/testing/scheduled_workflows.rb +75 -0
  51. data/lib/temporal/testing/temporal_override.rb +35 -7
  52. data/lib/temporal/testing/workflow_override.rb +6 -1
  53. data/lib/temporal/version.rb +1 -1
  54. data/lib/temporal/worker.rb +28 -10
  55. data/lib/temporal/workflow.rb +8 -2
  56. data/lib/temporal/workflow/command.rb +3 -0
  57. data/lib/temporal/workflow/context.rb +40 -5
  58. data/lib/temporal/workflow/errors.rb +39 -0
  59. data/lib/temporal/workflow/executor.rb +1 -1
  60. data/lib/temporal/workflow/future.rb +18 -6
  61. data/lib/temporal/workflow/history/event.rb +1 -3
  62. data/lib/temporal/workflow/history/event_target.rb +4 -0
  63. data/lib/temporal/workflow/history/window.rb +1 -1
  64. data/lib/temporal/workflow/poller.rb +41 -13
  65. data/lib/temporal/workflow/replay_aware_logger.rb +4 -4
  66. data/lib/temporal/workflow/state_manager.rb +33 -52
  67. data/lib/temporal/workflow/task_processor.rb +41 -11
  68. metadata +21 -9
  69. data/lib/temporal/client/serializer/payload.rb +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42114cc4bbe2bc250e8c8e5dd5cfef7701fc48ea5b18eb1be4581dc8d8aa1a62
4
- data.tar.gz: 4824e86f5440afe08de9d15fb7462eef948bef48696d85fca0fd5714cc117d9e
3
+ metadata.gz: 53787ddd1790dc6c6351b5a7dc28097945f84b254064f28e70f992a55d71c24c
4
+ data.tar.gz: b29c289da477adf979d9aad49c37304c25be3b837f428f21928c6eb0b722488c
5
5
  SHA512:
6
- metadata.gz: 2a8a04ab82160833c6d0ebe0dc7cd8601341821aa1ab8124ccfc5cae854c275868d32765ad5c0c8563d70e72b2d36110c8f61addf44e75899826b57f9123a05b
7
- data.tar.gz: 30d8479367f29a687b203c5ecef4e6de1c32bb9263c2e91e6e822a93c7db3f418641e6095a8e4ef0e552ba3973caa6b016f864ea92802bc2189c47185a7e6fff
6
+ metadata.gz: 5cc0666de89e075656f11d02012de544fb996f2ac8f7d684a1907ff83b00015515ab764be6faf1302dff979415bfe8d734d4d6be2e9bc54343923a79a69fcd70
7
+ data.tar.gz: 6442f0fb3308c6dd99b1b1f879fd34512eb0d0a49d4965682e65c1649cfbbda88311b9719956f365fd4faebfca55367d7623f584cc32140f1d90a991062b9477
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ gem 'coveralls', require: false
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
- # Ruby worker for Temporal [Under Development]
1
+ # Ruby worker for Temporal
2
+
3
+ [![Coverage Status](https://coveralls.io/repos/github/coinbase/temporal-ruby/badge.svg?branch=master)](https://coveralls.io/github/coinbase/temporal-ruby?branch=master)
2
4
 
3
5
  <img src="./assets/temporal_logo.png" width="250" align="right" alt="Temporal" />
4
6
 
@@ -98,7 +100,7 @@ Temporal service handles all the persistence, fault tolerance and coordination o
98
100
  activities. To set it up locally, download and boot the Docker Compose file from the official repo:
99
101
 
100
102
  ```sh
101
- > curl -O https://raw.githubusercontent.com/temporalio/temporal/master/docker/docker-compose.yml
103
+ > curl -O https://raw.githubusercontent.com/temporalio/docker-compose/main/docker-compose.yml
102
104
 
103
105
  > docker-compose up
104
106
  ```
@@ -166,7 +168,7 @@ Besides calling activities workflows can:
166
168
 
167
169
  - Use timers
168
170
  - Receive signals
169
- - Execute other (child) workflows [not yet implemented]
171
+ - Execute other (child) workflows
170
172
  - Respond to queries [not yet implemented]
171
173
 
172
174
 
@@ -308,6 +310,24 @@ of precedence):
308
310
  3. Globally, when configuring your Temporal library via `Temporal.configure`
309
311
 
310
312
 
313
+ ## Periodic workflow execution
314
+
315
+ In certain cases you might need a workflow that runs periodically using a cron schedule. This can be
316
+ achieved using the `Temporal.schedule_workflow` API that take a periodic cron schedule as a second
317
+ argument:
318
+
319
+ ```ruby
320
+ Temporal.schedule_workflow(HealthCheckWorkflow, '*/5 * * * *')
321
+ ```
322
+
323
+ This will instruct Temporal to run a HealthCheckWorkflow every 5 minutes. All the rest of the
324
+ arguments are identical to the `Temporal.start_workflow` API.
325
+
326
+ *NOTE: Your execution timeout will be measured across all the workflow invocations, so make sure to
327
+ set it to allow as many invocations as you need. You can also set it to `nil`, which will use a
328
+ default value of 10 years.*
329
+
330
+
311
331
  ## Breaking Changes
312
332
 
313
333
  Since the workflow execution has to be deterministic, breaking changes can not be simply added and
@@ -124,7 +124,7 @@ end
124
124
 
125
125
  module Temporal
126
126
  module Api
127
- module Decision
127
+ module Command
128
128
  module V1
129
129
  ScheduleActivityTaskCommandAttributes = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.command.v1.ScheduleActivityTaskCommandAttributes").msgclass
130
130
  RequestCancelActivityTaskCommandAttributes = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.command.v1.RequestCancelActivityTaskCommandAttributes").msgclass
@@ -19,6 +19,12 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
19
19
  value :INDEXED_VALUE_TYPE_BOOL, 5
20
20
  value :INDEXED_VALUE_TYPE_DATETIME, 6
21
21
  end
22
+ add_enum "temporal.api.enums.v1.Severity" do
23
+ value :SEVERITY_UNSPECIFIED, 0
24
+ value :SEVERITY_HIGH, 1
25
+ value :SEVERITY_MEDIUM, 2
26
+ value :SEVERITY_LOW, 3
27
+ end
22
28
  end
23
29
  end
24
30
 
@@ -28,6 +34,7 @@ module Temporal
28
34
  module V1
29
35
  EncodingType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.enums.v1.EncodingType").enummodule
30
36
  IndexedValueType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.enums.v1.IndexedValueType").enummodule
37
+ Severity = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.enums.v1.Severity").enummodule
31
38
  end
32
39
  end
33
40
  end
@@ -20,13 +20,12 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
20
20
  end
21
21
  add_message "temporal.api.errordetails.v1.ClientVersionNotSupportedFailure" do
22
22
  optional :client_version, :string, 1
23
- optional :client_impl, :string, 2
23
+ optional :client_name, :string, 2
24
24
  optional :supported_versions, :string, 3
25
25
  end
26
- add_message "temporal.api.errordetails.v1.FeatureVersionNotSupportedFailure" do
27
- optional :feature, :string, 1
28
- optional :feature_version, :string, 2
29
- optional :supported_versions, :string, 3
26
+ add_message "temporal.api.errordetails.v1.ServerVersionNotSupportedFailure" do
27
+ optional :server_version, :string, 1
28
+ optional :client_supported_server_versions, :string, 2
30
29
  end
31
30
  add_message "temporal.api.errordetails.v1.NamespaceAlreadyExistsFailure" do
32
31
  end
@@ -45,7 +44,7 @@ module Temporal
45
44
  WorkflowExecutionAlreadyStartedFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.errordetails.v1.WorkflowExecutionAlreadyStartedFailure").msgclass
46
45
  NamespaceNotActiveFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.errordetails.v1.NamespaceNotActiveFailure").msgclass
47
46
  ClientVersionNotSupportedFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.errordetails.v1.ClientVersionNotSupportedFailure").msgclass
48
- FeatureVersionNotSupportedFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.errordetails.v1.FeatureVersionNotSupportedFailure").msgclass
47
+ ServerVersionNotSupportedFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.errordetails.v1.ServerVersionNotSupportedFailure").msgclass
49
48
  NamespaceAlreadyExistsFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.errordetails.v1.NamespaceAlreadyExistsFailure").msgclass
50
49
  CancellationAlreadyRequestedFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.errordetails.v1.CancellationAlreadyRequestedFailure").msgclass
51
50
  QueryFailedFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.errordetails.v1.QueryFailedFailure").msgclass
@@ -3,15 +3,25 @@
3
3
 
4
4
  require 'google/protobuf'
5
5
 
6
+ require 'google/protobuf/timestamp_pb'
7
+ require 'temporal/api/enums/v1/common_pb'
6
8
  Google::Protobuf::DescriptorPool.generated_pool.build do
7
9
  add_file("temporal/api/version/v1/message.proto", :syntax => :proto3) do
8
- add_message "temporal.api.version.v1.SupportedSDKVersions" do
9
- optional :go_sdk, :string, 1
10
- optional :java_sdk, :string, 2
10
+ add_message "temporal.api.version.v1.ReleaseInfo" do
11
+ optional :version, :string, 1
12
+ optional :release_time, :message, 2, "google.protobuf.Timestamp"
13
+ optional :notes, :string, 3
11
14
  end
12
- add_message "temporal.api.version.v1.WorkerVersionInfo" do
13
- optional :implementation, :string, 1
14
- optional :feature_version, :string, 2
15
+ add_message "temporal.api.version.v1.Alert" do
16
+ optional :message, :string, 1
17
+ optional :severity, :enum, 2, "temporal.api.enums.v1.Severity"
18
+ end
19
+ add_message "temporal.api.version.v1.VersionInfo" do
20
+ optional :current, :message, 1, "temporal.api.version.v1.ReleaseInfo"
21
+ optional :recommended, :message, 2, "temporal.api.version.v1.ReleaseInfo"
22
+ optional :instructions, :string, 3
23
+ repeated :alerts, :message, 4, "temporal.api.version.v1.Alert"
24
+ optional :last_update_time, :message, 5, "google.protobuf.Timestamp"
15
25
  end
16
26
  end
17
27
  end
@@ -20,8 +30,9 @@ module Temporal
20
30
  module Api
21
31
  module Version
22
32
  module V1
23
- SupportedSDKVersions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.version.v1.SupportedSDKVersions").msgclass
24
- WorkerVersionInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.version.v1.WorkerVersionInfo").msgclass
33
+ ReleaseInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.version.v1.ReleaseInfo").msgclass
34
+ Alert = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.version.v1.Alert").msgclass
35
+ VersionInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("temporal.api.version.v1.VersionInfo").msgclass
25
36
  end
26
37
  end
27
38
  end
@@ -3,8 +3,6 @@
3
3
 
4
4
  require 'google/protobuf'
5
5
 
6
- require 'google/protobuf/duration_pb'
7
- require 'google/protobuf/timestamp_pb'
8
6
  require 'temporal/api/enums/v1/workflow_pb'
9
7
  require 'temporal/api/enums/v1/namespace_pb'
10
8
  require 'temporal/api/enums/v1/failed_cause_pb'
@@ -22,10 +20,12 @@ require 'temporal/api/query/v1/message_pb'
22
20
  require 'temporal/api/replication/v1/message_pb'
23
21
  require 'temporal/api/taskqueue/v1/message_pb'
24
22
  require 'temporal/api/version/v1/message_pb'
23
+ require 'google/protobuf/duration_pb'
24
+ require 'google/protobuf/timestamp_pb'
25
25
  Google::Protobuf::DescriptorPool.generated_pool.build do
26
26
  add_file("temporal/api/workflowservice/v1/request_response.proto", :syntax => :proto3) do
27
27
  add_message "temporal.api.workflowservice.v1.RegisterNamespaceRequest" do
28
- optional :name, :string, 1
28
+ optional :namespace, :string, 1
29
29
  optional :description, :string, 2
30
30
  optional :owner_email, :string, 3
31
31
  optional :workflow_execution_retention_period, :message, 4, "google.protobuf.Duration"
@@ -50,7 +50,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
50
50
  optional :next_page_token, :bytes, 2
51
51
  end
52
52
  add_message "temporal.api.workflowservice.v1.DescribeNamespaceRequest" do
53
- optional :name, :string, 1
53
+ optional :namespace, :string, 1
54
54
  optional :id, :string, 2
55
55
  end
56
56
  add_message "temporal.api.workflowservice.v1.DescribeNamespaceResponse" do
@@ -61,7 +61,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
61
61
  optional :is_global_namespace, :bool, 5
62
62
  end
63
63
  add_message "temporal.api.workflowservice.v1.UpdateNamespaceRequest" do
64
- optional :name, :string, 1
64
+ optional :namespace, :string, 1
65
65
  optional :update_info, :message, 2, "temporal.api.namespace.v1.UpdateNamespaceInfo"
66
66
  optional :config, :message, 3, "temporal.api.namespace.v1.NamespaceConfig"
67
67
  optional :replication_config, :message, 4, "temporal.api.replication.v1.NamespaceReplicationConfig"
@@ -76,7 +76,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
76
76
  optional :is_global_namespace, :bool, 5
77
77
  end
78
78
  add_message "temporal.api.workflowservice.v1.DeprecateNamespaceRequest" do
79
- optional :name, :string, 1
79
+ optional :namespace, :string, 1
80
80
  optional :security_token, :string, 2
81
81
  end
82
82
  add_message "temporal.api.workflowservice.v1.DeprecateNamespaceResponse" do
@@ -148,6 +148,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
148
148
  optional :force_create_new_workflow_task, :bool, 6
149
149
  optional :binary_checksum, :string, 7
150
150
  map :query_results, :string, :message, 8, "temporal.api.query.v1.WorkflowQueryResult"
151
+ optional :namespace, :string, 9
151
152
  end
152
153
  add_message "temporal.api.workflowservice.v1.RespondWorkflowTaskCompletedResponse" do
153
154
  optional :workflow_task, :message, 1, "temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponse"
@@ -158,6 +159,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
158
159
  optional :failure, :message, 3, "temporal.api.failure.v1.Failure"
159
160
  optional :identity, :string, 4
160
161
  optional :binary_checksum, :string, 5
162
+ optional :namespace, :string, 6
161
163
  end
162
164
  add_message "temporal.api.workflowservice.v1.RespondWorkflowTaskFailedResponse" do
163
165
  end
@@ -190,6 +192,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
190
192
  optional :task_token, :bytes, 1
191
193
  optional :details, :message, 2, "temporal.api.common.v1.Payloads"
192
194
  optional :identity, :string, 3
195
+ optional :namespace, :string, 4
193
196
  end
194
197
  add_message "temporal.api.workflowservice.v1.RecordActivityTaskHeartbeatResponse" do
195
198
  optional :cancel_requested, :bool, 1
@@ -209,6 +212,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
209
212
  optional :task_token, :bytes, 1
210
213
  optional :result, :message, 2, "temporal.api.common.v1.Payloads"
211
214
  optional :identity, :string, 3
215
+ optional :namespace, :string, 4
212
216
  end
213
217
  add_message "temporal.api.workflowservice.v1.RespondActivityTaskCompletedResponse" do
214
218
  end
@@ -226,6 +230,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
226
230
  optional :task_token, :bytes, 1
227
231
  optional :failure, :message, 2, "temporal.api.failure.v1.Failure"
228
232
  optional :identity, :string, 3
233
+ optional :namespace, :string, 4
229
234
  end
230
235
  add_message "temporal.api.workflowservice.v1.RespondActivityTaskFailedResponse" do
231
236
  end
@@ -243,6 +248,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
243
248
  optional :task_token, :bytes, 1
244
249
  optional :details, :message, 2, "temporal.api.common.v1.Payloads"
245
250
  optional :identity, :string, 3
251
+ optional :namespace, :string, 4
246
252
  end
247
253
  add_message "temporal.api.workflowservice.v1.RespondActivityTaskCanceledResponse" do
248
254
  end
@@ -396,7 +402,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
396
402
  optional :completed_type, :enum, 2, "temporal.api.enums.v1.QueryResultType"
397
403
  optional :query_result, :message, 3, "temporal.api.common.v1.Payloads"
398
404
  optional :error_message, :string, 4
399
- optional :worker_version_info, :message, 5, "temporal.api.version.v1.WorkerVersionInfo"
405
+ optional :namespace, :string, 6
400
406
  end
401
407
  add_message "temporal.api.workflowservice.v1.RespondQueryTaskCompletedResponse" do
402
408
  end
@@ -439,7 +445,12 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
439
445
  add_message "temporal.api.workflowservice.v1.GetClusterInfoRequest" do
440
446
  end
441
447
  add_message "temporal.api.workflowservice.v1.GetClusterInfoResponse" do
442
- optional :supported_sdk_versions, :message, 1, "temporal.api.version.v1.SupportedSDKVersions"
448
+ map :supported_clients, :string, :string, 1
449
+ optional :server_version, :string, 2
450
+ optional :cluster_id, :string, 3
451
+ optional :version_info, :message, 4, "temporal.api.version.v1.VersionInfo"
452
+ optional :cluster_name, :string, 5
453
+ optional :history_shard_count, :int32, 6
443
454
  end
444
455
  add_message "temporal.api.workflowservice.v1.ListTaskQueuePartitionsRequest" do
445
456
  optional :namespace, :string, 1
@@ -199,9 +199,6 @@ module Temporal
199
199
  # Things cleared are:
200
200
  # 1. StickyTaskQueue
201
201
  # 2. StickyScheduleToStartTimeout
202
- # 3. ClientLibraryVersion
203
- # 4. ClientFeatureVersion
204
- # 5. ClientImpl
205
202
  rpc :ResetStickyTaskQueue, ::Temporal::Api::WorkflowService::V1::ResetStickyTaskQueueRequest, ::Temporal::Api::WorkflowService::V1::ResetStickyTaskQueueResponse
206
203
  # QueryWorkflow returns query result for a specified workflow execution
207
204
  rpc :QueryWorkflow, ::Temporal::Api::WorkflowService::V1::QueryWorkflowRequest, ::Temporal::Api::WorkflowService::V1::QueryWorkflowResponse
data/lib/temporal.rb CHANGED
@@ -11,6 +11,9 @@ require 'temporal/workflow'
11
11
  require 'temporal/workflow/history'
12
12
  require 'temporal/workflow/execution_info'
13
13
  require 'temporal/metrics'
14
+ require 'temporal/json'
15
+ require 'temporal/errors'
16
+ require 'temporal/workflow/errors'
14
17
 
15
18
  module Temporal
16
19
  class << self
@@ -28,6 +31,8 @@ module Temporal
28
31
  task_queue: execution_options.task_queue,
29
32
  input: input,
30
33
  execution_timeout: execution_options.timeouts[:execution],
34
+ # If unspecified, individual runs should have the full time for the execution (which includes retries).
35
+ run_timeout: execution_options.timeouts[:run] || execution_options.timeouts[:execution],
31
36
  task_timeout: execution_options.timeouts[:task],
32
37
  workflow_id_reuse_policy: options[:workflow_id_reuse_policy],
33
38
  headers: execution_options.headers
@@ -36,6 +41,33 @@ module Temporal
36
41
  response.run_id
37
42
  end
38
43
 
44
+ def schedule_workflow(workflow, cron_schedule, *input, **args)
45
+ options = args.delete(:options) || {}
46
+ input << args unless args.empty?
47
+
48
+ execution_options = ExecutionOptions.new(workflow, options)
49
+ workflow_id = options[:workflow_id] || SecureRandom.uuid
50
+
51
+ response = client.start_workflow_execution(
52
+ namespace: execution_options.namespace,
53
+ workflow_id: workflow_id,
54
+ workflow_name: execution_options.name,
55
+ task_queue: execution_options.task_queue,
56
+ input: input,
57
+ execution_timeout: execution_options.timeouts[:execution],
58
+ # Execution timeout is across all scheduled jobs, whereas run is for an individual run.
59
+ # This default is here for backward compatibility. Certainly, the run timeout shouldn't be higher
60
+ # than the execution timeout.
61
+ run_timeout: execution_options.timeouts[:run] || execution_options.timeouts[:execution],
62
+ task_timeout: execution_options.timeouts[:task],
63
+ workflow_id_reuse_policy: options[:workflow_id_reuse_policy],
64
+ headers: execution_options.headers,
65
+ cron_schedule: cron_schedule
66
+ )
67
+
68
+ response.run_id
69
+ end
70
+
39
71
  def register_namespace(name, description = nil)
40
72
  client.register_namespace(name: name, description: description)
41
73
  end
@@ -52,6 +84,61 @@ module Temporal
52
84
  )
53
85
  end
54
86
 
87
+ # Long polls for a workflow to be completed and returns whatever the execute function
88
+ # returned. This function times out after 30 seconds and throws Temporal::TimeoutError,
89
+ # not to be confused with Temporal::WorkflowTimedOut which reports that the workflow
90
+ # itself timed out.
91
+ # run_id of nil: await the entire workflow completion. This can span multiple runs
92
+ # in the case where the workflow uses continue-as-new.
93
+ # timeout: seconds to wait for the result. This cannot be longer than 30 seconds because
94
+ # that is the maximum the server supports.
95
+ # namespace: if nil, choose the one declared on the Workflow, or the global default
96
+ def await_workflow_result(workflow, workflow_id:, run_id: nil, timeout: nil, namespace: nil)
97
+ options = namespace ? {namespace: namespace} : {}
98
+ execution_options = ExecutionOptions.new(workflow, options)
99
+ max_timeout = Temporal::Client::GRPCClient::SERVER_MAX_GET_WORKFLOW_EXECUTION_HISTORY_POLL
100
+ history_response = nil
101
+ begin
102
+ history_response = client.get_workflow_execution_history(
103
+ namespace: execution_options.namespace,
104
+ workflow_id: workflow_id,
105
+ run_id: run_id,
106
+ wait_for_new_event: true,
107
+ event_type: :close,
108
+ timeout: timeout || max_timeout,
109
+ )
110
+ rescue GRPC::DeadlineExceeded => e
111
+ message = if timeout
112
+ "Timed out after your specified limit of timeout: #{timeout} seconds"
113
+ else
114
+ "Timed out after #{max_timeout} seconds, which is the maximum supported amount."
115
+ end
116
+ raise TimeoutError.new(message)
117
+ end
118
+ history = Workflow::History.new(history_response.history.events)
119
+ closed_event = history.events.first
120
+ case closed_event.type
121
+ when 'WORKFLOW_EXECUTION_COMPLETED'
122
+ payloads = closed_event.attributes.result
123
+ return ResultConverter.from_result_payloads(payloads)
124
+ when 'WORKFLOW_EXECUTION_TIMED_OUT'
125
+ raise Temporal::WorkflowTimedOut
126
+ when 'WORKFLOW_EXECUTION_TERMINATED'
127
+ raise Temporal::WorkflowTerminated
128
+ when 'WORKFLOW_EXECUTION_CANCELED'
129
+ raise Temporal::WorkflowCanceled
130
+ when 'WORKFLOW_EXECUTION_FAILED'
131
+ raise Temporal::Workflow::Errors.generate_error(closed_event.attributes.failure)
132
+ when 'WORKFLOW_EXECUTION_CONTINUED_AS_NEW'
133
+ new_run_id = closed_event.attributes.new_execution_run_id
134
+ # Throw to let the caller know they're not getting the result
135
+ # they wanted. They can re-call with the new run_id to poll.
136
+ raise Temporal::WorkflowRunContinuedAsNew.new(new_run_id: new_run_id)
137
+ else
138
+ raise NotImplementedError, "Unexpected event type #{closed_event.type}."
139
+ end
140
+ end
141
+
55
142
  def reset_workflow(namespace, workflow_id, run_id, workflow_task_id: nil, reason: 'manual reset')
56
143
  workflow_task_id ||= get_last_completed_workflow_task_id(namespace, workflow_id, run_id)
57
144
  raise Error, 'Could not find a completed workflow task event' unless workflow_task_id
@@ -67,6 +154,18 @@ module Temporal
67
154
  response.run_id
68
155
  end
69
156
 
157
+ def terminate_workflow(workflow_id, namespace: nil, run_id: nil, reason: nil, details: nil)
158
+ namespace ||= Temporal.configuration.namespace
159
+
160
+ client.terminate_workflow_execution(
161
+ namespace: namespace,
162
+ workflow_id: workflow_id,
163
+ run_id: run_id,
164
+ reason: reason,
165
+ details: details
166
+ )
167
+ end
168
+
70
169
  def fetch_workflow_execution_info(namespace, workflow_id, run_id)
71
170
  response = client.describe_workflow_execution(
72
171
  namespace: namespace,
@@ -117,6 +216,11 @@ module Temporal
117
216
  @metrics ||= Metrics.new(configuration.metrics_adapter)
118
217
  end
119
218
 
219
+ class ResultConverter
220
+ extend Concerns::Payloads
221
+ end
222
+ private_constant :ResultConverter
223
+
120
224
  private
121
225
 
122
226
  def client
@@ -31,10 +31,14 @@ module Temporal
31
31
  end
32
32
 
33
33
  def heartbeat(details = nil)
34
- logger.debug('Activity heartbeat')
34
+ logger.debug("Activity heartbeat", metadata.to_h)
35
35
  client.record_activity_task_heartbeat(task_token: task_token, details: details)
36
36
  end
37
37
 
38
+ def heartbeat_details
39
+ metadata.heartbeat_details
40
+ end
41
+
38
42
  def logger
39
43
  Temporal.logger
40
44
  end