@temporalio/core-bridge 0.23.0 → 1.0.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 (135) hide show
  1. package/Cargo.lock +118 -15
  2. package/Cargo.toml +2 -1
  3. package/LICENSE.md +1 -1
  4. package/README.md +1 -1
  5. package/index.d.ts +47 -18
  6. package/package.json +7 -7
  7. package/releases/aarch64-apple-darwin/index.node +0 -0
  8. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  9. package/releases/x86_64-apple-darwin/index.node +0 -0
  10. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  11. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  12. package/sdk-core/.buildkite/docker/docker-compose.yaml +4 -2
  13. package/sdk-core/ARCHITECTURE.md +9 -7
  14. package/sdk-core/README.md +5 -1
  15. package/sdk-core/arch_docs/diagrams/workflow_internals.svg +1 -0
  16. package/sdk-core/bridge-ffi/src/wrappers.rs +0 -3
  17. package/sdk-core/client/src/lib.rs +26 -8
  18. package/sdk-core/client/src/raw.rs +166 -54
  19. package/sdk-core/client/src/retry.rs +9 -4
  20. package/sdk-core/client/src/workflow_handle/mod.rs +4 -2
  21. package/sdk-core/core/Cargo.toml +2 -0
  22. package/sdk-core/core/src/abstractions.rs +137 -16
  23. package/sdk-core/core/src/core_tests/activity_tasks.rs +258 -63
  24. package/sdk-core/core/src/core_tests/child_workflows.rs +1 -2
  25. package/sdk-core/core/src/core_tests/determinism.rs +2 -2
  26. package/sdk-core/core/src/core_tests/local_activities.rs +8 -7
  27. package/sdk-core/core/src/core_tests/queries.rs +146 -60
  28. package/sdk-core/core/src/core_tests/replay_flag.rs +1 -1
  29. package/sdk-core/core/src/core_tests/workers.rs +39 -23
  30. package/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
  31. package/sdk-core/core/src/core_tests/workflow_tasks.rs +387 -280
  32. package/sdk-core/core/src/lib.rs +6 -4
  33. package/sdk-core/core/src/pollers/poll_buffer.rs +16 -10
  34. package/sdk-core/core/src/protosext/mod.rs +6 -6
  35. package/sdk-core/core/src/retry_logic.rs +1 -1
  36. package/sdk-core/core/src/telemetry/metrics.rs +21 -7
  37. package/sdk-core/core/src/telemetry/mod.rs +18 -4
  38. package/sdk-core/core/src/test_help/mod.rs +341 -109
  39. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +18 -9
  40. package/sdk-core/core/src/worker/activities/local_activities.rs +19 -16
  41. package/sdk-core/core/src/worker/activities.rs +156 -29
  42. package/sdk-core/core/src/worker/client.rs +1 -0
  43. package/sdk-core/core/src/worker/mod.rs +132 -659
  44. package/sdk-core/core/src/{workflow → worker/workflow}/bridge.rs +1 -1
  45. package/sdk-core/core/src/{workflow → worker/workflow}/driven_workflow.rs +1 -1
  46. package/sdk-core/core/src/{workflow → worker/workflow}/history_update.rs +16 -2
  47. package/sdk-core/core/src/{workflow → worker/workflow}/machines/activity_state_machine.rs +39 -4
  48. package/sdk-core/core/src/{workflow → worker/workflow}/machines/cancel_external_state_machine.rs +5 -2
  49. package/sdk-core/core/src/{workflow → worker/workflow}/machines/cancel_workflow_state_machine.rs +1 -1
  50. package/sdk-core/core/src/{workflow → worker/workflow}/machines/child_workflow_state_machine.rs +2 -4
  51. package/sdk-core/core/src/{workflow → worker/workflow}/machines/complete_workflow_state_machine.rs +0 -0
  52. package/sdk-core/core/src/{workflow → worker/workflow}/machines/continue_as_new_workflow_state_machine.rs +1 -1
  53. package/sdk-core/core/src/{workflow → worker/workflow}/machines/fail_workflow_state_machine.rs +0 -0
  54. package/sdk-core/core/src/{workflow → worker/workflow}/machines/local_activity_state_machine.rs +2 -5
  55. package/sdk-core/core/src/{workflow → worker/workflow}/machines/mod.rs +1 -1
  56. package/sdk-core/core/src/{workflow → worker/workflow}/machines/mutable_side_effect_state_machine.rs +0 -0
  57. package/sdk-core/core/src/{workflow → worker/workflow}/machines/patch_state_machine.rs +1 -1
  58. package/sdk-core/core/src/{workflow → worker/workflow}/machines/side_effect_state_machine.rs +0 -0
  59. package/sdk-core/core/src/{workflow → worker/workflow}/machines/signal_external_state_machine.rs +4 -2
  60. package/sdk-core/core/src/{workflow → worker/workflow}/machines/timer_state_machine.rs +1 -2
  61. package/sdk-core/core/src/{workflow → worker/workflow}/machines/transition_coverage.rs +1 -1
  62. package/sdk-core/core/src/{workflow → worker/workflow}/machines/upsert_search_attributes_state_machine.rs +5 -7
  63. package/sdk-core/core/src/{workflow → worker/workflow}/machines/workflow_machines/local_acts.rs +2 -2
  64. package/sdk-core/core/src/{workflow → worker/workflow}/machines/workflow_machines.rs +40 -16
  65. package/sdk-core/core/src/{workflow → worker/workflow}/machines/workflow_task_state_machine.rs +0 -0
  66. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +198 -0
  67. package/sdk-core/core/src/worker/workflow/managed_run.rs +627 -0
  68. package/sdk-core/core/src/worker/workflow/mod.rs +1115 -0
  69. package/sdk-core/core/src/worker/workflow/run_cache.rs +143 -0
  70. package/sdk-core/core/src/worker/workflow/wft_poller.rs +88 -0
  71. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +936 -0
  72. package/sdk-core/core-api/src/errors.rs +3 -10
  73. package/sdk-core/core-api/src/lib.rs +2 -1
  74. package/sdk-core/core-api/src/worker.rs +26 -2
  75. package/sdk-core/etc/dynamic-config.yaml +2 -0
  76. package/sdk-core/integ-with-otel.sh +1 -1
  77. package/sdk-core/protos/api_upstream/Makefile +4 -4
  78. package/sdk-core/protos/api_upstream/api-linter.yaml +2 -0
  79. package/sdk-core/protos/api_upstream/buf.yaml +8 -9
  80. package/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +83 -0
  81. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +7 -1
  82. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/cluster.proto +40 -0
  83. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +3 -0
  84. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +3 -1
  85. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +60 -0
  86. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +3 -0
  87. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +32 -4
  88. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +69 -19
  89. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +13 -0
  90. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +163 -0
  91. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +97 -0
  92. package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +300 -0
  93. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +25 -0
  94. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +180 -3
  95. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +53 -3
  96. package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +2 -2
  97. package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +6 -5
  98. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -1
  99. package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +2 -1
  100. package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +0 -64
  101. package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +2 -1
  102. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +11 -8
  103. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +30 -25
  104. package/sdk-core/sdk/src/activity_context.rs +12 -5
  105. package/sdk-core/sdk/src/app_data.rs +37 -0
  106. package/sdk-core/sdk/src/lib.rs +76 -43
  107. package/sdk-core/sdk/src/workflow_context/options.rs +8 -6
  108. package/sdk-core/sdk/src/workflow_context.rs +14 -19
  109. package/sdk-core/sdk/src/workflow_future.rs +11 -6
  110. package/sdk-core/sdk-core-protos/src/history_builder.rs +19 -5
  111. package/sdk-core/sdk-core-protos/src/history_info.rs +11 -6
  112. package/sdk-core/sdk-core-protos/src/lib.rs +74 -176
  113. package/sdk-core/test-utils/src/lib.rs +85 -72
  114. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +11 -9
  115. package/sdk-core/tests/integ_tests/polling_tests.rs +12 -0
  116. package/sdk-core/tests/integ_tests/queries_tests.rs +39 -22
  117. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +49 -4
  118. package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +61 -0
  119. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
  120. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +74 -13
  121. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +19 -0
  122. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
  123. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -3
  124. package/sdk-core/tests/integ_tests/workflow_tests.rs +10 -23
  125. package/sdk-core/tests/load_tests.rs +8 -3
  126. package/sdk-core/tests/main.rs +2 -1
  127. package/src/conversions.rs +47 -39
  128. package/src/errors.rs +10 -21
  129. package/src/lib.rs +342 -325
  130. package/sdk-core/core/src/pending_activations.rs +0 -173
  131. package/sdk-core/core/src/worker/wft_delivery.rs +0 -81
  132. package/sdk-core/core/src/workflow/mod.rs +0 -478
  133. package/sdk-core/core/src/workflow/workflow_tasks/cache_manager.rs +0 -194
  134. package/sdk-core/core/src/workflow/workflow_tasks/concurrency_manager.rs +0 -418
  135. package/sdk-core/core/src/workflow/workflow_tasks/mod.rs +0 -989
@@ -8,16 +8,25 @@
8
8
  //!
9
9
  //! An example of running an activity worker:
10
10
  //! ```no_run
11
- //! use std::{sync::Arc, str::FromStr};
12
- //! use temporal_sdk::{sdk_client_options, Worker, ActContext};
13
- //! use temporal_sdk_core::{init_worker, Url};
14
- //! use temporal_sdk_core_api::worker::{WorkerConfig, WorkerConfigBuilder};
11
+ //! use std::{str::FromStr, sync::Arc};
12
+ //! use temporal_sdk::{sdk_client_options, ActContext, Worker};
13
+ //! use temporal_sdk_core::{init_worker, telemetry_init, TelemetryOptionsBuilder, Url};
14
+ //! use temporal_sdk_core_api::worker::WorkerConfigBuilder;
15
15
  //!
16
16
  //! #[tokio::main]
17
17
  //! async fn main() -> Result<(), Box<dyn std::error::Error>> {
18
18
  //! let server_options = sdk_client_options(Url::from_str("http://localhost:7233")?).build()?;
19
- //! let client = server_options.connect("my_namespace", None, None).await?;
20
- //! let worker_config = WorkerConfigBuilder::default().build()?;
19
+ //!
20
+ //! let client = server_options.connect("default", None, None).await?;
21
+ //!
22
+ //! let telemetry_options = TelemetryOptionsBuilder::default().build()?;
23
+ //! telemetry_init(&telemetry_options)?;
24
+ //!
25
+ //! let worker_config = WorkerConfigBuilder::default()
26
+ //! .namespace("default")
27
+ //! .task_queue("task_queue")
28
+ //! .build()?;
29
+ //!
21
30
  //! let core_worker = init_worker(worker_config, client);
22
31
  //!
23
32
  //! let mut worker = Worker::new_from_core(Arc::new(core_worker), "task_queue");
@@ -25,7 +34,9 @@
25
34
  //! "echo_activity",
26
35
  //! |_ctx: ActContext, echo_me: String| async move { Ok(echo_me) },
27
36
  //! );
37
+ //!
28
38
  //! worker.run().await?;
39
+ //!
29
40
  //! Ok(())
30
41
  //! }
31
42
  //! ```
@@ -34,6 +45,7 @@
34
45
  extern crate tracing;
35
46
 
36
47
  mod activity_context;
48
+ mod app_data;
37
49
  mod conversions;
38
50
  pub mod interceptors;
39
51
  mod payload_converter;
@@ -51,9 +63,9 @@ use crate::{
51
63
  interceptors::WorkerInterceptor,
52
64
  workflow_context::{ChildWfCommon, PendingChildWorkflow},
53
65
  };
54
- use anyhow::{anyhow, bail};
66
+ use anyhow::{anyhow, bail, Context};
67
+ use app_data::AppData;
55
68
  use futures::{future::BoxFuture, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
56
- use once_cell::sync::OnceCell;
57
69
  use std::{
58
70
  cell::RefCell,
59
71
  collections::HashMap,
@@ -72,7 +84,7 @@ use temporal_sdk_core_protos::{
72
84
  activity_result::{ActivityExecutionResult, ActivityResolution},
73
85
  activity_task::{activity_task, ActivityTask},
74
86
  child_workflow::ChildWorkflowResult,
75
- common::{NamespacedWorkflowExecution, Payload},
87
+ common::NamespacedWorkflowExecution,
76
88
  workflow_activation::{
77
89
  resolve_child_workflow_execution_start::Status as ChildWorkflowStartStatus,
78
90
  workflow_activation_job::Variant, WorkflowActivation, WorkflowActivationJob,
@@ -81,7 +93,7 @@ use temporal_sdk_core_protos::{
81
93
  workflow_completion::WorkflowActivationCompletion,
82
94
  ActivityTaskCompletion, AsJsonPayloadExt, FromJsonPayloadExt,
83
95
  },
84
- temporal::api::failure::v1::Failure,
96
+ temporal::api::{common::v1::Payload, failure::v1::Failure},
85
97
  TaskToken,
86
98
  };
87
99
  use tokio::{
@@ -103,8 +115,7 @@ pub fn sdk_client_options(url: impl Into<Url>) -> ClientOptionsBuilder {
103
115
  builder
104
116
  .target_url(url)
105
117
  .client_name("rust-sdk".to_string())
106
- .client_version(VERSION.to_string())
107
- .worker_binary_id(binary_id().to_string());
118
+ .client_version(VERSION.to_string());
108
119
 
109
120
  builder
110
121
  }
@@ -115,6 +126,7 @@ pub struct Worker {
115
126
  common: CommonWorker,
116
127
  workflow_half: WorkflowHalf,
117
128
  activity_half: ActivityHalf,
129
+ app_data: Option<AppData>,
118
130
  }
119
131
 
120
132
  struct CommonWorker {
@@ -146,8 +158,7 @@ struct ActivityHalf {
146
158
  }
147
159
 
148
160
  impl Worker {
149
- #[doc(hidden)]
150
- /// Create a new rust worker from a core worker
161
+ /// Create a new Rust SDK worker from a core worker
151
162
  pub fn new_from_core(worker: Arc<dyn CoreWorker>, task_queue: impl Into<String>) -> Self {
152
163
  Self {
153
164
  common: CommonWorker {
@@ -163,6 +174,7 @@ impl Worker {
163
174
  activity_fns: Default::default(),
164
175
  task_tokens_to_cancels: Default::default(),
165
176
  },
177
+ app_data: Some(Default::default()),
166
178
  }
167
179
  }
168
180
 
@@ -206,11 +218,21 @@ impl Worker {
206
218
  );
207
219
  }
208
220
 
221
+ /// Insert Custom App Context for Workflows and Activities
222
+ pub fn insert_app_data<T: Send + Sync + 'static>(&mut self, data: T) {
223
+ self.app_data.as_mut().map(|a| a.insert(data));
224
+ }
225
+
209
226
  /// Runs the worker. Eventually resolves after the worker has been explicitly shut down,
210
227
  /// or may return early with an error in the event of some unresolvable problem.
211
228
  pub async fn run(&mut self) -> Result<(), anyhow::Error> {
212
229
  let shutdown_token = CancellationToken::new();
213
- let (common, wf_half, act_half) = self.split_apart();
230
+ let (common, wf_half, act_half, app_data) = self.split_apart();
231
+ let safe_app_data = Arc::new(
232
+ app_data
233
+ .take()
234
+ .ok_or_else(|| anyhow!("app_data should exist on run"))?,
235
+ );
214
236
  let (wf_future_tx, wf_future_rx) = unbounded_channel();
215
237
  let (completions_tx, completions_rx) = unbounded_channel();
216
238
  let wf_future_joiner = async {
@@ -225,15 +247,17 @@ impl Worker {
225
247
  let wf_half = &*wf_half;
226
248
  async move {
227
249
  join_handle.await??;
250
+ info!(run_id=%run_id, "Removing workflow from cache");
228
251
  wf_half.workflows.borrow_mut().remove(&run_id);
229
252
  Ok(())
230
253
  }
231
254
  },
232
255
  )
233
256
  .await
257
+ .context("Workflow futures encountered an error")
234
258
  };
235
259
  let wf_completion_processor = async {
236
- let r = UnboundedReceiverStream::new(completions_rx)
260
+ UnboundedReceiverStream::new(completions_rx)
237
261
  .map(Ok)
238
262
  .try_for_each_concurrent(None, |completion| async {
239
263
  if let Some(ref i) = common.worker_interceptor {
@@ -241,9 +265,9 @@ impl Worker {
241
265
  }
242
266
  common.worker.complete_workflow_activation(completion).await
243
267
  })
244
- .map_err(Into::into)
245
- .await;
246
- r
268
+ .map_err(anyhow::Error::from)
269
+ .await
270
+ .context("Workflow completions processor encountered an error")
247
271
  };
248
272
  tokio::try_join!(
249
273
  // Workflow polling loop
@@ -287,9 +311,12 @@ impl Worker {
287
311
  if matches!(activity, Err(PollActivityError::ShutDown)) {
288
312
  break;
289
313
  }
290
- act_half.activity_task_handler(common.worker.clone(),
291
- common.task_queue.clone(),
292
- activity?)?;
314
+ act_half.activity_task_handler(
315
+ common.worker.clone(),
316
+ safe_app_data.clone(),
317
+ common.task_queue.clone(),
318
+ activity?
319
+ )?;
293
320
  },
294
321
  _ = shutdown_token.cancelled() => { break }
295
322
  }
@@ -306,6 +333,10 @@ impl Worker {
306
333
  i.on_shutdown(self);
307
334
  }
308
335
  self.common.worker.shutdown().await;
336
+ self.app_data = Some(
337
+ Arc::try_unwrap(safe_app_data)
338
+ .map_err(|_| anyhow!("some references of AppData exist on worker shutdown"))?,
339
+ );
309
340
  Ok(())
310
341
  }
311
342
 
@@ -327,11 +358,19 @@ impl Worker {
327
358
  self.workflow_half.workflows.borrow().len()
328
359
  }
329
360
 
330
- fn split_apart(&mut self) -> (&mut CommonWorker, &mut WorkflowHalf, &mut ActivityHalf) {
361
+ fn split_apart(
362
+ &mut self,
363
+ ) -> (
364
+ &mut CommonWorker,
365
+ &mut WorkflowHalf,
366
+ &mut ActivityHalf,
367
+ &mut Option<AppData>,
368
+ ) {
331
369
  (
332
370
  &mut self.common,
333
371
  &mut self.workflow_half,
334
372
  &mut self.activity_half,
373
+ &mut self.app_data,
335
374
  )
336
375
  }
337
376
  }
@@ -398,7 +437,11 @@ impl WorkflowHalf {
398
437
  .send(activation)
399
438
  .expect("Workflow should exist if we're sending it an activation");
400
439
  } else {
401
- bail!("Got activation for unknown workflow");
440
+ bail!(
441
+ "Got activation {:?} for unknown workflow {}",
442
+ activation,
443
+ run_id
444
+ );
402
445
  };
403
446
 
404
447
  Ok(res)
@@ -410,6 +453,7 @@ impl ActivityHalf {
410
453
  fn activity_task_handler(
411
454
  &mut self,
412
455
  worker: Arc<dyn CoreWorker>,
456
+ app_data: Arc<AppData>,
413
457
  task_queue: String,
414
458
  activity: ActivityTask,
415
459
  ) -> Result<(), anyhow::Error> {
@@ -430,8 +474,14 @@ impl ActivityHalf {
430
474
  self.task_tokens_to_cancels
431
475
  .insert(task_token.clone().into(), ct.clone());
432
476
 
433
- let (ctx, arg) =
434
- ActContext::new(worker.clone(), ct, task_queue, task_token.clone(), start);
477
+ let (ctx, arg) = ActContext::new(
478
+ worker.clone(),
479
+ app_data,
480
+ ct,
481
+ task_queue,
482
+ task_token.clone(),
483
+ start,
484
+ );
435
485
  tokio::spawn(async move {
436
486
  let output = (act_fn.act_func)(ctx, arg).await;
437
487
  let result = match output {
@@ -713,20 +763,3 @@ where
713
763
  Arc::new(wrapper)
714
764
  }
715
765
  }
716
-
717
- /// Reads own binary, hashes it, and returns b64 str version of that hash
718
- fn binary_id() -> &'static str {
719
- use sha2::{Digest, Sha256};
720
- use std::{env, fs, io};
721
-
722
- static INSTANCE: OnceCell<String> = OnceCell::new();
723
- INSTANCE.get_or_init(|| {
724
- let exe_path = env::current_exe().expect("Cannot read own binary to determine binary id");
725
- let mut exe_file =
726
- fs::File::open(exe_path).expect("Cannot read own binary to determine binary id");
727
- let mut hasher = Sha256::new();
728
- io::copy(&mut exe_file, &mut hasher).expect("Copying data into binary hasher works");
729
- let hash = hasher.finalize();
730
- base64::encode(hash)
731
- })
732
- }
@@ -1,11 +1,13 @@
1
1
  use std::{collections::HashMap, time::Duration};
2
- use temporal_sdk_core_protos::coresdk::{
3
- child_workflow::ChildWorkflowCancellationType,
4
- common::{Payload, RetryPolicy},
5
- workflow_commands::{
6
- ActivityCancellationType, ScheduleActivity, ScheduleLocalActivity,
7
- StartChildWorkflowExecution,
2
+ use temporal_sdk_core_protos::{
3
+ coresdk::{
4
+ child_workflow::ChildWorkflowCancellationType,
5
+ workflow_commands::{
6
+ ActivityCancellationType, ScheduleActivity, ScheduleLocalActivity,
7
+ StartChildWorkflowExecution,
8
+ },
8
9
  },
10
+ temporal::api::common::v1::{Payload, RetryPolicy},
9
11
  };
10
12
 
11
13
  // TODO: Before release, probably best to avoid using proto types entirely here. They're awkward.
@@ -25,17 +25,20 @@ use std::{
25
25
  task::Poll,
26
26
  time::{Duration, SystemTime},
27
27
  };
28
- use temporal_sdk_core_protos::coresdk::{
29
- activity_result::{activity_resolution, ActivityResolution},
30
- child_workflow::ChildWorkflowResult,
31
- common::{NamespacedWorkflowExecution, Payload},
32
- workflow_activation::resolve_child_workflow_execution_start::Status as ChildWorkflowStartStatus,
33
- workflow_commands::{
34
- request_cancel_external_workflow_execution as cancel_we,
35
- signal_external_workflow_execution as sig_we, workflow_command,
36
- RequestCancelExternalWorkflowExecution, SetPatchMarker, SignalExternalWorkflowExecution,
37
- StartTimer, UpsertWorkflowSearchAttributes,
28
+ use temporal_sdk_core_protos::{
29
+ coresdk::{
30
+ activity_result::{activity_resolution, ActivityResolution},
31
+ child_workflow::ChildWorkflowResult,
32
+ common::NamespacedWorkflowExecution,
33
+ workflow_activation::resolve_child_workflow_execution_start::Status as ChildWorkflowStartStatus,
34
+ workflow_commands::{
35
+ request_cancel_external_workflow_execution as cancel_we,
36
+ signal_external_workflow_execution as sig_we, workflow_command,
37
+ RequestCancelExternalWorkflowExecution, SetPatchMarker,
38
+ SignalExternalWorkflowExecution, StartTimer, UpsertWorkflowSearchAttributes,
39
+ },
38
40
  },
41
+ temporal::api::common::v1::Payload,
39
42
  };
40
43
  use tokio::sync::{mpsc, oneshot, watch};
41
44
  use tokio_stream::wrappers::UnboundedReceiverStream;
@@ -59,7 +62,6 @@ struct WfCtxProtectedDat {
59
62
  next_child_workflow_sequence_number: u32,
60
63
  next_cancel_external_wf_sequence_number: u32,
61
64
  next_signal_external_wf_sequence_number: u32,
62
- next_upsert_search_attrs_sequence_number: u32,
63
65
  }
64
66
 
65
67
  impl WfCtxProtectedDat {
@@ -88,11 +90,6 @@ impl WfCtxProtectedDat {
88
90
  self.next_signal_external_wf_sequence_number += 1;
89
91
  seq
90
92
  }
91
- fn next_upsert_search_attrs_wf_seq(&mut self) -> u32 {
92
- let seq = self.next_upsert_search_attrs_sequence_number;
93
- self.next_upsert_search_attrs_sequence_number += 1;
94
- seq
95
- }
96
93
  }
97
94
 
98
95
  #[derive(Clone, Debug, Default)]
@@ -130,7 +127,6 @@ impl WfContext {
130
127
  next_child_workflow_sequence_number: 1,
131
128
  next_cancel_external_wf_sequence_number: 1,
132
129
  next_signal_external_wf_sequence_number: 1,
133
- next_upsert_search_attrs_sequence_number: 1,
134
130
  }),
135
131
  },
136
132
  rx,
@@ -289,9 +285,8 @@ impl WfContext {
289
285
  /// Add or create a set of search attributes
290
286
  pub fn upsert_search_attributes(&self, attr_iter: impl IntoIterator<Item = (String, Payload)>) {
291
287
  self.send(RustWfCmd::NewNonblockingCmd(
292
- workflow_command::Variant::UpsertWorkflowSearchAttributesCommandAttributes(
288
+ workflow_command::Variant::UpsertWorkflowSearchAttributes(
293
289
  UpsertWorkflowSearchAttributes {
294
- seq: self.seq_nums.write().next_upsert_search_attrs_wf_seq(),
295
290
  search_attributes: HashMap::from_iter(attr_iter.into_iter()),
296
291
  },
297
292
  ),
@@ -17,7 +17,6 @@ use std::{
17
17
  };
18
18
  use temporal_sdk_core_protos::{
19
19
  coresdk::{
20
- common::Payload,
21
20
  workflow_activation::{
22
21
  workflow_activation_job::Variant, FireTimer, NotifyHasPatch, ResolveActivity,
23
22
  ResolveChildWorkflowExecution, ResolveChildWorkflowExecutionStart, WorkflowActivation,
@@ -33,7 +32,7 @@ use temporal_sdk_core_protos::{
33
32
  },
34
33
  workflow_completion::WorkflowActivationCompletion,
35
34
  },
36
- temporal::api::failure::v1::Failure,
35
+ temporal::api::{common::v1::Payload, failure::v1::Failure},
37
36
  utilities::TryIntoOrNone,
38
37
  };
39
38
  use tokio::sync::{
@@ -123,11 +122,10 @@ impl WorkflowFuture {
123
122
  UnblockEvent::CancelExternal(seq, _) => CommandID::CancelExternal(seq),
124
123
  };
125
124
  let unblocker = self.command_status.remove(&cmd_id);
126
- unblocker
125
+ let _ = unblocker
127
126
  .ok_or_else(|| anyhow!("Command {:?} not found to unblock!", cmd_id))?
128
127
  .unblocker
129
- .send(event)
130
- .expect("Receive half of unblock channel must exist");
128
+ .send(event);
131
129
  Ok(())
132
130
  }
133
131
 
@@ -238,7 +236,14 @@ impl Future for WorkflowFuture {
238
236
  'activations: loop {
239
237
  // WF must always receive an activation first before responding with commands
240
238
  let activation = match self.incoming_activations.poll_recv(cx) {
241
- Poll::Ready(a) => a.expect("activation channel not dropped"),
239
+ Poll::Ready(a) => match a {
240
+ Some(act) => act,
241
+ None => {
242
+ return Poll::Ready(Err(anyhow!(
243
+ "Workflow future's activation channel was lost!"
244
+ )))
245
+ }
246
+ },
242
247
  Poll::Pending => return Poll::Pending,
243
248
  };
244
249
 
@@ -3,7 +3,7 @@ use crate::{
3
3
  coresdk::{
4
4
  common::{
5
5
  build_has_change_marker_details, build_local_activity_marker_details,
6
- NamespacedWorkflowExecution, Payload as CorePayload,
6
+ NamespacedWorkflowExecution,
7
7
  },
8
8
  external_data::LocalActivityMarkerData,
9
9
  IntoPayloadsExt,
@@ -116,6 +116,20 @@ impl TestHistoryBuilder {
116
116
  self.build_and_push_event(EventType::WorkflowExecutionCompleted, attrs.into());
117
117
  }
118
118
 
119
+ pub fn add_workflow_execution_terminated(&mut self) {
120
+ let attrs = WorkflowExecutionTerminatedEventAttributes {
121
+ ..Default::default()
122
+ };
123
+ self.build_and_push_event(EventType::WorkflowExecutionTerminated, attrs.into());
124
+ }
125
+
126
+ pub fn add_workflow_execution_timed_out(&mut self) {
127
+ let attrs = WorkflowExecutionTimedOutEventAttributes {
128
+ ..Default::default()
129
+ };
130
+ self.build_and_push_event(EventType::WorkflowExecutionTimedOut, attrs.into());
131
+ }
132
+
119
133
  pub fn add_workflow_execution_failed(&mut self) {
120
134
  let attrs = WorkflowExecutionFailedEventAttributes {
121
135
  workflow_task_completed_event_id: self.previous_task_completed_id,
@@ -170,7 +184,7 @@ impl TestHistoryBuilder {
170
184
  &mut self,
171
185
  scheduled_event_id: i64,
172
186
  started_event_id: i64,
173
- payload: CorePayload,
187
+ payload: Payload,
174
188
  ) {
175
189
  self.add(
176
190
  EventType::ActivityTaskCompleted,
@@ -254,7 +268,7 @@ impl TestHistoryBuilder {
254
268
  &mut self,
255
269
  seq: u32,
256
270
  activity_id: &str,
257
- payload: Option<CorePayload>,
271
+ payload: Option<Payload>,
258
272
  failure: Option<Failure>,
259
273
  complete_time: Option<Timestamp>,
260
274
  ) {
@@ -283,7 +297,7 @@ impl TestHistoryBuilder {
283
297
  &mut self,
284
298
  seq: u32,
285
299
  activity_id: &str,
286
- payload: CorePayload,
300
+ payload: Payload,
287
301
  ) {
288
302
  self.add_local_activity_marker(seq, activity_id, Some(payload), None, None);
289
303
  }
@@ -292,7 +306,7 @@ impl TestHistoryBuilder {
292
306
  &mut self,
293
307
  seq: u32,
294
308
  activity_id: &str,
295
- payload: CorePayload,
309
+ payload: Payload,
296
310
  complete_time: Timestamp,
297
311
  ) {
298
312
  self.add_local_activity_marker(seq, activity_id, Some(payload), None, Some(complete_time));
@@ -60,9 +60,14 @@ impl HistoryInfo {
60
60
  let next_is_completed = next_event.map_or(false, |ne| {
61
61
  ne.event_type == EventType::WorkflowTaskCompleted as i32
62
62
  });
63
- let next_is_failed_or_timeout = next_event.map_or(false, |ne| {
64
- ne.event_type == EventType::WorkflowTaskFailed as i32
65
- || ne.event_type == EventType::WorkflowTaskTimedOut as i32
63
+ let next_is_failed_or_timeout_or_term = next_event.map_or(false, |ne| {
64
+ matches!(
65
+ ne.event_type(),
66
+ EventType::WorkflowTaskFailed
67
+ | EventType::WorkflowTaskTimedOut
68
+ | EventType::WorkflowExecutionTerminated
69
+ | EventType::WorkflowExecutionTimedOut
70
+ )
66
71
  });
67
72
 
68
73
  if next_event.is_none() || next_is_completed {
@@ -84,10 +89,10 @@ impl HistoryInfo {
84
89
  wf_type,
85
90
  });
86
91
  }
87
- } else if next_event.is_some() && !next_is_failed_or_timeout {
92
+ } else if next_event.is_some() && !next_is_failed_or_timeout_or_term {
88
93
  bail!(
89
- "Invalid history! Event {event:?} should be WFT \
90
- completed, failed, or timed out"
94
+ "Invalid history! Event {next_event:?} should be WFT \
95
+ completed, failed, or timed out - or WE terminated."
91
96
  );
92
97
  }
93
98
  }