@temporalio/core-bridge 0.17.2 → 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 +45 -52
  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 +264 -286
  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 +34 -73
  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 +305 -195
  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 +19 -21
  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 +344 -160
  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 +297 -81
  85. package/sdk-core/{test_utils → core-api}/Cargo.toml +10 -7
  86. package/sdk-core/{src → core-api/src}/errors.rs +42 -90
  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 +594 -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 -158
@@ -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),
75
79
  })),
76
80
  }
77
81
  }
82
+
83
+ pub fn fail(fail: APIFailure) -> Self {
84
+ Self {
85
+ status: Some(aer::Status::Failed(Failure {
86
+ failure: Some(fail),
87
+ })),
88
+ }
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 {})),
100
+ }
101
+ }
102
+
103
+ pub fn is_cancelled(&self) -> bool {
104
+ matches!(self.status, Some(aer::Status::Cancelled(_)))
105
+ }
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
+ }),
83
160
  }
84
161
  }
85
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
+ }
186
437
  }
187
438
 
188
- impl Display for WfActivation {
439
+ impl Display for EvictionReason {
189
440
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
190
- write!(f, "WfActivation(")?;
441
+ write!(f, "{:?}", self)
442
+ }
443
+ }
444
+
445
+ impl Display for WorkflowActivation {
446
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
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
  }
@@ -267,7 +536,7 @@ pub mod coresdk {
267
536
  use crate::temporal::api::failure;
268
537
  tonic::include_proto!("coresdk.workflow_completion");
269
538
 
270
- impl wf_activation_completion::Status {
539
+ impl workflow_activation_completion::Status {
271
540
  pub const fn is_success(&self) -> bool {
272
541
  match &self {
273
542
  Self::Successful(_) => true,
@@ -297,51 +566,125 @@ pub mod coresdk {
297
566
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
298
567
  match &self.variant {
299
568
  None => write!(f, "Empty"),
300
- Some(v) => match v {
301
- workflow_command::Variant::StartTimer(_) => write!(f, "StartTimer"),
302
- workflow_command::Variant::ScheduleActivity(_) => {
303
- write!(f, "ScheduleActivity")
304
- }
305
- workflow_command::Variant::RespondToQuery(_) => write!(f, "RespondToQuery"),
306
- workflow_command::Variant::RequestCancelActivity(_) => {
307
- write!(f, "RequestCancelActivity")
308
- }
309
- workflow_command::Variant::CancelTimer(_) => write!(f, "CancelTimer"),
310
- workflow_command::Variant::CompleteWorkflowExecution(_) => {
311
- write!(f, "CompleteWorkflowExecution")
312
- }
313
- workflow_command::Variant::FailWorkflowExecution(_) => {
314
- write!(f, "FailWorkflowExecution")
315
- }
316
- workflow_command::Variant::ContinueAsNewWorkflowExecution(_) => {
317
- write!(f, "ContinueAsNewWorkflowExecution")
318
- }
319
- workflow_command::Variant::CancelWorkflowExecution(_) => {
320
- write!(f, "CancelWorkflowExecution")
321
- }
322
- workflow_command::Variant::SetPatchMarker(_) => {
323
- write!(f, "SetPatchMarker")
324
- }
325
- workflow_command::Variant::StartChildWorkflowExecution(_) => {
326
- write!(f, "StartChildWorkflowExecution")
327
- }
328
- workflow_command::Variant::RequestCancelExternalWorkflowExecution(_) => {
329
- write!(f, "RequestCancelExternalWorkflowExecution")
330
- }
331
- workflow_command::Variant::SignalExternalWorkflowExecution(_) => {
332
- write!(f, "SignalExternalWorkflowExecution")
333
- }
334
- workflow_command::Variant::CancelSignalWorkflow(_) => {
335
- write!(f, "CancelSignalWorkflow")
336
- }
337
- workflow_command::Variant::CancelUnstartedChildWorkflowExecution(_) => {
338
- write!(f, "CancelUnstartedChildWorkflowExecution")
339
- }
340
- },
569
+ Some(v) => write!(f, "{}", v),
341
570
  }
342
571
  }
343
572
  }
344
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
+
345
688
  impl QueryResult {
346
689
  /// Helper to construct the Temporal API query result types.
347
690
  pub fn into_components(self) -> (String, QueryResultType, Option<Payloads>, String) {
@@ -375,8 +718,8 @@ pub mod coresdk {
375
718
 
376
719
  pub type HistoryEventId = i64;
377
720
 
378
- impl From<wf_activation_job::Variant> for WfActivationJob {
379
- 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 {
380
723
  Self { variant: Some(a) }
381
724
  }
382
725
  }
@@ -403,14 +746,14 @@ pub mod coresdk {
403
746
  }
404
747
  }
405
748
 
406
- impl WfActivationCompletion {
749
+ impl WorkflowActivationCompletion {
407
750
  /// Create a successful activation with no commands in it
408
751
  pub fn empty(task_queue: impl Into<String>, run_id: impl Into<String>) -> Self {
409
752
  let success = workflow_completion::Success::from_variants(vec![]);
410
753
  Self {
411
754
  run_id: run_id.into(),
412
755
  task_queue: task_queue.into(),
413
- status: Some(wf_activation_completion::Status::Successful(success)),
756
+ status: Some(workflow_activation_completion::Status::Successful(success)),
414
757
  }
415
758
  }
416
759
 
@@ -424,7 +767,7 @@ pub mod coresdk {
424
767
  Self {
425
768
  run_id: run_id.into(),
426
769
  task_queue: task_q.into(),
427
- status: Some(wf_activation_completion::Status::Successful(success)),
770
+ status: Some(workflow_activation_completion::Status::Successful(success)),
428
771
  }
429
772
  }
430
773
 
@@ -438,7 +781,7 @@ pub mod coresdk {
438
781
  Self {
439
782
  run_id: run_id.into(),
440
783
  task_queue: task_q.into(),
441
- status: Some(wf_activation_completion::Status::Successful(success)),
784
+ status: Some(workflow_activation_completion::Status::Successful(success)),
442
785
  }
443
786
  }
444
787
 
@@ -450,7 +793,7 @@ pub mod coresdk {
450
793
  Self {
451
794
  run_id: run_id.into(),
452
795
  task_queue: task_q.into(),
453
- status: Some(wf_activation_completion::Status::Failed(
796
+ status: Some(workflow_activation_completion::Status::Failed(
454
797
  workflow_completion::Failure {
455
798
  failure: Some(failure),
456
799
  },
@@ -469,7 +812,7 @@ pub mod coresdk {
469
812
 
470
813
  /// Returns true if the activation contains a fail workflow execution command
471
814
  pub fn has_fail_execution(&self) -> bool {
472
- if let Some(wf_activation_completion::Status::Successful(s)) = &self.status {
815
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
473
816
  return s.commands.iter().any(|wfc| {
474
817
  matches!(
475
818
  wfc,
@@ -484,7 +827,7 @@ pub mod coresdk {
484
827
 
485
828
  /// Returns true if the activation contains a cancel workflow execution command
486
829
  pub fn has_cancel_workflow_execution(&self) -> bool {
487
- if let Some(wf_activation_completion::Status::Successful(s)) = &self.status {
830
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
488
831
  return s.commands.iter().any(|wfc| {
489
832
  matches!(
490
833
  wfc,
@@ -499,7 +842,7 @@ pub mod coresdk {
499
842
 
500
843
  /// Returns true if the activation contains a continue as new workflow execution command
501
844
  pub fn has_continue_as_new(&self) -> bool {
502
- if let Some(wf_activation_completion::Status::Successful(s)) = &self.status {
845
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
503
846
  return s.commands.iter().any(|wfc| {
504
847
  matches!(
505
848
  wfc,
@@ -516,7 +859,7 @@ pub mod coresdk {
516
859
 
517
860
  /// Returns true if the activation contains a complete workflow execution command
518
861
  pub fn has_complete_workflow_execution(&self) -> bool {
519
- if let Some(wf_activation_completion::Status::Successful(s)) = &self.status {
862
+ if let Some(workflow_activation_completion::Status::Successful(s)) = &self.status {
520
863
  return s.commands.iter().any(|wfc| {
521
864
  matches!(
522
865
  wfc,
@@ -530,15 +873,23 @@ pub mod coresdk {
530
873
  }
531
874
  }
532
875
 
533
- /// Makes converting outgoing lang commands into [WfActivationCompletion]s easier
876
+ /// Makes converting outgoing lang commands into [WorkflowActivationCompletion]s easier
534
877
  pub trait IntoCompletion {
535
878
  /// The conversion function
536
- 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;
537
884
  }
538
885
 
539
886
  impl IntoCompletion for workflow_command::Variant {
540
- fn into_completion(self, task_queue: String, run_id: String) -> WfActivationCompletion {
541
- 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)
542
893
  }
543
894
  }
544
895
 
@@ -547,21 +898,25 @@ pub mod coresdk {
547
898
  I: IntoIterator<Item = V>,
548
899
  V: Into<WorkflowCommand>,
549
900
  {
550
- 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 {
551
906
  let success = self.into_iter().map(Into::into).collect::<Vec<_>>().into();
552
- WfActivationCompletion {
907
+ WorkflowActivationCompletion {
553
908
  run_id,
554
909
  task_queue,
555
- status: Some(wf_activation_completion::Status::Successful(success)),
910
+ status: Some(workflow_activation_completion::Status::Successful(success)),
556
911
  }
557
912
  }
558
913
  }
559
914
 
560
- impl Display for WfActivationCompletion {
915
+ impl Display for WorkflowActivationCompletion {
561
916
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
562
917
  write!(
563
918
  f,
564
- "WfActivationCompletion(run_id: {}, status: ",
919
+ "WorkflowActivationCompletion(run_id: {}, status: ",
565
920
  &self.run_id
566
921
  )?;
567
922
  match &self.status {
@@ -572,12 +927,12 @@ pub mod coresdk {
572
927
  }
573
928
  }
574
929
 
575
- impl Display for wf_activation_completion::Status {
930
+ impl Display for workflow_activation_completion::Status {
576
931
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
577
932
  match self {
578
- wf_activation_completion::Status::Successful(workflow_completion::Success {
579
- commands,
580
- }) => {
933
+ workflow_activation_completion::Status::Successful(
934
+ workflow_completion::Success { commands },
935
+ ) => {
581
936
  write!(f, "Success(")?;
582
937
  let mut written = 0;
583
938
  for c in commands {
@@ -590,32 +945,13 @@ pub mod coresdk {
590
945
  }
591
946
  write!(f, ")")
592
947
  }
593
- wf_activation_completion::Status::Failed(_) => {
948
+ workflow_activation_completion::Status::Failed(_) => {
594
949
  write!(f, "Failed")
595
950
  }
596
951
  }
597
952
  }
598
953
  }
599
954
 
600
- impl ActivityResult {
601
- pub const fn ok(result: Payload) -> Self {
602
- Self {
603
- status: Some(activity_result::activity_result::Status::Completed(
604
- activity_result::Success {
605
- result: Some(result),
606
- },
607
- )),
608
- }
609
- }
610
-
611
- pub fn unwrap_ok_payload(self) -> Payload {
612
- match self.status.unwrap() {
613
- activity_result::activity_result::Status::Completed(c) => c.result.unwrap(),
614
- _ => panic!("Activity was not successful"),
615
- }
616
- }
617
- }
618
-
619
955
  impl ActivityTask {
620
956
  pub fn start_from_poll_resp(r: PollActivityTaskQueueResponse) -> Self {
621
957
  let (workflow_id, run_id) = r
@@ -624,7 +960,6 @@ pub mod coresdk {
624
960
  .unwrap_or_default();
625
961
  Self {
626
962
  task_token: r.task_token,
627
- activity_id: r.activity_id,
628
963
  variant: Some(activity_task::activity_task::Variant::Start(
629
964
  activity_task::Start {
630
965
  workflow_namespace: r.workflow_namespace,
@@ -633,6 +968,7 @@ pub mod coresdk {
633
968
  workflow_id,
634
969
  run_id,
635
970
  }),
971
+ activity_id: r.activity_id,
636
972
  activity_type: r.activity_type.map_or_else(|| "".to_string(), |at| at.name),
637
973
  header_fields: r.header.map(Into::into).unwrap_or_default(),
638
974
  input: Vec::from_payloads(r.input),
@@ -640,11 +976,12 @@ pub mod coresdk {
640
976
  scheduled_time: r.scheduled_time,
641
977
  current_attempt_scheduled_time: r.current_attempt_scheduled_time,
642
978
  started_time: r.started_time,
643
- attempt: r.attempt,
979
+ attempt: r.attempt as u32,
644
980
  schedule_to_close_timeout: r.schedule_to_close_timeout,
645
981
  start_to_close_timeout: r.start_to_close_timeout,
646
982
  heartbeat_timeout: r.heartbeat_timeout,
647
983
  retry_policy: r.retry_policy.map(Into::into),
984
+ is_local: false,
648
985
  },
649
986
  )),
650
987
  }
@@ -673,6 +1010,10 @@ pub mod coresdk {
673
1010
  }
674
1011
 
675
1012
  impl Failure {
1013
+ pub fn is_timeout(&self) -> bool {
1014
+ matches!(self.failure_info, Some(FailureInfo::TimeoutFailureInfo(_)))
1015
+ }
1016
+
676
1017
  pub fn application_failure(message: String, non_retryable: bool) -> Self {
677
1018
  Self {
678
1019
  message,
@@ -687,6 +1028,18 @@ pub mod coresdk {
687
1028
  }
688
1029
  }
689
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
+
690
1043
  impl From<common::Payload> for super::temporal::api::common::v1::Payload {
691
1044
  fn from(p: Payload) -> Self {
692
1045
  Self {
@@ -774,6 +1127,55 @@ pub mod coresdk {
774
1127
  }
775
1128
  }
776
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
+
777
1179
  /// Errors when converting from a [Payloads] api proto to our internal [common::Payload]
778
1180
  #[derive(derive_more::Display, Debug)]
779
1181
  pub enum PayloadsToPayloadError {
@@ -799,8 +1201,12 @@ pub mod coresdk {
799
1201
  }
800
1202
 
801
1203
  // No need to lint these
802
- #[allow(clippy::all)]
803
- #[allow(missing_docs)]
1204
+ #[allow(
1205
+ clippy::all,
1206
+ missing_docs,
1207
+ rustdoc::broken_intra_doc_links,
1208
+ rustdoc::bare_urls
1209
+ )]
804
1210
  // This is disgusting, but unclear to me how to avoid it. TODO: Discuss w/ prost maintainer
805
1211
  pub mod temporal {
806
1212
  pub mod api {
@@ -1084,11 +1490,31 @@ pub mod temporal {
1084
1490
  use crate::temporal::api::{
1085
1491
  enums::v1::EventType, history::v1::history_event::Attributes,
1086
1492
  };
1493
+ use anyhow::bail;
1087
1494
  use prost::alloc::fmt::Formatter;
1088
1495
  use std::fmt::Display;
1089
1496
 
1090
1497
  tonic::include_proto!("temporal.api.history.v1");
1091
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
+
1092
1518
  impl HistoryEvent {
1093
1519
  /// Returns true if this is an event created to mirror a command
1094
1520
  pub fn is_command_event(&self) -> bool {