@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
@@ -1,14 +1,11 @@
1
- use crate::{
2
- prototype_rust_sdk::{WfContext, WorkflowFunction},
3
- test_help::canned_histories,
4
- workflow::managed_wf::ManagedWFFunc,
5
- };
1
+ use crate::{test_help::canned_histories, workflow::managed_wf::ManagedWFFunc};
6
2
  use rstest::{fixture, rstest};
7
3
  use std::time::Duration;
4
+ use temporal_sdk::{WfContext, WorkflowFunction};
8
5
  use temporal_sdk_core_protos::temporal::api::enums::v1::CommandType;
9
6
 
10
7
  fn timers_wf(num_timers: u32) -> WorkflowFunction {
11
- WorkflowFunction::new(move |mut command_sink: WfContext| async move {
8
+ WorkflowFunction::new(move |command_sink: WfContext| async move {
12
9
  for _ in 1..=num_timers {
13
10
  command_sink.timer(Duration::from_secs(1)).await;
14
11
  }
@@ -30,20 +27,19 @@ fn fire_happy_hist(num_timers: u32) -> ManagedWFFunc {
30
27
  #[tokio::test]
31
28
  async fn replay_flag_is_correct(#[case] mut wfm: ManagedWFFunc, #[case] num_timers: usize) {
32
29
  // Verify replay flag is correct by constructing a workflow manager that already has a complete
33
- // history fed into it. The first (few, depending on test a params) activation(s) will be under
34
- // replay while the last should not
30
+ // history fed into it. It should always be replaying, because history is complete.
35
31
 
36
32
  for _ in 1..=num_timers {
37
33
  let act = wfm.get_next_activation().await.unwrap();
38
34
  assert!(act.is_replaying);
39
- let commands = wfm.get_server_commands().await.commands;
35
+ let commands = wfm.get_server_commands().commands;
40
36
  assert_eq!(commands.len(), 1);
41
37
  assert_eq!(commands[0].command_type, CommandType::StartTimer as i32);
42
38
  }
43
39
 
44
40
  let act = wfm.get_next_activation().await.unwrap();
45
- assert!(!act.is_replaying);
46
- let commands = wfm.get_server_commands().await.commands;
41
+ assert!(act.is_replaying);
42
+ let commands = wfm.get_server_commands().commands;
47
43
  assert_eq!(commands.len(), 1);
48
44
  assert_eq!(
49
45
  commands[0].command_type,
@@ -62,7 +58,7 @@ async fn replay_flag_is_correct_partial_history() {
62
58
 
63
59
  let act = wfm.get_next_activation().await.unwrap();
64
60
  assert!(!act.is_replaying);
65
- let commands = wfm.get_server_commands().await.commands;
61
+ let commands = wfm.get_server_commands().commands;
66
62
  assert_eq!(commands.len(), 1);
67
63
  assert_eq!(commands[0].command_type, CommandType::StartTimer as i32);
68
64
  wfm.shutdown().await.unwrap();
@@ -1,27 +1,29 @@
1
1
  use crate::{
2
- pollers::{MockManualGateway, MockServerGatewayApis},
3
2
  test_help::{
4
- build_fake_core, build_multihist_mock_sg, canned_histories, hist_to_poll_resp, mock_core,
5
- mock_core_with_opts_no_workers, mock_manual_poller, register_mock_workers,
6
- single_hist_mock_sg, FakeWfResponses, MockWorker, MocksHolder, ResponseType, TEST_Q,
3
+ build_fake_core, build_mock_pollers, build_multihist_mock_sg, canned_histories,
4
+ hist_to_poll_resp, mock_core, mock_core_with_opts_no_workers, mock_manual_poller,
5
+ register_mock_workers, single_hist_mock_sg, FakeWfResponses, MockPollCfg, MockWorker,
6
+ MocksHolder, ResponseType, TEST_Q,
7
7
  },
8
- Core, CoreInitOptionsBuilder, CoreSDK, PollWfError, WorkerConfigBuilder,
8
+ Core, CoreInitOptionsBuilder, CoreSDK, PollActivityError, PollWfError, WorkerConfigBuilder,
9
9
  };
10
10
  use futures::FutureExt;
11
11
  use rstest::{fixture, rstest};
12
- use std::time::Duration;
12
+ use std::{cell::RefCell, time::Duration};
13
+ use temporal_client::mocks::{mock_gateway, mock_manual_gateway};
13
14
  use temporal_sdk_core_protos::{
14
15
  coresdk::{
15
- workflow_activation::wf_activation_job,
16
+ workflow_activation::workflow_activation_job,
16
17
  workflow_commands::{
17
18
  workflow_command, ActivityCancellationType, CompleteWorkflowExecution,
18
19
  RequestCancelActivity, ScheduleActivity, StartTimer,
19
20
  },
20
- workflow_completion::WfActivationCompletion,
21
+ workflow_completion::WorkflowActivationCompletion,
21
22
  },
22
23
  temporal::api::workflowservice::v1::RespondWorkflowTaskCompletedResponse,
23
24
  };
24
- use tokio::sync::watch;
25
+ use temporal_sdk_core_test_utils::start_timer_cmd;
26
+ use tokio::sync::{watch, Barrier};
25
27
 
26
28
  #[tokio::test]
27
29
  async fn multi_workers() {
@@ -45,9 +47,9 @@ async fn multi_workers() {
45
47
  let res = core.poll_workflow_activation(&tq).await.unwrap();
46
48
  assert_matches!(
47
49
  res.jobs[0].variant,
48
- Some(wf_activation_job::Variant::StartWorkflow(_))
50
+ Some(workflow_activation_job::Variant::StartWorkflow(_))
49
51
  );
50
- core.complete_workflow_activation(WfActivationCompletion::empty(tq, res.run_id))
52
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(tq, res.run_id))
51
53
  .await
52
54
  .unwrap();
53
55
  }
@@ -90,7 +92,6 @@ async fn worker_double_register_is_err() {
90
92
  .build()
91
93
  .unwrap(),
92
94
  )
93
- .await
94
95
  .is_err());
95
96
  }
96
97
 
@@ -116,7 +117,7 @@ async fn pending_activities_only_returned_for_their_queue() {
116
117
 
117
118
  // Create a pending activation by cancelling a try-cancel activity
118
119
  let res = core.poll_workflow_activation("q-1").await.unwrap();
119
- core.complete_workflow_activation(WfActivationCompletion::from_cmds(
120
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
120
121
  "q-1",
121
122
  res.run_id,
122
123
  vec![ScheduleActivity {
@@ -130,7 +131,7 @@ async fn pending_activities_only_returned_for_their_queue() {
130
131
  .await
131
132
  .unwrap();
132
133
  let res = core.poll_workflow_activation("q-1").await.unwrap();
133
- core.complete_workflow_activation(WfActivationCompletion::from_cmds(
134
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
134
135
  "q-1",
135
136
  res.run_id,
136
137
  vec![RequestCancelActivity { seq: act_id }.into()],
@@ -141,14 +142,14 @@ async fn pending_activities_only_returned_for_their_queue() {
141
142
  let res = core.poll_workflow_activation("q-2").await.unwrap();
142
143
  assert_matches!(
143
144
  res.jobs[0].variant,
144
- Some(wf_activation_job::Variant::StartWorkflow(_))
145
+ Some(workflow_activation_job::Variant::StartWorkflow(_))
145
146
  );
146
147
  }
147
148
 
148
149
  #[tokio::test]
149
150
  async fn nonexistent_worker_poll_returns_not_registered() {
150
151
  let core =
151
- mock_core_with_opts_no_workers(MockManualGateway::new(), CoreInitOptionsBuilder::default());
152
+ mock_core_with_opts_no_workers(mock_manual_gateway(), CoreInitOptionsBuilder::default());
152
153
  assert_matches!(
153
154
  core.poll_workflow_activation(TEST_Q).await.unwrap_err(),
154
155
  PollWfError::NoWorkerForQueue(_)
@@ -165,7 +166,7 @@ async fn after_shutdown_of_worker_get_shutdown_err() {
165
166
 
166
167
  tokio::join!(core.shutdown_worker(TEST_Q), async {
167
168
  // Need to complete task for shutdown to finish
168
- core.complete_workflow_activation(WfActivationCompletion::from_cmd(
169
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
169
170
  TEST_Q,
170
171
  run_id.clone(),
171
172
  workflow_command::Variant::StartTimer(StartTimer {
@@ -179,11 +180,14 @@ async fn after_shutdown_of_worker_get_shutdown_err() {
179
180
  let res = core.poll_workflow_activation(TEST_Q).await.unwrap();
180
181
  assert_matches!(
181
182
  res.jobs[0].variant,
182
- Some(wf_activation_job::Variant::RemoveFromCache(_))
183
+ Some(workflow_activation_job::Variant::RemoveFromCache(_))
183
184
  );
184
- core.complete_workflow_activation(WfActivationCompletion::empty(TEST_Q, run_id.clone()))
185
- .await
186
- .unwrap();
185
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(
186
+ TEST_Q,
187
+ run_id.clone(),
188
+ ))
189
+ .await
190
+ .unwrap();
187
191
  assert_matches!(
188
192
  core.poll_workflow_activation(TEST_Q).await.unwrap_err(),
189
193
  PollWfError::ShutDown
@@ -197,17 +201,17 @@ async fn after_shutdown_of_worker_can_be_reregistered() {
197
201
  let mut core = build_fake_core("fake_wf_id", t.clone(), &[1]);
198
202
  let res = core.poll_workflow_activation(TEST_Q).await.unwrap();
199
203
  assert_eq!(res.jobs.len(), 1);
200
- core.complete_workflow_activation(WfActivationCompletion::empty(TEST_Q, res.run_id))
204
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(TEST_Q, res.run_id))
201
205
  .await
202
206
  .unwrap();
203
207
  core.shutdown_worker(TEST_Q).await;
204
208
  // Need to recreate mock to re-register worker
205
- let mocks = single_hist_mock_sg("fake_wf_id", t, &[1], MockServerGatewayApis::new(), true);
209
+ let mocks = single_hist_mock_sg("fake_wf_id", t, &[1], mock_gateway(), true);
206
210
  let pollers = mocks.take_pollers().into_values();
207
211
  register_mock_workers(&mut core, pollers);
208
212
  // Worker is replaced and the different mock returns a new wft
209
213
  let res = core.poll_workflow_activation(TEST_Q).await.unwrap();
210
- core.complete_workflow_activation(WfActivationCompletion::empty(TEST_Q, res.run_id))
214
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(TEST_Q, res.run_id))
211
215
  .await
212
216
  .unwrap();
213
217
  core.shutdown().await;
@@ -220,14 +224,10 @@ async fn shutdown_worker_can_complete_pending_activation() {
220
224
  let res = core.poll_workflow_activation(TEST_Q).await.unwrap();
221
225
  assert_eq!(res.jobs.len(), 1);
222
226
  // Complete the timer, will queue PA
223
- core.complete_workflow_activation(WfActivationCompletion::from_cmds(
227
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
224
228
  TEST_Q,
225
229
  res.run_id,
226
- vec![StartTimer {
227
- seq: 1,
228
- ..Default::default()
229
- }
230
- .into()],
230
+ vec![start_timer_cmd(1, Duration::from_secs(1))],
231
231
  ))
232
232
  .await
233
233
  .unwrap();
@@ -236,7 +236,7 @@ async fn shutdown_worker_can_complete_pending_activation() {
236
236
  let res = core.poll_workflow_activation(TEST_Q).await.unwrap();
237
237
  // The timer fires
238
238
  assert_eq!(res.jobs.len(), 1);
239
- core.complete_workflow_activation(WfActivationCompletion::from_cmds(
239
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
240
240
  TEST_Q,
241
241
  res.run_id,
242
242
  vec![CompleteWorkflowExecution::default().into()],
@@ -281,7 +281,7 @@ fn worker_shutdown() -> (CoreSDK, watch::Sender<bool>) {
281
281
  });
282
282
  mock_pollers.push(MockWorker::new(&tq, Box::from(mock_poller)));
283
283
  }
284
- let mut mock_gateway = MockServerGatewayApis::new();
284
+ let mut mock_gateway = mock_gateway();
285
285
  mock_gateway
286
286
  .expect_complete_workflow_task()
287
287
  .returning(|_| Ok(RespondWorkflowTaskCompletedResponse::default()));
@@ -324,7 +324,7 @@ async fn worker_shutdown_during_multiple_poll_doesnt_deadlock(
324
324
  };
325
325
  let poll2fut = async {
326
326
  let res = core.poll_workflow_activation("q2").await.unwrap();
327
- core.complete_workflow_activation(WfActivationCompletion::empty("q2", res.run_id))
327
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty("q2", res.run_id))
328
328
  .await
329
329
  .unwrap();
330
330
  };
@@ -336,3 +336,90 @@ async fn worker_shutdown_during_multiple_poll_doesnt_deadlock(
336
336
  tokio::join!(pollfut, poll2fut, shutdownfut);
337
337
  core.shutdown().await;
338
338
  }
339
+
340
+ #[rstest]
341
+ #[tokio::test]
342
+ async fn can_shutdown_local_act_only_worker_when_act_polling(
343
+ #[values(true, false)] whole_core_shutdown: bool,
344
+ ) {
345
+ let t = canned_histories::single_timer("1");
346
+ let mock = mock_gateway();
347
+ let mh = MockPollCfg::from_resp_batches("fakeid", t, [1], mock);
348
+ let mut mock = build_mock_pollers(mh);
349
+ mock.worker_cfg(TEST_Q, |w| {
350
+ w.no_remote_activities = true;
351
+ });
352
+ let core = mock_core(mock);
353
+ let barrier = Barrier::new(2);
354
+
355
+ tokio::join!(
356
+ async {
357
+ barrier.wait().await;
358
+ if whole_core_shutdown {
359
+ core.shutdown().await;
360
+ } else {
361
+ core.shutdown_worker(TEST_Q).await;
362
+ }
363
+ },
364
+ async {
365
+ let res = core.poll_workflow_activation(TEST_Q).await.unwrap();
366
+ // Complete so there's no outstanding WFT and shutdown can finish
367
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(
368
+ TEST_Q, res.run_id,
369
+ ))
370
+ .await
371
+ .unwrap();
372
+ barrier.wait().await;
373
+ assert_matches!(
374
+ core.poll_activity_task(TEST_Q).await.unwrap_err(),
375
+ PollActivityError::ShutDown
376
+ );
377
+ }
378
+ );
379
+ }
380
+
381
+ #[tokio::test]
382
+ async fn complete_with_task_not_found_during_shutdwn() {
383
+ let t = canned_histories::single_timer("1");
384
+ let mut mock = mock_gateway();
385
+ mock.expect_complete_workflow_task()
386
+ .times(1)
387
+ .returning(|_| Err(tonic::Status::not_found("Workflow task not found.")));
388
+ let mh = MockPollCfg::from_resp_batches("fakeid", t, [1], mock);
389
+ let core = mock_core(build_mock_pollers(mh));
390
+
391
+ let res = core.poll_workflow_activation(TEST_Q).await.unwrap();
392
+ assert_eq!(res.jobs.len(), 1);
393
+
394
+ let complete_order = RefCell::new(vec![]);
395
+ // Initiate shutdown before completing the activation
396
+ let shutdown_fut = async {
397
+ core.shutdown().await;
398
+ complete_order.borrow_mut().push(3);
399
+ };
400
+ let poll_fut = async {
401
+ // This should *not* return shutdown, but instead should do nothing until the complete
402
+ // goes through, at which point it will return the eviction.
403
+ let res = core.poll_workflow_activation(TEST_Q).await.unwrap();
404
+ assert_matches!(
405
+ res.jobs[0].variant,
406
+ Some(workflow_activation_job::Variant::RemoveFromCache(_))
407
+ );
408
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(TEST_Q, res.run_id))
409
+ .await
410
+ .unwrap();
411
+ complete_order.borrow_mut().push(2);
412
+ };
413
+ let complete_fut = async {
414
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
415
+ TEST_Q,
416
+ res.run_id,
417
+ vec![start_timer_cmd(1, Duration::from_secs(1))],
418
+ ))
419
+ .await
420
+ .unwrap();
421
+ complete_order.borrow_mut().push(1);
422
+ };
423
+ tokio::join!(shutdown_fut, poll_fut, complete_fut);
424
+ assert_eq!(&complete_order.into_inner(), &[1, 2, 3])
425
+ }
@@ -6,12 +6,14 @@ use crate::{
6
6
  workflow::WorkflowCachingPolicy::NonSticky,
7
7
  };
8
8
  use rstest::rstest;
9
+ use std::time::Duration;
9
10
  use temporal_sdk_core_protos::coresdk::{
10
- workflow_activation::{wf_activation_job, WfActivationJob},
11
+ workflow_activation::{workflow_activation_job, WorkflowActivationJob},
11
12
  workflow_commands::{
12
- CancelWorkflowExecution, CompleteWorkflowExecution, FailWorkflowExecution, StartTimer,
13
+ CancelWorkflowExecution, CompleteWorkflowExecution, FailWorkflowExecution,
13
14
  },
14
15
  };
16
+ use temporal_sdk_core_test_utils::start_timer_cmd;
15
17
 
16
18
  enum CompletionType {
17
19
  Complete,
@@ -56,17 +58,13 @@ async fn timer_then_cancel_req(
56
58
  NonSticky,
57
59
  &[
58
60
  gen_assert_and_reply(
59
- &job_assert!(wf_activation_job::Variant::StartWorkflow(_)),
60
- vec![StartTimer {
61
- seq: timer_seq,
62
- ..Default::default()
63
- }
64
- .into()],
61
+ &job_assert!(workflow_activation_job::Variant::StartWorkflow(_)),
62
+ vec![start_timer_cmd(timer_seq, Duration::from_secs(1))],
65
63
  ),
66
64
  gen_assert_and_reply(
67
65
  &job_assert!(
68
- wf_activation_job::Variant::FireTimer(_),
69
- wf_activation_job::Variant::CancelWorkflow(_)
66
+ workflow_activation_job::Variant::FireTimer(_),
67
+ workflow_activation_job::Variant::CancelWorkflow(_)
70
68
  ),
71
69
  vec![final_cmd],
72
70
  ),
@@ -86,26 +84,18 @@ async fn timer_then_cancel_req_then_timer_then_cancelled() {
86
84
  NonSticky,
87
85
  &[
88
86
  gen_assert_and_reply(
89
- &job_assert!(wf_activation_job::Variant::StartWorkflow(_)),
90
- vec![StartTimer {
91
- seq: 1,
92
- ..Default::default()
93
- }
94
- .into()],
87
+ &job_assert!(workflow_activation_job::Variant::StartWorkflow(_)),
88
+ vec![start_timer_cmd(1, Duration::from_secs(1))],
95
89
  ),
96
90
  gen_assert_and_reply(
97
91
  &job_assert!(
98
- wf_activation_job::Variant::FireTimer(_),
99
- wf_activation_job::Variant::CancelWorkflow(_)
92
+ workflow_activation_job::Variant::FireTimer(_),
93
+ workflow_activation_job::Variant::CancelWorkflow(_)
100
94
  ),
101
- vec![StartTimer {
102
- seq: 2,
103
- ..Default::default()
104
- }
105
- .into()],
95
+ vec![start_timer_cmd(2, Duration::from_secs(1))],
106
96
  ),
107
97
  gen_assert_and_reply(
108
- &job_assert!(wf_activation_job::Variant::FireTimer(_)),
98
+ &job_assert!(workflow_activation_job::Variant::FireTimer(_)),
109
99
  vec![CancelWorkflowExecution::default().into()],
110
100
  ),
111
101
  ],
@@ -124,8 +114,8 @@ async fn immediate_cancel() {
124
114
  NonSticky,
125
115
  &[gen_assert_and_reply(
126
116
  &job_assert!(
127
- wf_activation_job::Variant::StartWorkflow(_),
128
- wf_activation_job::Variant::CancelWorkflow(_)
117
+ workflow_activation_job::Variant::StartWorkflow(_),
118
+ workflow_activation_job::Variant::CancelWorkflow(_)
129
119
  ),
130
120
  vec![CancelWorkflowExecution {}.into()],
131
121
  )],