@temporalio/core-bridge 0.16.4 → 0.18.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.
Files changed (170) hide show
  1. package/Cargo.lock +339 -226
  2. package/Cargo.toml +7 -3
  3. package/common.js +50 -0
  4. package/index.d.ts +7 -0
  5. package/index.js +12 -0
  6. package/package.json +7 -4
  7. package/releases/aarch64-apple-darwin/index.node +0 -0
  8. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  9. package/{index.node → releases/index.node} +0 -0
  10. package/releases/x86_64-apple-darwin/index.node +0 -0
  11. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  12. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  13. package/scripts/build.js +10 -50
  14. package/sdk-core/.buildkite/docker/Dockerfile +1 -1
  15. package/sdk-core/.buildkite/docker/docker-compose.yaml +2 -2
  16. package/sdk-core/.buildkite/pipeline.yml +2 -0
  17. package/sdk-core/Cargo.toml +1 -88
  18. package/sdk-core/README.md +30 -6
  19. package/sdk-core/bridge-ffi/Cargo.toml +24 -0
  20. package/sdk-core/bridge-ffi/LICENSE.txt +23 -0
  21. package/sdk-core/bridge-ffi/build.rs +25 -0
  22. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +216 -0
  23. package/sdk-core/bridge-ffi/src/lib.rs +829 -0
  24. package/sdk-core/bridge-ffi/src/wrappers.rs +193 -0
  25. package/sdk-core/client/Cargo.toml +32 -0
  26. package/sdk-core/{src/pollers/gateway.rs → client/src/lib.rs} +101 -195
  27. package/sdk-core/client/src/metrics.rs +89 -0
  28. package/sdk-core/client/src/mocks.rs +167 -0
  29. package/sdk-core/{src/pollers → client/src}/retry.rs +172 -14
  30. package/sdk-core/core/Cargo.toml +96 -0
  31. package/sdk-core/{src → core/src}/core_tests/activity_tasks.rs +193 -37
  32. package/sdk-core/{src → core/src}/core_tests/child_workflows.rs +14 -14
  33. package/sdk-core/{src → core/src}/core_tests/determinism.rs +8 -8
  34. package/sdk-core/core/src/core_tests/local_activities.rs +328 -0
  35. package/sdk-core/{src → core/src}/core_tests/mod.rs +6 -9
  36. package/sdk-core/{src → core/src}/core_tests/queries.rs +54 -54
  37. package/sdk-core/{src → core/src}/core_tests/replay_flag.rs +8 -12
  38. package/sdk-core/{src → core/src}/core_tests/workers.rs +120 -33
  39. package/sdk-core/{src → core/src}/core_tests/workflow_cancels.rs +16 -26
  40. package/sdk-core/{src → core/src}/core_tests/workflow_tasks.rs +280 -292
  41. package/sdk-core/core/src/lib.rs +374 -0
  42. package/sdk-core/{src → core/src}/log_export.rs +3 -27
  43. package/sdk-core/core/src/pending_activations.rs +162 -0
  44. package/sdk-core/{src → core/src}/pollers/mod.rs +4 -22
  45. package/sdk-core/{src → core/src}/pollers/poll_buffer.rs +1 -1
  46. package/sdk-core/core/src/protosext/mod.rs +396 -0
  47. package/sdk-core/core/src/replay/mod.rs +210 -0
  48. package/sdk-core/core/src/retry_logic.rs +144 -0
  49. package/sdk-core/{src → core/src}/telemetry/metrics.rs +3 -58
  50. package/sdk-core/{src → core/src}/telemetry/mod.rs +8 -8
  51. package/sdk-core/{src → core/src}/telemetry/prometheus_server.rs +0 -0
  52. package/sdk-core/{src → core/src}/test_help/mod.rs +35 -83
  53. package/sdk-core/{src → core/src}/worker/activities/activity_heartbeat_manager.rs +95 -42
  54. package/sdk-core/core/src/worker/activities/local_activities.rs +973 -0
  55. package/sdk-core/{src → core/src}/worker/activities.rs +52 -33
  56. package/sdk-core/{src → core/src}/worker/dispatcher.rs +8 -6
  57. package/sdk-core/{src → core/src}/worker/mod.rs +347 -221
  58. package/sdk-core/core/src/worker/wft_delivery.rs +81 -0
  59. package/sdk-core/{src → core/src}/workflow/bridge.rs +5 -2
  60. package/sdk-core/{src → core/src}/workflow/driven_workflow.rs +17 -7
  61. package/sdk-core/{src → core/src}/workflow/history_update.rs +33 -7
  62. package/sdk-core/{src → core/src/workflow}/machines/activity_state_machine.rs +26 -26
  63. package/sdk-core/{src → core/src/workflow}/machines/cancel_external_state_machine.rs +8 -11
  64. package/sdk-core/{src → core/src/workflow}/machines/cancel_workflow_state_machine.rs +19 -21
  65. package/sdk-core/{src → core/src/workflow}/machines/child_workflow_state_machine.rs +20 -31
  66. package/sdk-core/{src → core/src/workflow}/machines/complete_workflow_state_machine.rs +3 -5
  67. package/sdk-core/{src → core/src/workflow}/machines/continue_as_new_workflow_state_machine.rs +18 -18
  68. package/sdk-core/{src → core/src/workflow}/machines/fail_workflow_state_machine.rs +5 -6
  69. package/sdk-core/core/src/workflow/machines/local_activity_state_machine.rs +1451 -0
  70. package/sdk-core/{src → core/src/workflow}/machines/mod.rs +54 -107
  71. package/sdk-core/{src → core/src/workflow}/machines/mutable_side_effect_state_machine.rs +0 -0
  72. package/sdk-core/{src → core/src/workflow}/machines/patch_state_machine.rs +29 -30
  73. package/sdk-core/{src → core/src/workflow}/machines/side_effect_state_machine.rs +0 -0
  74. package/sdk-core/{src → core/src/workflow}/machines/signal_external_state_machine.rs +17 -19
  75. package/sdk-core/{src → core/src/workflow}/machines/timer_state_machine.rs +20 -21
  76. package/sdk-core/{src → core/src/workflow}/machines/transition_coverage.rs +5 -2
  77. package/sdk-core/{src → core/src/workflow}/machines/upsert_search_attributes_state_machine.rs +0 -0
  78. package/sdk-core/core/src/workflow/machines/workflow_machines/local_acts.rs +96 -0
  79. package/sdk-core/{src → core/src/workflow}/machines/workflow_machines.rs +357 -171
  80. package/sdk-core/{src → core/src/workflow}/machines/workflow_task_state_machine.rs +1 -1
  81. package/sdk-core/{src → core/src}/workflow/mod.rs +200 -39
  82. package/sdk-core/{src → core/src}/workflow/workflow_tasks/cache_manager.rs +0 -0
  83. package/sdk-core/{src → core/src}/workflow/workflow_tasks/concurrency_manager.rs +38 -5
  84. package/sdk-core/{src → core/src}/workflow/workflow_tasks/mod.rs +317 -103
  85. package/sdk-core/{test_utils → core-api}/Cargo.toml +10 -7
  86. package/sdk-core/{src → core-api/src}/errors.rs +42 -92
  87. package/sdk-core/core-api/src/lib.rs +158 -0
  88. package/sdk-core/{src/worker/config.rs → core-api/src/worker.rs} +18 -23
  89. package/sdk-core/etc/deps.svg +156 -0
  90. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +5 -5
  91. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +3 -5
  92. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +7 -1
  93. package/sdk-core/histories/fail_wf_task.bin +0 -0
  94. package/sdk-core/histories/timer_workflow_history.bin +0 -0
  95. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +44 -13
  96. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +19 -1
  97. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +1 -1
  98. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +9 -0
  99. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +1 -0
  100. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +1 -0
  101. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +13 -0
  102. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +14 -7
  103. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +176 -18
  104. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
  105. package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +11 -0
  106. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +3 -0
  107. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +156 -7
  108. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +135 -104
  109. package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
  110. package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +78 -0
  111. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +205 -0
  112. package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +61 -0
  113. package/sdk-core/protos/local/{child_workflow.proto → temporal/sdk/core/child_workflow/child_workflow.proto} +1 -1
  114. package/sdk-core/protos/local/{common.proto → temporal/sdk/core/common/common.proto} +5 -3
  115. package/sdk-core/protos/local/{core_interface.proto → temporal/sdk/core/core_interface.proto} +10 -10
  116. package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
  117. package/sdk-core/protos/local/{workflow_activation.proto → temporal/sdk/core/workflow_activation/workflow_activation.proto} +35 -11
  118. package/sdk-core/protos/local/{workflow_commands.proto → temporal/sdk/core/workflow_commands/workflow_commands.proto} +55 -4
  119. package/sdk-core/protos/local/{workflow_completion.proto → temporal/sdk/core/workflow_completion/workflow_completion.proto} +3 -3
  120. package/sdk-core/sdk/Cargo.toml +32 -0
  121. package/sdk-core/{src/prototype_rust_sdk → sdk/src}/conversions.rs +0 -0
  122. package/sdk-core/sdk/src/lib.rs +699 -0
  123. package/sdk-core/sdk/src/payload_converter.rs +11 -0
  124. package/sdk-core/sdk/src/workflow_context/options.rs +180 -0
  125. package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_context.rs +201 -124
  126. package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_future.rs +63 -30
  127. package/sdk-core/sdk-core-protos/Cargo.toml +10 -0
  128. package/sdk-core/sdk-core-protos/build.rs +28 -6
  129. package/sdk-core/sdk-core-protos/src/constants.rs +7 -0
  130. package/sdk-core/{src/test_help → sdk-core-protos/src}/history_builder.rs +134 -49
  131. package/sdk-core/sdk-core-protos/src/history_info.rs +216 -0
  132. package/sdk-core/sdk-core-protos/src/lib.rs +601 -168
  133. package/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
  134. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  135. package/sdk-core/test-utils/Cargo.toml +32 -0
  136. package/sdk-core/{src/test_help → test-utils/src}/canned_histories.rs +59 -78
  137. package/sdk-core/test-utils/src/histfetch.rs +28 -0
  138. package/sdk-core/{test_utils → test-utils}/src/lib.rs +131 -68
  139. package/sdk-core/tests/integ_tests/client_tests.rs +1 -1
  140. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +11 -7
  141. package/sdk-core/tests/integ_tests/polling_tests.rs +12 -11
  142. package/sdk-core/tests/integ_tests/queries_tests.rs +82 -78
  143. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +91 -71
  144. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +3 -4
  145. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +2 -4
  146. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -6
  147. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +4 -6
  148. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -4
  149. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +496 -0
  150. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +5 -8
  151. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +125 -0
  152. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +7 -13
  153. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +33 -5
  154. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +12 -16
  155. package/sdk-core/tests/integ_tests/workflow_tests.rs +85 -82
  156. package/sdk-core/tests/load_tests.rs +6 -6
  157. package/sdk-core/tests/main.rs +2 -2
  158. package/src/conversions.rs +24 -21
  159. package/src/errors.rs +8 -0
  160. package/src/lib.rs +323 -211
  161. package/sdk-core/protos/local/activity_result.proto +0 -46
  162. package/sdk-core/protos/local/activity_task.proto +0 -66
  163. package/sdk-core/src/core_tests/retry.rs +0 -147
  164. package/sdk-core/src/lib.rs +0 -403
  165. package/sdk-core/src/machines/local_activity_state_machine.rs +0 -117
  166. package/sdk-core/src/pending_activations.rs +0 -249
  167. package/sdk-core/src/protosext/mod.rs +0 -160
  168. package/sdk-core/src/prototype_rust_sdk.rs +0 -412
  169. package/sdk-core/src/task_token.rs +0 -20
  170. package/sdk-core/src/test_help/history_info.rs +0 -157
@@ -2,6 +2,21 @@
2
2
  //! the Temporal Core SDK. Language SDK authors can generate structs using the proto definitions
3
3
  //! that will match the generated structs in this module.
4
4
 
5
+ pub mod constants;
6
+ pub mod utilities;
7
+
8
+ #[cfg(feature = "history_builders")]
9
+ mod history_builder;
10
+ #[cfg(feature = "history_builders")]
11
+ mod history_info;
12
+ mod task_token;
13
+
14
+ #[cfg(feature = "history_builders")]
15
+ pub use history_builder::{default_wes_attribs, TestHistoryBuilder, DEFAULT_WORKFLOW_TYPE};
16
+ #[cfg(feature = "history_builders")]
17
+ pub use history_info::HistoryInfo;
18
+ pub use task_token::TaskToken;
19
+
5
20
  #[allow(clippy::large_enum_variant)]
6
21
  // I'd prefer not to do this, but there are some generated things that just don't need it.
7
22
  #[allow(missing_docs)]
@@ -15,32 +30,27 @@ pub mod coresdk {
15
30
  failure::v1::{failure::FailureInfo, ApplicationFailureInfo, Failure},
16
31
  workflowservice::v1::PollActivityTaskQueueResponse,
17
32
  };
18
- use activity_result::ActivityResult;
19
33
  use activity_task::ActivityTask;
20
34
  use common::Payload;
35
+ use serde::{Deserialize, Serialize};
21
36
  use std::{
22
37
  collections::HashMap,
23
38
  convert::TryFrom,
24
39
  fmt::{Display, Formatter},
25
40
  iter::FromIterator,
26
41
  };
27
- use workflow_activation::{wf_activation_job, WfActivationJob};
42
+ use workflow_activation::{workflow_activation_job, WorkflowActivationJob};
28
43
  use workflow_commands::{workflow_command, workflow_command::Variant, WorkflowCommand};
29
- use workflow_completion::{wf_activation_completion, WfActivationCompletion};
44
+ use workflow_completion::{workflow_activation_completion, WorkflowActivationCompletion};
30
45
 
31
46
  #[allow(clippy::module_inception)]
32
47
  pub mod activity_task {
33
48
  tonic::include_proto!("coresdk.activity_task");
34
49
 
35
50
  impl ActivityTask {
36
- pub fn cancel_from_ids(
37
- task_token: Vec<u8>,
38
- activity_id: String,
39
- reason: ActivityCancelReason,
40
- ) -> Self {
51
+ pub fn cancel_from_ids(task_token: Vec<u8>, reason: ActivityCancelReason) -> Self {
41
52
  Self {
42
53
  task_token,
43
- activity_id,
44
54
  variant: Some(activity_task::Variant::Cancel(Cancel {
45
55
  reason: reason as i32,
46
56
  })),
@@ -52,41 +62,134 @@ pub mod coresdk {
52
62
  pub mod activity_result {
53
63
  tonic::include_proto!("coresdk.activity_result");
54
64
  use super::{
55
- super::temporal::api::failure::v1::{
56
- failure, CanceledFailureInfo, Failure as APIFailure,
65
+ super::temporal::api::{
66
+ common::v1::Payload as APIPayload,
67
+ failure::v1::{failure, CanceledFailureInfo, Failure as APIFailure},
57
68
  },
58
69
  common::Payload,
59
70
  };
71
+ use crate::temporal::api::{enums::v1::TimeoutType, failure::v1::TimeoutFailureInfo};
72
+ use activity_execution_result as aer;
60
73
 
61
- impl ActivityResult {
62
- pub fn cancel_from_details(payload: Option<Payload>) -> Self {
74
+ impl ActivityExecutionResult {
75
+ pub const fn ok(result: Payload) -> Self {
63
76
  Self {
64
- status: Some(activity_result::Status::Cancelled(Cancellation {
65
- failure: Some(APIFailure {
66
- // CanceledFailure
67
- message: "Activity cancelled".to_string(),
68
- failure_info: Some(failure::FailureInfo::CanceledFailureInfo(
69
- CanceledFailureInfo {
70
- details: payload.map(Into::into),
71
- },
72
- )),
73
- ..Default::default()
74
- }),
77
+ status: Some(aer::Status::Completed(Success {
78
+ result: Some(result),
79
+ })),
80
+ }
81
+ }
82
+
83
+ pub fn fail(fail: APIFailure) -> Self {
84
+ Self {
85
+ status: Some(aer::Status::Failed(Failure {
86
+ failure: Some(fail),
75
87
  })),
76
88
  }
77
89
  }
90
+
91
+ pub fn cancel_from_details(payload: Option<Payload>) -> Self {
92
+ Self {
93
+ status: Some(aer::Status::Cancelled(Cancellation::from_details(payload))),
94
+ }
95
+ }
96
+
78
97
  pub const fn will_complete_async() -> Self {
79
98
  Self {
80
- status: Some(activity_result::Status::WillCompleteAsync(
81
- WillCompleteAsync {},
82
- )),
99
+ status: Some(aer::Status::WillCompleteAsync(WillCompleteAsync {})),
83
100
  }
84
101
  }
102
+
103
+ pub fn is_cancelled(&self) -> bool {
104
+ matches!(self.status, Some(aer::Status::Cancelled(_)))
105
+ }
85
106
  }
107
+
108
+ impl From<Result<APIPayload, APIFailure>> for ActivityExecutionResult {
109
+ fn from(r: Result<APIPayload, APIFailure>) -> Self {
110
+ Self {
111
+ status: match r {
112
+ Ok(p) => Some(aer::Status::Completed(Success {
113
+ result: Some(p.into()),
114
+ })),
115
+ Err(f) => Some(aer::Status::Failed(Failure { failure: Some(f) })),
116
+ },
117
+ }
118
+ }
119
+ }
120
+
121
+ impl ActivityResolution {
122
+ pub fn unwrap_ok_payload(self) -> Payload {
123
+ match self.status.unwrap() {
124
+ activity_resolution::Status::Completed(c) => c.result.unwrap(),
125
+ _ => panic!("Activity was not successful"),
126
+ }
127
+ }
128
+
129
+ pub fn completed_ok(&self) -> bool {
130
+ matches!(self.status, Some(activity_resolution::Status::Completed(_)))
131
+ }
132
+
133
+ pub fn failed(&self) -> bool {
134
+ matches!(self.status, Some(activity_resolution::Status::Failed(_)))
135
+ }
136
+
137
+ pub fn timed_out(&self) -> bool {
138
+ matches!(self.status, Some(activity_resolution::Status::Failed(Failure {
139
+ failure: Some(ref f)
140
+ })) if f.is_timeout())
141
+ }
142
+
143
+ pub fn cancelled(&self) -> bool {
144
+ matches!(self.status, Some(activity_resolution::Status::Cancelled(_)))
145
+ }
146
+ }
147
+
148
+ impl Cancellation {
149
+ pub fn from_details(payload: Option<Payload>) -> Self {
150
+ Cancellation {
151
+ failure: Some(APIFailure {
152
+ message: "Activity cancelled".to_string(),
153
+ failure_info: Some(failure::FailureInfo::CanceledFailureInfo(
154
+ CanceledFailureInfo {
155
+ details: payload.map(Into::into),
156
+ },
157
+ )),
158
+ ..Default::default()
159
+ }),
160
+ }
161
+ }
162
+ }
163
+
164
+ impl Failure {
165
+ pub fn timeout(timeout_type: TimeoutType) -> Self {
166
+ Failure {
167
+ failure: Some(APIFailure {
168
+ message: "Activity timed out".to_string(),
169
+ failure_info: Some(failure::FailureInfo::TimeoutFailureInfo(
170
+ TimeoutFailureInfo {
171
+ timeout_type: timeout_type as i32,
172
+ last_heartbeat_details: None,
173
+ },
174
+ )),
175
+ ..Default::default()
176
+ }),
177
+ }
178
+ }
179
+ }
180
+ }
181
+
182
+ pub mod bridge {
183
+ tonic::include_proto!("coresdk.bridge");
86
184
  }
185
+
87
186
  pub mod common {
88
187
  tonic::include_proto!("coresdk.common");
89
- use crate::temporal::api::common::v1::Payloads;
188
+ use super::external_data::LocalActivityMarkerData;
189
+ use crate::{
190
+ coresdk::{AsJsonPayloadExt, IntoPayloadsExt},
191
+ temporal::api::common::v1::{Payload as ApiPayload, Payloads},
192
+ };
90
193
  use std::collections::HashMap;
91
194
 
92
195
  impl<T> From<T> for Payload
@@ -126,11 +229,122 @@ pub mod coresdk {
126
229
  let deprecated = *details.get("deprecated")?.payloads.get(0)?.data.get(0)? != 0;
127
230
  Some((name.to_string(), deprecated))
128
231
  }
232
+
233
+ pub fn build_local_activity_marker_details(
234
+ metadata: LocalActivityMarkerData,
235
+ result: Option<Payload>,
236
+ ) -> HashMap<String, Payloads> {
237
+ let mut hm = HashMap::new();
238
+ // It would be more efficient for this to be proto binary, but then it shows up as
239
+ // meaningless in the Temporal UI...
240
+ if let Some(jsonified) = metadata.as_json_payload().into_payloads() {
241
+ hm.insert("data".to_string(), jsonified);
242
+ }
243
+ if let Some(res) = result {
244
+ hm.insert("result".to_string(), res.into());
245
+ }
246
+ hm
247
+ }
248
+
249
+ /// Given a marker detail map, returns just the local activity info, but not the payload.
250
+ /// This is fairly inexpensive. Deserializing the whole payload may not be.
251
+ pub fn extract_local_activity_marker_data(
252
+ details: &HashMap<String, Payloads>,
253
+ ) -> Option<LocalActivityMarkerData> {
254
+ details
255
+ .get("data")
256
+ .and_then(|p| p.payloads.get(0))
257
+ .and_then(|p| std::str::from_utf8(&p.data).ok())
258
+ .and_then(|s| serde_json::from_str(s).ok())
259
+ }
260
+
261
+ /// Given a marker detail map, returns the local activity info and the result payload
262
+ /// if they are found and the marker data is well-formed. This removes the data from the
263
+ /// map.
264
+ pub fn extract_local_activity_marker_details(
265
+ details: &mut HashMap<String, Payloads>,
266
+ ) -> (Option<LocalActivityMarkerData>, Option<ApiPayload>) {
267
+ let data = extract_local_activity_marker_data(details);
268
+ let result = details.remove("result").and_then(|mut p| p.payloads.pop());
269
+ (data, result)
270
+ }
271
+ }
272
+
273
+ pub mod external_data {
274
+ use prost_types::{Duration, Timestamp};
275
+ use serde::{Deserialize, Deserializer, Serialize, Serializer};
276
+ tonic::include_proto!("coresdk.external_data");
277
+
278
+ // Buncha hullaballoo because prost types aren't serde compat.
279
+ // See https://github.com/tokio-rs/prost/issues/75 which hilariously Chad opened ages ago
280
+
281
+ #[derive(Serialize, Deserialize)]
282
+ #[serde(remote = "Timestamp")]
283
+ struct TimestampDef {
284
+ pub seconds: i64,
285
+ pub nanos: i32,
286
+ }
287
+ mod opt_timestamp {
288
+ use super::*;
289
+
290
+ pub fn serialize<S>(value: &Option<Timestamp>, serializer: S) -> Result<S::Ok, S::Error>
291
+ where
292
+ S: Serializer,
293
+ {
294
+ #[derive(Serialize)]
295
+ struct Helper<'a>(#[serde(with = "TimestampDef")] &'a Timestamp);
296
+
297
+ value.as_ref().map(Helper).serialize(serializer)
298
+ }
299
+
300
+ pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Timestamp>, D::Error>
301
+ where
302
+ D: Deserializer<'de>,
303
+ {
304
+ #[derive(Deserialize)]
305
+ struct Helper(#[serde(with = "TimestampDef")] Timestamp);
306
+
307
+ let helper = Option::deserialize(deserializer)?;
308
+ Ok(helper.map(|Helper(external)| external))
309
+ }
310
+ }
311
+
312
+ // Luckily Duration is also stored the exact same way
313
+ #[derive(Serialize, Deserialize)]
314
+ #[serde(remote = "Duration")]
315
+ struct DurationDef {
316
+ pub seconds: i64,
317
+ pub nanos: i32,
318
+ }
319
+ mod opt_duration {
320
+ use super::*;
321
+
322
+ pub fn serialize<S>(value: &Option<Duration>, serializer: S) -> Result<S::Ok, S::Error>
323
+ where
324
+ S: Serializer,
325
+ {
326
+ #[derive(Serialize)]
327
+ struct Helper<'a>(#[serde(with = "DurationDef")] &'a Duration);
328
+
329
+ value.as_ref().map(Helper).serialize(serializer)
330
+ }
331
+
332
+ pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
333
+ where
334
+ D: Deserializer<'de>,
335
+ {
336
+ #[derive(Deserialize)]
337
+ struct Helper(#[serde(with = "DurationDef")] Duration);
338
+
339
+ let helper = Option::deserialize(deserializer)?;
340
+ Ok(helper.map(|Helper(external)| external))
341
+ }
342
+ }
129
343
  }
130
344
 
131
345
  pub mod workflow_activation {
132
346
  use crate::{
133
- coresdk::FromPayloadsExt,
347
+ coresdk::{workflow_activation::remove_from_cache::EvictionReason, FromPayloadsExt},
134
348
  temporal::api::history::v1::{
135
349
  WorkflowExecutionCancelRequestedEventAttributes,
136
350
  WorkflowExecutionSignaledEventAttributes,
@@ -139,13 +353,21 @@ pub mod coresdk {
139
353
  use std::fmt::{Display, Formatter};
140
354
 
141
355
  tonic::include_proto!("coresdk.workflow_activation");
142
- pub fn create_evict_activation(run_id: String, reason: String) -> WfActivation {
143
- WfActivation {
356
+
357
+ pub fn create_evict_activation(
358
+ run_id: String,
359
+ message: String,
360
+ reason: EvictionReason,
361
+ ) -> WorkflowActivation {
362
+ WorkflowActivation {
144
363
  timestamp: None,
145
364
  run_id,
146
365
  is_replaying: false,
147
- jobs: vec![WfActivationJob::from(
148
- wf_activation_job::Variant::RemoveFromCache(RemoveFromCache { reason }),
366
+ jobs: vec![WorkflowActivationJob::from(
367
+ workflow_activation_job::Variant::RemoveFromCache(RemoveFromCache {
368
+ message,
369
+ reason: reason as i32,
370
+ }),
149
371
  )],
150
372
  }
151
373
  }
@@ -153,27 +375,27 @@ pub mod coresdk {
153
375
  pub fn create_query_activation(
154
376
  run_id: String,
155
377
  queries: impl IntoIterator<Item = QueryWorkflow>,
156
- ) -> WfActivation {
157
- WfActivation {
378
+ ) -> WorkflowActivation {
379
+ WorkflowActivation {
158
380
  timestamp: None,
159
381
  run_id,
160
382
  is_replaying: false,
161
383
  jobs: queries
162
384
  .into_iter()
163
- .map(|qr| wf_activation_job::Variant::QueryWorkflow(qr).into())
385
+ .map(|qr| workflow_activation_job::Variant::QueryWorkflow(qr).into())
164
386
  .collect(),
165
387
  }
166
388
  }
167
389
 
168
- impl WfActivation {
390
+ impl WorkflowActivation {
169
391
  /// Returns the index of the eviction job if this activation contains one. If present
170
392
  /// it should always be the last job in the list.
171
393
  pub fn eviction_index(&self) -> Option<usize> {
172
394
  self.jobs.iter().position(|j| {
173
395
  matches!(
174
396
  j,
175
- WfActivationJob {
176
- variant: Some(wf_activation_job::Variant::RemoveFromCache(_))
397
+ WorkflowActivationJob {
398
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_))
177
399
  }
178
400
  )
179
401
  })
@@ -183,11 +405,46 @@ pub mod coresdk {
183
405
  pub fn is_only_eviction(&self) -> bool {
184
406
  self.jobs.len() == 1 && self.eviction_index().is_some()
185
407
  }
408
+
409
+ /// Returns eviction reason if this activation has an evict job
410
+ pub fn eviction_reason(&self) -> Option<EvictionReason> {
411
+ self.jobs.iter().find_map(|j| {
412
+ if let Some(workflow_activation_job::Variant::RemoveFromCache(ref rj)) =
413
+ j.variant
414
+ {
415
+ EvictionReason::from_i32(rj.reason)
416
+ } else {
417
+ None
418
+ }
419
+ })
420
+ }
421
+
422
+ /// Append an eviction job to the joblist
423
+ pub fn append_evict_job(&mut self, evict_job: RemoveFromCache) {
424
+ if let Some(last_job) = self.jobs.last() {
425
+ if matches!(
426
+ last_job.variant,
427
+ Some(workflow_activation_job::Variant::RemoveFromCache(_))
428
+ ) {
429
+ return;
430
+ }
431
+ }
432
+ let evict_job = WorkflowActivationJob::from(
433
+ workflow_activation_job::Variant::RemoveFromCache(evict_job),
434
+ );
435
+ self.jobs.push(evict_job);
436
+ }
437
+ }
438
+
439
+ impl Display for EvictionReason {
440
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
441
+ write!(f, "{:?}", self)
442
+ }
186
443
  }
187
444
 
188
- impl Display for WfActivation {
445
+ impl Display for WorkflowActivation {
189
446
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
190
- write!(f, "WfActivation(")?;
447
+ write!(f, "WorkflowActivation(")?;
191
448
  write!(f, "run_id: {}, ", self.run_id)?;
192
449
  write!(f, "is_replaying: {}, ", self.is_replaying)?;
193
450
  write!(
@@ -203,45 +460,57 @@ pub mod coresdk {
203
460
  }
204
461
  }
205
462
 
206
- impl Display for WfActivationJob {
463
+ impl Display for WorkflowActivationJob {
207
464
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
208
465
  match &self.variant {
209
- None => write!(f, "Empty"),
210
- Some(v) => match v {
211
- wf_activation_job::Variant::StartWorkflow(_) => write!(f, "StartWorkflow"),
212
- wf_activation_job::Variant::FireTimer(_) => write!(f, "FireTimer"),
213
- wf_activation_job::Variant::UpdateRandomSeed(_) => {
214
- write!(f, "UpdateRandomSeed")
215
- }
216
- wf_activation_job::Variant::QueryWorkflow(_) => write!(f, "QueryWorkflow"),
217
- wf_activation_job::Variant::CancelWorkflow(_) => {
218
- write!(f, "CancelWorkflow")
219
- }
220
- wf_activation_job::Variant::SignalWorkflow(_) => {
221
- write!(f, "SignalWorkflow")
222
- }
223
- wf_activation_job::Variant::ResolveActivity(_) => {
224
- write!(f, "ResolveActivity")
225
- }
226
- wf_activation_job::Variant::NotifyHasPatch(_) => {
227
- write!(f, "NotifyHasPatch")
228
- }
229
- wf_activation_job::Variant::ResolveChildWorkflowExecutionStart(_) => {
230
- write!(f, "ResolveChildWorkflowExecutionStart")
231
- }
232
- wf_activation_job::Variant::ResolveChildWorkflowExecution(_) => {
233
- write!(f, "ResolveChildWorkflowExecution")
234
- }
235
- wf_activation_job::Variant::ResolveSignalExternalWorkflow(_) => {
236
- write!(f, "ResolveSignalExternalWorkflow")
237
- }
238
- wf_activation_job::Variant::RemoveFromCache(_) => {
239
- write!(f, "RemoveFromCache")
240
- }
241
- wf_activation_job::Variant::ResolveRequestCancelExternalWorkflow(_) => {
242
- write!(f, "ResolveRequestCancelExternalWorkflow")
243
- }
244
- },
466
+ None => write!(f, "empty"),
467
+ Some(v) => write!(f, "{}", v),
468
+ }
469
+ }
470
+ }
471
+
472
+ impl Display for workflow_activation_job::Variant {
473
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
474
+ match self {
475
+ workflow_activation_job::Variant::StartWorkflow(_) => {
476
+ write!(f, "StartWorkflow")
477
+ }
478
+ workflow_activation_job::Variant::FireTimer(t) => {
479
+ write!(f, "FireTimer({})", t.seq)
480
+ }
481
+ workflow_activation_job::Variant::UpdateRandomSeed(_) => {
482
+ write!(f, "UpdateRandomSeed")
483
+ }
484
+ workflow_activation_job::Variant::QueryWorkflow(_) => {
485
+ write!(f, "QueryWorkflow")
486
+ }
487
+ workflow_activation_job::Variant::CancelWorkflow(_) => {
488
+ write!(f, "CancelWorkflow")
489
+ }
490
+ workflow_activation_job::Variant::SignalWorkflow(_) => {
491
+ write!(f, "SignalWorkflow")
492
+ }
493
+ workflow_activation_job::Variant::ResolveActivity(r) => {
494
+ write!(f, "ResolveActivity({})", r.seq)
495
+ }
496
+ workflow_activation_job::Variant::NotifyHasPatch(_) => {
497
+ write!(f, "NotifyHasPatch")
498
+ }
499
+ workflow_activation_job::Variant::ResolveChildWorkflowExecutionStart(_) => {
500
+ write!(f, "ResolveChildWorkflowExecutionStart")
501
+ }
502
+ workflow_activation_job::Variant::ResolveChildWorkflowExecution(_) => {
503
+ write!(f, "ResolveChildWorkflowExecution")
504
+ }
505
+ workflow_activation_job::Variant::ResolveSignalExternalWorkflow(_) => {
506
+ write!(f, "ResolveSignalExternalWorkflow")
507
+ }
508
+ workflow_activation_job::Variant::RemoveFromCache(_) => {
509
+ write!(f, "RemoveFromCache")
510
+ }
511
+ workflow_activation_job::Variant::ResolveRequestCancelExternalWorkflow(_) => {
512
+ write!(f, "ResolveRequestCancelExternalWorkflow")
513
+ }
245
514
  }
246
515
  }
247
516
  }
@@ -264,9 +533,10 @@ pub mod coresdk {
264
533
  }
265
534
 
266
535
  pub mod workflow_completion {
536
+ use crate::temporal::api::failure;
267
537
  tonic::include_proto!("coresdk.workflow_completion");
268
538
 
269
- impl wf_activation_completion::Status {
539
+ impl workflow_activation_completion::Status {
270
540
  pub const fn is_success(&self) -> bool {
271
541
  match &self {
272
542
  Self::Successful(_) => true,
@@ -274,6 +544,12 @@ pub mod coresdk {
274
544
  }
275
545
  }
276
546
  }
547
+
548
+ impl From<failure::v1::Failure> for Failure {
549
+ fn from(f: failure::v1::Failure) -> Self {
550
+ Failure { failure: Some(f) }
551
+ }
552
+ }
277
553
  }
278
554
 
279
555
  pub mod child_workflow {
@@ -290,51 +566,125 @@ pub mod coresdk {
290
566
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
291
567
  match &self.variant {
292
568
  None => write!(f, "Empty"),
293
- Some(v) => match v {
294
- workflow_command::Variant::StartTimer(_) => write!(f, "StartTimer"),
295
- workflow_command::Variant::ScheduleActivity(_) => {
296
- write!(f, "ScheduleActivity")
297
- }
298
- workflow_command::Variant::RespondToQuery(_) => write!(f, "RespondToQuery"),
299
- workflow_command::Variant::RequestCancelActivity(_) => {
300
- write!(f, "RequestCancelActivity")
301
- }
302
- workflow_command::Variant::CancelTimer(_) => write!(f, "CancelTimer"),
303
- workflow_command::Variant::CompleteWorkflowExecution(_) => {
304
- write!(f, "CompleteWorkflowExecution")
305
- }
306
- workflow_command::Variant::FailWorkflowExecution(_) => {
307
- write!(f, "FailWorkflowExecution")
308
- }
309
- workflow_command::Variant::ContinueAsNewWorkflowExecution(_) => {
310
- write!(f, "ContinueAsNewWorkflowExecution")
311
- }
312
- workflow_command::Variant::CancelWorkflowExecution(_) => {
313
- write!(f, "CancelWorkflowExecution")
314
- }
315
- workflow_command::Variant::SetPatchMarker(_) => {
316
- write!(f, "SetPatchMarker")
317
- }
318
- workflow_command::Variant::StartChildWorkflowExecution(_) => {
319
- write!(f, "StartChildWorkflowExecution")
320
- }
321
- workflow_command::Variant::RequestCancelExternalWorkflowExecution(_) => {
322
- write!(f, "RequestCancelExternalWorkflowExecution")
323
- }
324
- workflow_command::Variant::SignalExternalWorkflowExecution(_) => {
325
- write!(f, "SignalExternalWorkflowExecution")
326
- }
327
- workflow_command::Variant::CancelSignalWorkflow(_) => {
328
- write!(f, "CancelSignalWorkflow")
329
- }
330
- workflow_command::Variant::CancelUnstartedChildWorkflowExecution(_) => {
331
- write!(f, "CancelUnstartedChildWorkflowExecution")
332
- }
333
- },
569
+ Some(v) => write!(f, "{}", v),
334
570
  }
335
571
  }
336
572
  }
337
573
 
574
+ impl Display for StartTimer {
575
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
576
+ write!(f, "StartTimer({})", self.seq)
577
+ }
578
+ }
579
+
580
+ impl Display for ScheduleActivity {
581
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
582
+ write!(f, "ScheduleActivity({}, {})", self.seq, self.activity_type)
583
+ }
584
+ }
585
+
586
+ impl Display for ScheduleLocalActivity {
587
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
588
+ write!(
589
+ f,
590
+ "ScheduleLocalActivity({}, {})",
591
+ self.seq, self.activity_type
592
+ )
593
+ }
594
+ }
595
+
596
+ impl Display for QueryResult {
597
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
598
+ write!(f, "RespondToQuery({})", self.query_id)
599
+ }
600
+ }
601
+
602
+ impl Display for RequestCancelActivity {
603
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
604
+ write!(f, "RequestCancelActivity({})", self.seq)
605
+ }
606
+ }
607
+
608
+ impl Display for RequestCancelLocalActivity {
609
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
610
+ write!(f, "RequestCancelLocalActivity({})", self.seq)
611
+ }
612
+ }
613
+
614
+ impl Display for CancelTimer {
615
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
616
+ write!(f, "CancelTimer({})", self.seq)
617
+ }
618
+ }
619
+
620
+ impl Display for CompleteWorkflowExecution {
621
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
622
+ write!(f, "CompleteWorkflowExecution")
623
+ }
624
+ }
625
+
626
+ impl Display for FailWorkflowExecution {
627
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
628
+ write!(f, "FailWorkflowExecution")
629
+ }
630
+ }
631
+
632
+ impl Display for ContinueAsNewWorkflowExecution {
633
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
634
+ write!(f, "ContinueAsNewWorkflowExecution")
635
+ }
636
+ }
637
+
638
+ impl Display for CancelWorkflowExecution {
639
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
640
+ write!(f, "CancelWorkflowExecution")
641
+ }
642
+ }
643
+
644
+ impl Display for SetPatchMarker {
645
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
646
+ write!(f, "SetPatchMarker({})", self.patch_id)
647
+ }
648
+ }
649
+
650
+ impl Display for StartChildWorkflowExecution {
651
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
652
+ write!(
653
+ f,
654
+ "StartChildWorkflowExecution({}, {})",
655
+ self.seq, self.workflow_type
656
+ )
657
+ }
658
+ }
659
+
660
+ impl Display for RequestCancelExternalWorkflowExecution {
661
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
662
+ write!(f, "RequestCancelExternalWorkflowExecution({})", self.seq)
663
+ }
664
+ }
665
+
666
+ impl Display for SignalExternalWorkflowExecution {
667
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
668
+ write!(f, "SignalExternalWorkflowExecution({})", self.seq)
669
+ }
670
+ }
671
+
672
+ impl Display for CancelSignalWorkflow {
673
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
674
+ write!(f, "CancelSignalWorkflow({})", self.seq)
675
+ }
676
+ }
677
+
678
+ impl Display for CancelUnstartedChildWorkflowExecution {
679
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
680
+ write!(
681
+ f,
682
+ "CancelUnstartedChildWorkflowExecution({})",
683
+ self.child_workflow_seq
684
+ )
685
+ }
686
+ }
687
+
338
688
  impl QueryResult {
339
689
  /// Helper to construct the Temporal API query result types.
340
690
  pub fn into_components(self) -> (String, QueryResultType, Option<Payloads>, String) {
@@ -368,8 +718,8 @@ pub mod coresdk {
368
718
 
369
719
  pub type HistoryEventId = i64;
370
720
 
371
- impl From<wf_activation_job::Variant> for WfActivationJob {
372
- fn from(a: wf_activation_job::Variant) -> Self {
721
+ impl From<workflow_activation_job::Variant> for WorkflowActivationJob {
722
+ fn from(a: workflow_activation_job::Variant) -> Self {
373
723
  Self { variant: Some(a) }
374
724
  }
375
725
  }
@@ -396,14 +746,14 @@ pub mod coresdk {
396
746
  }
397
747
  }
398
748
 
399
- impl WfActivationCompletion {
749
+ impl WorkflowActivationCompletion {
400
750
  /// Create a successful activation with no commands in it
401
751
  pub fn empty(task_queue: impl Into<String>, run_id: impl Into<String>) -> Self {
402
752
  let success = workflow_completion::Success::from_variants(vec![]);
403
753
  Self {
404
754
  run_id: run_id.into(),
405
755
  task_queue: task_queue.into(),
406
- status: Some(wf_activation_completion::Status::Successful(success)),
756
+ status: Some(workflow_activation_completion::Status::Successful(success)),
407
757
  }
408
758
  }
409
759
 
@@ -417,7 +767,7 @@ pub mod coresdk {
417
767
  Self {
418
768
  run_id: run_id.into(),
419
769
  task_queue: task_q.into(),
420
- status: Some(wf_activation_completion::Status::Successful(success)),
770
+ status: Some(workflow_activation_completion::Status::Successful(success)),
421
771
  }
422
772
  }
423
773
 
@@ -431,7 +781,7 @@ pub mod coresdk {
431
781
  Self {
432
782
  run_id: run_id.into(),
433
783
  task_queue: task_q.into(),
434
- status: Some(wf_activation_completion::Status::Successful(success)),
784
+ status: Some(workflow_activation_completion::Status::Successful(success)),
435
785
  }
436
786
  }
437
787
 
@@ -443,7 +793,7 @@ pub mod coresdk {
443
793
  Self {
444
794
  run_id: run_id.into(),
445
795
  task_queue: task_q.into(),
446
- status: Some(wf_activation_completion::Status::Failed(
796
+ status: Some(workflow_activation_completion::Status::Failed(
447
797
  workflow_completion::Failure {
448
798
  failure: Some(failure),
449
799
  },
@@ -462,7 +812,7 @@ pub mod coresdk {
462
812
 
463
813
  /// Returns true if the activation contains a fail workflow execution command
464
814
  pub fn has_fail_execution(&self) -> bool {
465
- if let Some(wf_activation_completion::Status::Successful(s)) = &self.status {
815
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
466
816
  return s.commands.iter().any(|wfc| {
467
817
  matches!(
468
818
  wfc,
@@ -477,7 +827,7 @@ pub mod coresdk {
477
827
 
478
828
  /// Returns true if the activation contains a cancel workflow execution command
479
829
  pub fn has_cancel_workflow_execution(&self) -> bool {
480
- if let Some(wf_activation_completion::Status::Successful(s)) = &self.status {
830
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
481
831
  return s.commands.iter().any(|wfc| {
482
832
  matches!(
483
833
  wfc,
@@ -492,7 +842,7 @@ pub mod coresdk {
492
842
 
493
843
  /// Returns true if the activation contains a continue as new workflow execution command
494
844
  pub fn has_continue_as_new(&self) -> bool {
495
- if let Some(wf_activation_completion::Status::Successful(s)) = &self.status {
845
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
496
846
  return s.commands.iter().any(|wfc| {
497
847
  matches!(
498
848
  wfc,
@@ -509,7 +859,7 @@ pub mod coresdk {
509
859
 
510
860
  /// Returns true if the activation contains a complete workflow execution command
511
861
  pub fn has_complete_workflow_execution(&self) -> bool {
512
- if let Some(wf_activation_completion::Status::Successful(s)) = &self.status {
862
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
513
863
  return s.commands.iter().any(|wfc| {
514
864
  matches!(
515
865
  wfc,
@@ -523,15 +873,23 @@ pub mod coresdk {
523
873
  }
524
874
  }
525
875
 
526
- /// Makes converting outgoing lang commands into [WfActivationCompletion]s easier
876
+ /// Makes converting outgoing lang commands into [WorkflowActivationCompletion]s easier
527
877
  pub trait IntoCompletion {
528
878
  /// The conversion function
529
- fn into_completion(self, task_queue: String, run_id: String) -> WfActivationCompletion;
879
+ fn into_completion(
880
+ self,
881
+ task_queue: String,
882
+ run_id: String,
883
+ ) -> WorkflowActivationCompletion;
530
884
  }
531
885
 
532
886
  impl IntoCompletion for workflow_command::Variant {
533
- fn into_completion(self, task_queue: String, run_id: String) -> WfActivationCompletion {
534
- WfActivationCompletion::from_cmd(task_queue, run_id, self)
887
+ fn into_completion(
888
+ self,
889
+ task_queue: String,
890
+ run_id: String,
891
+ ) -> WorkflowActivationCompletion {
892
+ WorkflowActivationCompletion::from_cmd(task_queue, run_id, self)
535
893
  }
536
894
  }
537
895
 
@@ -540,21 +898,25 @@ pub mod coresdk {
540
898
  I: IntoIterator<Item = V>,
541
899
  V: Into<WorkflowCommand>,
542
900
  {
543
- fn into_completion(self, task_queue: String, run_id: String) -> WfActivationCompletion {
901
+ fn into_completion(
902
+ self,
903
+ task_queue: String,
904
+ run_id: String,
905
+ ) -> WorkflowActivationCompletion {
544
906
  let success = self.into_iter().map(Into::into).collect::<Vec<_>>().into();
545
- WfActivationCompletion {
907
+ WorkflowActivationCompletion {
546
908
  run_id,
547
909
  task_queue,
548
- status: Some(wf_activation_completion::Status::Successful(success)),
910
+ status: Some(workflow_activation_completion::Status::Successful(success)),
549
911
  }
550
912
  }
551
913
  }
552
914
 
553
- impl Display for WfActivationCompletion {
915
+ impl Display for WorkflowActivationCompletion {
554
916
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
555
917
  write!(
556
918
  f,
557
- "WfActivationCompletion(run_id: {}, status: ",
919
+ "WorkflowActivationCompletion(run_id: {}, status: ",
558
920
  &self.run_id
559
921
  )?;
560
922
  match &self.status {
@@ -565,12 +927,12 @@ pub mod coresdk {
565
927
  }
566
928
  }
567
929
 
568
- impl Display for wf_activation_completion::Status {
930
+ impl Display for workflow_activation_completion::Status {
569
931
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
570
932
  match self {
571
- wf_activation_completion::Status::Successful(workflow_completion::Success {
572
- commands,
573
- }) => {
933
+ workflow_activation_completion::Status::Successful(
934
+ workflow_completion::Success { commands },
935
+ ) => {
574
936
  write!(f, "Success(")?;
575
937
  let mut written = 0;
576
938
  for c in commands {
@@ -583,32 +945,13 @@ pub mod coresdk {
583
945
  }
584
946
  write!(f, ")")
585
947
  }
586
- wf_activation_completion::Status::Failed(_) => {
948
+ workflow_activation_completion::Status::Failed(_) => {
587
949
  write!(f, "Failed")
588
950
  }
589
951
  }
590
952
  }
591
953
  }
592
954
 
593
- impl ActivityResult {
594
- pub const fn ok(result: Payload) -> Self {
595
- Self {
596
- status: Some(activity_result::activity_result::Status::Completed(
597
- activity_result::Success {
598
- result: Some(result),
599
- },
600
- )),
601
- }
602
- }
603
-
604
- pub fn unwrap_ok_payload(self) -> Payload {
605
- match self.status.unwrap() {
606
- activity_result::activity_result::Status::Completed(c) => c.result.unwrap(),
607
- _ => panic!("Activity was not successful"),
608
- }
609
- }
610
- }
611
-
612
955
  impl ActivityTask {
613
956
  pub fn start_from_poll_resp(r: PollActivityTaskQueueResponse) -> Self {
614
957
  let (workflow_id, run_id) = r
@@ -617,7 +960,6 @@ pub mod coresdk {
617
960
  .unwrap_or_default();
618
961
  Self {
619
962
  task_token: r.task_token,
620
- activity_id: r.activity_id,
621
963
  variant: Some(activity_task::activity_task::Variant::Start(
622
964
  activity_task::Start {
623
965
  workflow_namespace: r.workflow_namespace,
@@ -626,6 +968,7 @@ pub mod coresdk {
626
968
  workflow_id,
627
969
  run_id,
628
970
  }),
971
+ activity_id: r.activity_id,
629
972
  activity_type: r.activity_type.map_or_else(|| "".to_string(), |at| at.name),
630
973
  header_fields: r.header.map(Into::into).unwrap_or_default(),
631
974
  input: Vec::from_payloads(r.input),
@@ -633,11 +976,12 @@ pub mod coresdk {
633
976
  scheduled_time: r.scheduled_time,
634
977
  current_attempt_scheduled_time: r.current_attempt_scheduled_time,
635
978
  started_time: r.started_time,
636
- attempt: r.attempt,
979
+ attempt: r.attempt as u32,
637
980
  schedule_to_close_timeout: r.schedule_to_close_timeout,
638
981
  start_to_close_timeout: r.start_to_close_timeout,
639
982
  heartbeat_timeout: r.heartbeat_timeout,
640
983
  retry_policy: r.retry_policy.map(Into::into),
984
+ is_local: false,
641
985
  },
642
986
  )),
643
987
  }
@@ -666,6 +1010,10 @@ pub mod coresdk {
666
1010
  }
667
1011
 
668
1012
  impl Failure {
1013
+ pub fn is_timeout(&self) -> bool {
1014
+ matches!(self.failure_info, Some(FailureInfo::TimeoutFailureInfo(_)))
1015
+ }
1016
+
669
1017
  pub fn application_failure(message: String, non_retryable: bool) -> Self {
670
1018
  Self {
671
1019
  message,
@@ -680,6 +1028,18 @@ pub mod coresdk {
680
1028
  }
681
1029
  }
682
1030
 
1031
+ impl From<&str> for Failure {
1032
+ fn from(v: &str) -> Self {
1033
+ Failure::application_failure(v.to_string(), false)
1034
+ }
1035
+ }
1036
+
1037
+ impl From<anyhow::Error> for Failure {
1038
+ fn from(ae: anyhow::Error) -> Self {
1039
+ Failure::application_failure(ae.to_string(), false)
1040
+ }
1041
+ }
1042
+
683
1043
  impl From<common::Payload> for super::temporal::api::common::v1::Payload {
684
1044
  fn from(p: Payload) -> Self {
685
1045
  Self {
@@ -767,6 +1127,55 @@ pub mod coresdk {
767
1127
  }
768
1128
  }
769
1129
 
1130
+ #[derive(thiserror::Error, Debug)]
1131
+ pub enum PayloadDeserializeErr {
1132
+ /// This deserializer does not handle this type of payload. Allows composing multiple
1133
+ /// deserializers.
1134
+ #[error("This deserializer does not understand this payload")]
1135
+ DeserializerDoesNotHandle,
1136
+ #[error("Error during deserialization: {0}")]
1137
+ DeserializeErr(#[from] anyhow::Error),
1138
+ }
1139
+
1140
+ // TODO: Once the prototype SDK is un-prototyped this serialization will need to be compat with
1141
+ // other SDKs (given they might execute an activity).
1142
+ pub trait AsJsonPayloadExt {
1143
+ fn as_json_payload(&self) -> anyhow::Result<Payload>;
1144
+ }
1145
+ impl<T> AsJsonPayloadExt for T
1146
+ where
1147
+ T: Serialize,
1148
+ {
1149
+ fn as_json_payload(&self) -> anyhow::Result<Payload> {
1150
+ let as_json = serde_json::to_string(self)?;
1151
+ let mut metadata = HashMap::new();
1152
+ metadata.insert("encoding".to_string(), b"json/plain".to_vec());
1153
+ Ok(Payload {
1154
+ metadata,
1155
+ data: as_json.into_bytes(),
1156
+ })
1157
+ }
1158
+ }
1159
+
1160
+ pub trait FromJsonPayloadExt: Sized {
1161
+ fn from_json_payload(payload: &Payload) -> Result<Self, PayloadDeserializeErr>;
1162
+ }
1163
+ impl<T> FromJsonPayloadExt for T
1164
+ where
1165
+ T: for<'de> Deserialize<'de>,
1166
+ {
1167
+ fn from_json_payload(payload: &Payload) -> Result<Self, PayloadDeserializeErr> {
1168
+ if !matches!(
1169
+ payload.metadata.get("encoding").map(|v| v.as_slice()),
1170
+ Some(b"json/plain")
1171
+ ) {
1172
+ return Err(PayloadDeserializeErr::DeserializerDoesNotHandle);
1173
+ }
1174
+ let payload_str = std::str::from_utf8(&payload.data).map_err(anyhow::Error::from)?;
1175
+ Ok(serde_json::from_str(payload_str).map_err(anyhow::Error::from)?)
1176
+ }
1177
+ }
1178
+
770
1179
  /// Errors when converting from a [Payloads] api proto to our internal [common::Payload]
771
1180
  #[derive(derive_more::Display, Debug)]
772
1181
  pub enum PayloadsToPayloadError {
@@ -792,8 +1201,12 @@ pub mod coresdk {
792
1201
  }
793
1202
 
794
1203
  // No need to lint these
795
- #[allow(clippy::all)]
796
- #[allow(missing_docs)]
1204
+ #[allow(
1205
+ clippy::all,
1206
+ missing_docs,
1207
+ rustdoc::broken_intra_doc_links,
1208
+ rustdoc::bare_urls
1209
+ )]
797
1210
  // This is disgusting, but unclear to me how to avoid it. TODO: Discuss w/ prost maintainer
798
1211
  pub mod temporal {
799
1212
  pub mod api {
@@ -1077,11 +1490,31 @@ pub mod temporal {
1077
1490
  use crate::temporal::api::{
1078
1491
  enums::v1::EventType, history::v1::history_event::Attributes,
1079
1492
  };
1493
+ use anyhow::bail;
1080
1494
  use prost::alloc::fmt::Formatter;
1081
1495
  use std::fmt::Display;
1082
1496
 
1083
1497
  tonic::include_proto!("temporal.api.history.v1");
1084
1498
 
1499
+ impl History {
1500
+ pub fn extract_run_id_from_start(&self) -> Result<&str, anyhow::Error> {
1501
+ if let Some(
1502
+ history_event::Attributes::WorkflowExecutionStartedEventAttributes(wes),
1503
+ ) = self.events.get(0).and_then(|x| x.attributes.as_ref())
1504
+ {
1505
+ Ok(&wes.original_execution_run_id)
1506
+ } else {
1507
+ bail!("First event is not WorkflowExecutionStarted?!?")
1508
+ }
1509
+ }
1510
+
1511
+ /// Returns the event id of the final event in the history. Will return 0 if
1512
+ /// there are no events.
1513
+ pub fn last_event_id(&self) -> i64 {
1514
+ self.events.last().map(|e| e.event_id).unwrap_or_default()
1515
+ }
1516
+ }
1517
+
1085
1518
  impl HistoryEvent {
1086
1519
  /// Returns true if this is an event created to mirror a command
1087
1520
  pub fn is_command_event(&self) -> bool {