temporalio 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +12 -12
- data/README.md +57 -0
- data/lib/temporalio/activity/definition.rb +22 -0
- data/lib/temporalio/activity/info.rb +21 -5
- data/lib/temporalio/client/activity_execution.rb +221 -0
- data/lib/temporalio/client/activity_execution_count.rb +40 -0
- data/lib/temporalio/client/activity_execution_status.rb +20 -0
- data/lib/temporalio/client/activity_handle.rb +123 -0
- data/lib/temporalio/client/activity_id_reference.rb +42 -7
- data/lib/temporalio/client/interceptor.rb +149 -0
- data/lib/temporalio/client/pending_activity_state.rb +18 -0
- data/lib/temporalio/client/with_start_workflow_operation.rb +6 -0
- data/lib/temporalio/client.rb +204 -0
- data/lib/temporalio/common_enums.rb +28 -0
- data/lib/temporalio/error/failure.rb +22 -0
- data/lib/temporalio/error.rb +11 -0
- data/lib/temporalio/internal/client/implementation.rb +213 -22
- data/lib/temporalio/internal/worker/activity_worker.rb +15 -5
- data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +14 -4
- data/lib/temporalio/testing/activity_environment.rb +2 -0
- data/lib/temporalio/version.rb +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 02f37fc5f0253de8502b8f11163f2df6038932aa103d1a6b4cde9e7b744f8db1
|
|
4
|
+
data.tar.gz: 9fa127403d3ffc13493c155493122eb7bd52eb83aae31f2ba8c32c47a05e5661
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5c06d25a83a29b5a7f1a5d1aa3ae5e83bd7c35155b5d5700d561dd87026b51e020eb0b8db17354e740bba49aee5b36e88e17c40e03ecedfb0aba8435fb4dce33
|
|
7
|
+
data.tar.gz: 3b6a5ab5a22fc430f27cf664107a7b7b26f17fd59661c6768efb839f1988dda8999eac2ba40d2957894a89fd0a0ca0c482cc53274819df70128584ac145e3c87
|
data/Cargo.lock
CHANGED
|
@@ -83,7 +83,7 @@ version = "1.1.5"
|
|
|
83
83
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
84
84
|
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
|
85
85
|
dependencies = [
|
|
86
|
-
"windows-sys 0.
|
|
86
|
+
"windows-sys 0.60.2",
|
|
87
87
|
]
|
|
88
88
|
|
|
89
89
|
[[package]]
|
|
@@ -94,7 +94,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
|
|
94
94
|
dependencies = [
|
|
95
95
|
"anstyle",
|
|
96
96
|
"once_cell_polyfill",
|
|
97
|
-
"windows-sys 0.
|
|
97
|
+
"windows-sys 0.60.2",
|
|
98
98
|
]
|
|
99
99
|
|
|
100
100
|
[[package]]
|
|
@@ -711,7 +711,7 @@ dependencies = [
|
|
|
711
711
|
"libc",
|
|
712
712
|
"option-ext",
|
|
713
713
|
"redox_users",
|
|
714
|
-
"windows-sys 0.
|
|
714
|
+
"windows-sys 0.60.2",
|
|
715
715
|
]
|
|
716
716
|
|
|
717
717
|
[[package]]
|
|
@@ -811,7 +811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
811
811
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
|
812
812
|
dependencies = [
|
|
813
813
|
"libc",
|
|
814
|
-
"windows-sys 0.
|
|
814
|
+
"windows-sys 0.60.2",
|
|
815
815
|
]
|
|
816
816
|
|
|
817
817
|
[[package]]
|
|
@@ -1755,7 +1755,7 @@ version = "0.50.3"
|
|
|
1755
1755
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1756
1756
|
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
|
1757
1757
|
dependencies = [
|
|
1758
|
-
"windows-sys 0.
|
|
1758
|
+
"windows-sys 0.60.2",
|
|
1759
1759
|
]
|
|
1760
1760
|
|
|
1761
1761
|
[[package]]
|
|
@@ -2721,7 +2721,7 @@ dependencies = [
|
|
|
2721
2721
|
"errno",
|
|
2722
2722
|
"libc",
|
|
2723
2723
|
"linux-raw-sys",
|
|
2724
|
-
"windows-sys 0.
|
|
2724
|
+
"windows-sys 0.60.2",
|
|
2725
2725
|
]
|
|
2726
2726
|
|
|
2727
2727
|
[[package]]
|
|
@@ -2780,7 +2780,7 @@ dependencies = [
|
|
|
2780
2780
|
"security-framework",
|
|
2781
2781
|
"security-framework-sys",
|
|
2782
2782
|
"webpki-root-certs",
|
|
2783
|
-
"windows-sys 0.
|
|
2783
|
+
"windows-sys 0.60.2",
|
|
2784
2784
|
]
|
|
2785
2785
|
|
|
2786
2786
|
[[package]]
|
|
@@ -3007,7 +3007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
3007
3007
|
checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
|
|
3008
3008
|
dependencies = [
|
|
3009
3009
|
"libc",
|
|
3010
|
-
"windows-sys 0.
|
|
3010
|
+
"windows-sys 0.60.2",
|
|
3011
3011
|
]
|
|
3012
3012
|
|
|
3013
3013
|
[[package]]
|
|
@@ -3100,7 +3100,7 @@ dependencies = [
|
|
|
3100
3100
|
"getrandom 0.4.2",
|
|
3101
3101
|
"once_cell",
|
|
3102
3102
|
"rustix",
|
|
3103
|
-
"windows-sys 0.
|
|
3103
|
+
"windows-sys 0.60.2",
|
|
3104
3104
|
]
|
|
3105
3105
|
|
|
3106
3106
|
[[package]]
|
|
@@ -3534,9 +3534,9 @@ checksum = "f17aaa1c6e3dc22b1da4b6bba97d066e354c7945cac2f7852d4e4e7ca7a6b56d"
|
|
|
3534
3534
|
|
|
3535
3535
|
[[package]]
|
|
3536
3536
|
name = "tonic"
|
|
3537
|
-
version = "0.14.
|
|
3537
|
+
version = "0.14.6"
|
|
3538
3538
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3539
|
-
checksum = "
|
|
3539
|
+
checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef"
|
|
3540
3540
|
dependencies = [
|
|
3541
3541
|
"async-trait",
|
|
3542
3542
|
"axum",
|
|
@@ -4033,7 +4033,7 @@ version = "0.1.11"
|
|
|
4033
4033
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
4034
4034
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
|
4035
4035
|
dependencies = [
|
|
4036
|
-
"windows-sys 0.
|
|
4036
|
+
"windows-sys 0.60.2",
|
|
4037
4037
|
]
|
|
4038
4038
|
|
|
4039
4039
|
[[package]]
|
data/README.md
CHANGED
|
@@ -1092,6 +1092,63 @@ it will raise the error raised in the activity.
|
|
|
1092
1092
|
The constructor of the environment has multiple keyword arguments that can be set to affect the activity context for the
|
|
1093
1093
|
activity.
|
|
1094
1094
|
|
|
1095
|
+
#### Standalone Activities
|
|
1096
|
+
|
|
1097
|
+
Activities can be started directly from a client, outside the context of any workflow. Standalone activities reuse the
|
|
1098
|
+
existing `Activity::Definition` class — the same activity code runs whether invoked from a workflow or as a standalone
|
|
1099
|
+
activity. They are addressed by `activity_id` (with an optional `activity_run_id` for disambiguating re-runs).
|
|
1100
|
+
|
|
1101
|
+
Start a standalone activity:
|
|
1102
|
+
|
|
1103
|
+
```ruby
|
|
1104
|
+
handle = client.start_activity(
|
|
1105
|
+
MyActivity,
|
|
1106
|
+
'some-arg',
|
|
1107
|
+
id: 'my-activity-id',
|
|
1108
|
+
task_queue: 'my-task-queue',
|
|
1109
|
+
start_to_close_timeout: 60
|
|
1110
|
+
)
|
|
1111
|
+
result = handle.result # blocks until the activity completes
|
|
1112
|
+
```
|
|
1113
|
+
|
|
1114
|
+
Or use the execute helper to start and wait:
|
|
1115
|
+
|
|
1116
|
+
```ruby
|
|
1117
|
+
result = client.execute_activity(
|
|
1118
|
+
MyActivity, 'some-arg',
|
|
1119
|
+
id: 'my-activity-id', task_queue: 'my-task-queue', start_to_close_timeout: 60
|
|
1120
|
+
)
|
|
1121
|
+
```
|
|
1122
|
+
|
|
1123
|
+
Get a handle to an existing standalone activity to describe, cancel, terminate, or fetch its result:
|
|
1124
|
+
|
|
1125
|
+
```ruby
|
|
1126
|
+
handle = client.activity_handle('my-activity-id')
|
|
1127
|
+
description = handle.describe # ActivityExecution::Description
|
|
1128
|
+
result = handle.result # blocks until the activity reaches a terminal state
|
|
1129
|
+
handle.cancel('reason for cancel') # or
|
|
1130
|
+
handle.terminate('reason for terminate')
|
|
1131
|
+
```
|
|
1132
|
+
|
|
1133
|
+
List and count standalone activities (visibility queries):
|
|
1134
|
+
|
|
1135
|
+
```ruby
|
|
1136
|
+
client.list_activities('ActivityType="MyActivity"').each { |exec| puts exec.activity_id }
|
|
1137
|
+
count = client.count_activities('ActivityType="MyActivity"').count
|
|
1138
|
+
```
|
|
1139
|
+
|
|
1140
|
+
Inside an activity body, `Temporalio::Activity::Context.current.info` exposes whether the activity is standalone
|
|
1141
|
+
or workflow-scheduled:
|
|
1142
|
+
|
|
1143
|
+
```ruby
|
|
1144
|
+
info = Temporalio::Activity::Context.current.info
|
|
1145
|
+
if info.in_workflow?
|
|
1146
|
+
# info.workflow_id, info.workflow_run_id, info.workflow_type are set
|
|
1147
|
+
else
|
|
1148
|
+
# info.activity_run_id is set; workflow_* fields are nil
|
|
1149
|
+
end
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1095
1152
|
### Telemetry
|
|
1096
1153
|
|
|
1097
1154
|
#### Metrics
|
|
@@ -155,6 +155,28 @@ module Temporalio
|
|
|
155
155
|
# @return [Object, nil] Result hint
|
|
156
156
|
attr_reader :result_hint
|
|
157
157
|
|
|
158
|
+
# Resolve an activity argument into a `[name, arg_hints, result_hint]` triple. Used by
|
|
159
|
+
# `Client#start_activity` to accept any of: a `Definition` subclass, an instance of one,
|
|
160
|
+
# an `Info`, a `Symbol` activity name, or a `String` activity name. Class/instance/Info
|
|
161
|
+
# inputs carry their definition's hints; Symbol/String inputs return `nil` hints.
|
|
162
|
+
#
|
|
163
|
+
# @param activity [Class<Definition>, Definition, Info, Symbol, String] Activity argument.
|
|
164
|
+
# @return [Array(String, Array[Object]?, Object?)] name, arg_hints, result_hint.
|
|
165
|
+
def self._type_and_hints_from_parameter(activity)
|
|
166
|
+
case activity
|
|
167
|
+
when String, Symbol
|
|
168
|
+
[activity.to_s, nil, nil]
|
|
169
|
+
when Class, Definition, Info
|
|
170
|
+
# Return or construct an Info -- needed because we want the checks in Info.initialize.
|
|
171
|
+
info = from_activity(activity)
|
|
172
|
+
raise ArgumentError, 'Cannot pass dynamic activity to start_activity' unless info.name
|
|
173
|
+
|
|
174
|
+
[info.name.to_s, info.arg_hints, info.result_hint]
|
|
175
|
+
else
|
|
176
|
+
raise ArgumentError, "#{activity} is not an activity class, instance, info, symbol, or string"
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
158
180
|
# Obtain definition info representing the given activity, which can be a class, instance, or definition info.
|
|
159
181
|
#
|
|
160
182
|
# @param activity [Definition, Class<Definition>, Info] Activity to get info for.
|
|
@@ -7,11 +7,13 @@ module Temporalio
|
|
|
7
7
|
module Activity
|
|
8
8
|
Info = Data.define(
|
|
9
9
|
:activity_id,
|
|
10
|
+
:activity_run_id,
|
|
10
11
|
:activity_type,
|
|
11
12
|
:attempt,
|
|
12
13
|
:current_attempt_scheduled_time,
|
|
13
14
|
:heartbeat_timeout,
|
|
14
15
|
:local?,
|
|
16
|
+
:namespace,
|
|
15
17
|
:priority,
|
|
16
18
|
:retry_policy,
|
|
17
19
|
:raw_heartbeat_details,
|
|
@@ -31,16 +33,21 @@ module Temporalio
|
|
|
31
33
|
#
|
|
32
34
|
# @!attribute activity_id
|
|
33
35
|
# @return [String] ID for the activity.
|
|
36
|
+
# @!attribute activity_run_id
|
|
37
|
+
# @return [String, nil] Run ID for a standalone activity execution. nil for activities scheduled from a workflow.
|
|
38
|
+
# WARNING: Standalone Activities are experimental.
|
|
34
39
|
# @!attribute activity_type
|
|
35
40
|
# @return [String] Type name for the activity.
|
|
36
41
|
# @!attribute attempt
|
|
37
|
-
# @return [Integer] Attempt the activity is on.
|
|
42
|
+
# @return [Integer] Attempt the activity is on. Attempts start at 1 and increment on each retry.
|
|
38
43
|
# @!attribute current_attempt_scheduled_time
|
|
39
44
|
# @return [Time] When the current attempt was scheduled.
|
|
40
45
|
# @!attribute heartbeat_timeout
|
|
41
46
|
# @return [Float, nil] Heartbeat timeout set by the caller.
|
|
42
47
|
# @!attribute local?
|
|
43
48
|
# @return [Boolean] Whether the activity is a local activity or not.
|
|
49
|
+
# @!attribute namespace
|
|
50
|
+
# @return [String] Namespace this activity is on.
|
|
44
51
|
# @!attribute priority
|
|
45
52
|
# @return [Priority] The priority of this activity.
|
|
46
53
|
# @!attribute retry_policy
|
|
@@ -64,17 +71,26 @@ module Temporalio
|
|
|
64
71
|
# @return [String] Task token uniquely identifying this activity. Note, this is a `ASCII-8BIT` encoded string, not
|
|
65
72
|
# a `UTF-8` encoded string nor a valid UTF-8 string.
|
|
66
73
|
# @!attribute workflow_id
|
|
67
|
-
# @return [String] Workflow ID that started this activity.
|
|
74
|
+
# @return [String, nil] Workflow ID that started this activity. nil for standalone activities.
|
|
68
75
|
# @!attribute workflow_namespace
|
|
69
|
-
# @return [String] Namespace this activity
|
|
76
|
+
# @return [String, nil] Namespace of the workflow that scheduled this activity. Nil for standalone
|
|
77
|
+
# activities. Prefer {#namespace}, which is always set.
|
|
78
|
+
# @deprecated Use {#namespace} instead.
|
|
70
79
|
# @!attribute workflow_run_id
|
|
71
|
-
# @return [String] Workflow run ID that started this activity.
|
|
80
|
+
# @return [String, nil] Workflow run ID that started this activity. nil for standalone activities.
|
|
72
81
|
# @!attribute workflow_type
|
|
73
|
-
# @return [String] Workflow type name that started this activity.
|
|
82
|
+
# @return [String, nil] Workflow type name that started this activity. nil for standalone activities.
|
|
74
83
|
#
|
|
75
84
|
# @note WARNING: This class may have required parameters added to its constructor. Users should not instantiate this
|
|
76
85
|
# class or it may break in incompatible ways.
|
|
77
86
|
class Info
|
|
87
|
+
# @return [Boolean] True if this activity was scheduled by a workflow execution; false for standalone activities.
|
|
88
|
+
#
|
|
89
|
+
# WARNING: Standalone Activities are experimental.
|
|
90
|
+
def in_workflow?
|
|
91
|
+
!workflow_id.nil?
|
|
92
|
+
end
|
|
93
|
+
|
|
78
94
|
# Convert raw heartbeat details into Ruby types.
|
|
79
95
|
#
|
|
80
96
|
# Note, this live-converts every invocation.
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'temporalio/api'
|
|
4
|
+
require 'temporalio/client/activity_execution_status'
|
|
5
|
+
require 'temporalio/client/pending_activity_state'
|
|
6
|
+
require 'temporalio/internal/proto_utils'
|
|
7
|
+
require 'temporalio/priority'
|
|
8
|
+
require 'temporalio/retry_policy'
|
|
9
|
+
require 'temporalio/search_attributes'
|
|
10
|
+
require 'temporalio/worker_deployment_version'
|
|
11
|
+
|
|
12
|
+
module Temporalio
|
|
13
|
+
class Client
|
|
14
|
+
# Info for a standalone activity execution. Returned by list_activities; extended by {Description}
|
|
15
|
+
# for describe results.
|
|
16
|
+
#
|
|
17
|
+
# WARNING: Standalone Activities are experimental.
|
|
18
|
+
class ActivityExecution
|
|
19
|
+
# @return [Api::Activity::V1::ActivityExecutionListInfo, Api::Activity::V1::ActivityExecutionInfo]
|
|
20
|
+
# Underlying protobuf info.
|
|
21
|
+
attr_reader :raw_info
|
|
22
|
+
|
|
23
|
+
# @!visibility private
|
|
24
|
+
def initialize(raw_info)
|
|
25
|
+
@raw_info = raw_info
|
|
26
|
+
@search_attributes = Internal::ProtoUtils::LazySearchAttributes.new(raw_info.search_attributes)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @return [String] ID for the activity.
|
|
30
|
+
def activity_id
|
|
31
|
+
@raw_info.activity_id
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @return [String] Run ID for this activity execution attempt.
|
|
35
|
+
def activity_run_id
|
|
36
|
+
Internal::ProtoUtils.string_or(@raw_info.run_id, nil)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @return [String] Type name of the activity.
|
|
40
|
+
def activity_type
|
|
41
|
+
@raw_info.activity_type&.name
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Time, nil] When the activity was scheduled.
|
|
45
|
+
def schedule_time
|
|
46
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.schedule_time)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @return [Time, nil] When the activity reached a terminal state.
|
|
50
|
+
def close_time
|
|
51
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.close_time)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @return [ActivityExecutionStatus] Overall status for the activity.
|
|
55
|
+
def status
|
|
56
|
+
Internal::ProtoUtils.enum_to_int(Api::Enums::V1::ActivityExecutionStatus, @raw_info.status)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @return [SearchAttributes, nil] Search attributes attached to this activity if any.
|
|
60
|
+
def search_attributes
|
|
61
|
+
@search_attributes.get
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [String] Task queue for the activity.
|
|
65
|
+
def task_queue
|
|
66
|
+
@raw_info.task_queue
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @return [Float, nil] How long this activity has been running across all attempts, in seconds.
|
|
70
|
+
def execution_duration
|
|
71
|
+
Internal::ProtoUtils.duration_to_seconds(@raw_info.execution_duration)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Rich description of a standalone activity execution; returned by {ActivityHandle#describe}.
|
|
75
|
+
#
|
|
76
|
+
# WARNING: Standalone Activities are experimental.
|
|
77
|
+
class Description < ActivityExecution
|
|
78
|
+
# @return [Api::WorkflowService::V1::DescribeActivityExecutionResponse] Underlying protobuf response.
|
|
79
|
+
attr_reader :raw_description
|
|
80
|
+
|
|
81
|
+
# @!visibility private
|
|
82
|
+
def initialize(raw_description, data_converter)
|
|
83
|
+
super(raw_description.info)
|
|
84
|
+
@raw_description = raw_description
|
|
85
|
+
@data_converter = data_converter
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# @return [PendingActivityState, nil] More detailed breakdown of the running state when
|
|
89
|
+
# the activity's status is RUNNING; nil otherwise.
|
|
90
|
+
def run_state
|
|
91
|
+
Internal::ProtoUtils.enum_to_int(Api::Enums::V1::PendingActivityState, @raw_info.run_state,
|
|
92
|
+
zero_means_nil: true)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @return [Float, nil] Schedule-to-close timeout in seconds.
|
|
96
|
+
def schedule_to_close_timeout
|
|
97
|
+
Internal::ProtoUtils.duration_to_seconds(@raw_info.schedule_to_close_timeout)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @return [Float, nil] Schedule-to-start timeout in seconds.
|
|
101
|
+
def schedule_to_start_timeout
|
|
102
|
+
Internal::ProtoUtils.duration_to_seconds(@raw_info.schedule_to_start_timeout)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# @return [Float, nil] Start-to-close timeout in seconds.
|
|
106
|
+
def start_to_close_timeout
|
|
107
|
+
Internal::ProtoUtils.duration_to_seconds(@raw_info.start_to_close_timeout)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# @return [Float, nil] Heartbeat timeout in seconds.
|
|
111
|
+
def heartbeat_timeout
|
|
112
|
+
Internal::ProtoUtils.duration_to_seconds(@raw_info.heartbeat_timeout)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @return [Boolean] Whether the activity has recorded any heartbeat details.
|
|
116
|
+
def has_heartbeat_details? # rubocop:disable Naming/PredicatePrefix
|
|
117
|
+
!@raw_info.heartbeat_details&.payloads.nil? && !@raw_info.heartbeat_details.payloads.empty?
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Deserialized last-heartbeat details. Empty when no heartbeat has been recorded.
|
|
121
|
+
#
|
|
122
|
+
# @param hints [Array<Object>, nil] Hints, if any, to assist conversion.
|
|
123
|
+
# @return [Array<Object>] Converted details.
|
|
124
|
+
def heartbeat_details(hints: nil)
|
|
125
|
+
@data_converter.from_payloads(@raw_info.heartbeat_details, hints:)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# @return [RetryPolicy] Retry policy in effect for this activity.
|
|
129
|
+
def retry_policy
|
|
130
|
+
RetryPolicy._from_proto(@raw_info.retry_policy)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# @return [Time, nil] Time the last heartbeat was recorded.
|
|
134
|
+
def last_heartbeat_time
|
|
135
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.last_heartbeat_time)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# @return [Time, nil] Time the last attempt started.
|
|
139
|
+
def last_started_time
|
|
140
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.last_started_time)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# @return [Integer] Current attempt number. Attempts start at 1 and increment on each retry.
|
|
144
|
+
def attempt
|
|
145
|
+
@raw_info.attempt
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# @return [Error::Failure, nil] Failure of the last failed attempt if any.
|
|
149
|
+
def last_failure
|
|
150
|
+
return nil unless @raw_info.last_failure
|
|
151
|
+
|
|
152
|
+
@data_converter.from_failure(@raw_info.last_failure)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# @return [Time, nil] Schedule time + schedule-to-close timeout.
|
|
156
|
+
def expiration_time
|
|
157
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.expiration_time)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# @return [String, nil] Identity of the worker that last picked up this activity.
|
|
161
|
+
def last_worker_identity
|
|
162
|
+
Internal::ProtoUtils.string_or(@raw_info.last_worker_identity, nil)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# @return [Float, nil] Time from last attempt failure to next retry, in seconds.
|
|
166
|
+
def current_retry_interval
|
|
167
|
+
Internal::ProtoUtils.duration_to_seconds(@raw_info.current_retry_interval)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# @return [Time, nil] Time when the last attempt completed.
|
|
171
|
+
def last_attempt_complete_time
|
|
172
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.last_attempt_complete_time)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# @return [Time, nil] Time when the next attempt will be scheduled.
|
|
176
|
+
def next_attempt_schedule_time
|
|
177
|
+
Internal::ProtoUtils.timestamp_to_time(@raw_info.next_attempt_schedule_time)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# @return [WorkerDeploymentVersion, nil] Worker deployment version this activity was last dispatched to.
|
|
181
|
+
def last_deployment_version
|
|
182
|
+
raw = @raw_info.last_deployment_version
|
|
183
|
+
return nil unless raw
|
|
184
|
+
|
|
185
|
+
WorkerDeploymentVersion.new(
|
|
186
|
+
deployment_name: raw.deployment_name,
|
|
187
|
+
build_id: raw.build_id
|
|
188
|
+
)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# @return [Priority] Priority of this activity.
|
|
192
|
+
def priority
|
|
193
|
+
Priority._from_proto(@raw_info.priority)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# @return [String, nil] Reason given when cancellation was requested.
|
|
197
|
+
def canceled_reason
|
|
198
|
+
Internal::ProtoUtils.string_or(@raw_info.canceled_reason, nil)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# @return [String, nil] Static user-metadata summary on the activity.
|
|
202
|
+
def static_summary
|
|
203
|
+
user_metadata.first
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# @return [String, nil] Static user-metadata details on the activity. May be in markdown format.
|
|
207
|
+
def static_details
|
|
208
|
+
user_metadata.last
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
private
|
|
212
|
+
|
|
213
|
+
def user_metadata
|
|
214
|
+
@user_metadata ||= Internal::ProtoUtils.from_user_metadata(
|
|
215
|
+
@raw_info.user_metadata, @data_converter
|
|
216
|
+
)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Temporalio
|
|
4
|
+
class Client
|
|
5
|
+
# Result of a {Client#count_activities} call.
|
|
6
|
+
#
|
|
7
|
+
# WARNING: Standalone Activities are experimental.
|
|
8
|
+
class ActivityExecutionCount
|
|
9
|
+
# @return [Integer] Approximate number of activities matching the query. If the query had a group-by clause,
|
|
10
|
+
# this is the sum of all the counts in {groups}.
|
|
11
|
+
attr_reader :count
|
|
12
|
+
|
|
13
|
+
# @return [Array<AggregationGroup>] Groups if the query had a group-by clause, or empty if not.
|
|
14
|
+
attr_reader :groups
|
|
15
|
+
|
|
16
|
+
# @!visibility private
|
|
17
|
+
def initialize(count, groups)
|
|
18
|
+
@count = count
|
|
19
|
+
@groups = groups
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Aggregation group if the activity count query had a group-by clause.
|
|
23
|
+
#
|
|
24
|
+
# WARNING: Standalone Activities are experimental.
|
|
25
|
+
class AggregationGroup
|
|
26
|
+
# @return [Integer] Approximate number of activities matching the query for this group.
|
|
27
|
+
attr_reader :count
|
|
28
|
+
|
|
29
|
+
# @return [Array<Object>] Search attribute values for this group.
|
|
30
|
+
attr_reader :group_values
|
|
31
|
+
|
|
32
|
+
# @!visibility private
|
|
33
|
+
def initialize(count, group_values)
|
|
34
|
+
@count = count
|
|
35
|
+
@group_values = group_values
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'temporalio/api'
|
|
4
|
+
|
|
5
|
+
module Temporalio
|
|
6
|
+
class Client
|
|
7
|
+
# Status of a standalone activity execution.
|
|
8
|
+
#
|
|
9
|
+
# WARNING: Standalone Activities are experimental.
|
|
10
|
+
module ActivityExecutionStatus
|
|
11
|
+
UNSPECIFIED = Api::Enums::V1::ActivityExecutionStatus::ACTIVITY_EXECUTION_STATUS_UNSPECIFIED
|
|
12
|
+
RUNNING = Api::Enums::V1::ActivityExecutionStatus::ACTIVITY_EXECUTION_STATUS_RUNNING
|
|
13
|
+
COMPLETED = Api::Enums::V1::ActivityExecutionStatus::ACTIVITY_EXECUTION_STATUS_COMPLETED
|
|
14
|
+
FAILED = Api::Enums::V1::ActivityExecutionStatus::ACTIVITY_EXECUTION_STATUS_FAILED
|
|
15
|
+
CANCELED = Api::Enums::V1::ActivityExecutionStatus::ACTIVITY_EXECUTION_STATUS_CANCELED
|
|
16
|
+
TERMINATED = Api::Enums::V1::ActivityExecutionStatus::ACTIVITY_EXECUTION_STATUS_TERMINATED
|
|
17
|
+
TIMED_OUT = Api::Enums::V1::ActivityExecutionStatus::ACTIVITY_EXECUTION_STATUS_TIMED_OUT
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'temporalio/api'
|
|
4
|
+
require 'temporalio/client/activity_execution'
|
|
5
|
+
require 'temporalio/client/interceptor'
|
|
6
|
+
require 'temporalio/error'
|
|
7
|
+
|
|
8
|
+
module Temporalio
|
|
9
|
+
class Client
|
|
10
|
+
# Handle for interacting with a standalone activity. Usually created via {Client.activity_handle}
|
|
11
|
+
# or {Client#start_activity}.
|
|
12
|
+
#
|
|
13
|
+
# WARNING: Standalone Activities are experimental.
|
|
14
|
+
class ActivityHandle
|
|
15
|
+
# @return [String] ID for the activity.
|
|
16
|
+
attr_reader :id
|
|
17
|
+
|
|
18
|
+
# @return [String, nil] Run ID for this activity execution. When nil, this handle targets the latest run.
|
|
19
|
+
attr_reader :run_id
|
|
20
|
+
|
|
21
|
+
# @return [Object, nil] Result hint used when deserializing the activity's result. May be overridden per
|
|
22
|
+
# {#result} call.
|
|
23
|
+
attr_reader :result_hint
|
|
24
|
+
|
|
25
|
+
# @!visibility private
|
|
26
|
+
def initialize(client:, id:, run_id:, result_hint:)
|
|
27
|
+
@client = client
|
|
28
|
+
@id = id
|
|
29
|
+
@run_id = run_id
|
|
30
|
+
@result_hint = result_hint
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Wait for the activity's outcome (result or failure). Internally long-polls
|
|
34
|
+
# PollActivityExecution and reissues until the activity reaches a terminal state, so this can
|
|
35
|
+
# block indefinitely for long-running activities.
|
|
36
|
+
#
|
|
37
|
+
# @param result_hint [Object, nil] Override the result hint. If nil, uses {#result_hint}.
|
|
38
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
|
39
|
+
#
|
|
40
|
+
# @return [Object, nil] Deserialized activity result.
|
|
41
|
+
#
|
|
42
|
+
# @raise [Error::ActivityFailedError] With `cause` populated from the activity failure.
|
|
43
|
+
# @raise [Error::RPCError] RPC error from call.
|
|
44
|
+
def result(result_hint: nil, rpc_options: nil)
|
|
45
|
+
hint = result_hint || @result_hint
|
|
46
|
+
outcome = @client._impl.fetch_activity_outcome(
|
|
47
|
+
Interceptor::FetchActivityOutcomeInput.new(
|
|
48
|
+
activity_id: id,
|
|
49
|
+
activity_run_id: run_id,
|
|
50
|
+
rpc_options:
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
_process_outcome(outcome, hint)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Describe the activity.
|
|
57
|
+
#
|
|
58
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
|
59
|
+
#
|
|
60
|
+
# @return [ActivityExecution::Description] Activity description.
|
|
61
|
+
# @raise [Error::RPCError] RPC error from call.
|
|
62
|
+
def describe(rpc_options: nil)
|
|
63
|
+
@client._impl.describe_activity(
|
|
64
|
+
Interceptor::DescribeActivityInput.new(
|
|
65
|
+
activity_id: id,
|
|
66
|
+
activity_run_id: run_id,
|
|
67
|
+
rpc_options:
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Request cancellation of the activity.
|
|
73
|
+
#
|
|
74
|
+
# @param reason [String, nil] Optional cancellation reason recorded on the server.
|
|
75
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
|
76
|
+
# @raise [Error::RPCError] RPC error from call.
|
|
77
|
+
def cancel(reason = nil, rpc_options: nil)
|
|
78
|
+
@client._impl.cancel_activity(
|
|
79
|
+
Interceptor::CancelActivityInput.new(
|
|
80
|
+
activity_id: id,
|
|
81
|
+
activity_run_id: run_id,
|
|
82
|
+
reason:,
|
|
83
|
+
rpc_options:
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
nil
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Terminate the activity (force-close).
|
|
90
|
+
#
|
|
91
|
+
# @param reason [String, nil] Optional termination reason recorded on the activity's failure outcome.
|
|
92
|
+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
|
|
93
|
+
# @raise [Error::RPCError] RPC error from call.
|
|
94
|
+
def terminate(reason = nil, rpc_options: nil)
|
|
95
|
+
@client._impl.terminate_activity(
|
|
96
|
+
Interceptor::TerminateActivityInput.new(
|
|
97
|
+
activity_id: id,
|
|
98
|
+
activity_run_id: run_id,
|
|
99
|
+
reason:,
|
|
100
|
+
rpc_options:
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
nil
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def _process_outcome(outcome, hint)
|
|
109
|
+
raise Error, 'Activity completed but outcome is missing from server response' if outcome.nil?
|
|
110
|
+
|
|
111
|
+
case outcome.value
|
|
112
|
+
when :failure
|
|
113
|
+
cause = @client.data_converter.from_failure(outcome.failure)
|
|
114
|
+
raise Error::ActivityFailedError.new, cause: cause
|
|
115
|
+
when :result
|
|
116
|
+
@client.data_converter.from_payloads(outcome.result, hints: Array(hint)).first
|
|
117
|
+
else
|
|
118
|
+
raise Error, "Unknown activity outcome: #{outcome.value.inspect}"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|