temporal-ruby 0.0.1.pre.pre1 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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