@temporalio/core-bridge 1.5.2 → 1.7.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 (194) hide show
  1. package/Cargo.lock +304 -112
  2. package/lib/index.d.ts +8 -6
  3. package/lib/index.js.map +1 -1
  4. package/package.json +9 -4
  5. package/releases/aarch64-apple-darwin/index.node +0 -0
  6. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  7. package/releases/x86_64-apple-darwin/index.node +0 -0
  8. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  9. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  10. package/sdk-core/.buildkite/docker/Dockerfile +2 -2
  11. package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
  12. package/sdk-core/.buildkite/pipeline.yml +2 -4
  13. package/sdk-core/.cargo/config.toml +5 -2
  14. package/sdk-core/.github/workflows/heavy.yml +29 -0
  15. package/sdk-core/Cargo.toml +1 -1
  16. package/sdk-core/README.md +20 -10
  17. package/sdk-core/client/src/lib.rs +215 -39
  18. package/sdk-core/client/src/metrics.rs +17 -8
  19. package/sdk-core/client/src/raw.rs +4 -4
  20. package/sdk-core/client/src/retry.rs +32 -20
  21. package/sdk-core/core/Cargo.toml +25 -12
  22. package/sdk-core/core/src/abstractions/take_cell.rs +28 -0
  23. package/sdk-core/core/src/abstractions.rs +204 -14
  24. package/sdk-core/core/src/core_tests/activity_tasks.rs +143 -50
  25. package/sdk-core/core/src/core_tests/child_workflows.rs +6 -5
  26. package/sdk-core/core/src/core_tests/determinism.rs +165 -2
  27. package/sdk-core/core/src/core_tests/local_activities.rs +431 -43
  28. package/sdk-core/core/src/core_tests/queries.rs +34 -16
  29. package/sdk-core/core/src/core_tests/workers.rs +8 -5
  30. package/sdk-core/core/src/core_tests/workflow_tasks.rs +588 -55
  31. package/sdk-core/core/src/ephemeral_server/mod.rs +113 -12
  32. package/sdk-core/core/src/internal_flags.rs +155 -0
  33. package/sdk-core/core/src/lib.rs +16 -9
  34. package/sdk-core/core/src/protosext/mod.rs +1 -1
  35. package/sdk-core/core/src/replay/mod.rs +16 -27
  36. package/sdk-core/core/src/telemetry/log_export.rs +1 -1
  37. package/sdk-core/core/src/telemetry/metrics.rs +69 -35
  38. package/sdk-core/core/src/telemetry/mod.rs +60 -21
  39. package/sdk-core/core/src/telemetry/prometheus_server.rs +19 -13
  40. package/sdk-core/core/src/test_help/mod.rs +73 -14
  41. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +119 -160
  42. package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
  43. package/sdk-core/core/src/worker/activities/local_activities.rs +379 -129
  44. package/sdk-core/core/src/worker/activities.rs +350 -175
  45. package/sdk-core/core/src/worker/client/mocks.rs +22 -2
  46. package/sdk-core/core/src/worker/client.rs +18 -2
  47. package/sdk-core/core/src/worker/mod.rs +183 -64
  48. package/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
  49. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
  50. package/sdk-core/core/src/worker/workflow/history_update.rs +916 -277
  51. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +216 -183
  52. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +9 -12
  53. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +7 -9
  54. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +160 -87
  55. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +13 -14
  56. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -9
  57. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +14 -17
  58. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +242 -110
  59. package/sdk-core/core/src/worker/workflow/machines/mod.rs +27 -19
  60. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +9 -11
  61. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +321 -206
  62. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +13 -18
  63. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +20 -29
  64. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  65. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +257 -51
  66. package/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
  67. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +310 -150
  68. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +17 -20
  69. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +31 -15
  70. package/sdk-core/core/src/worker/workflow/managed_run.rs +1052 -380
  71. package/sdk-core/core/src/worker/workflow/mod.rs +598 -390
  72. package/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
  73. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +137 -0
  74. package/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
  75. package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
  76. package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
  77. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +469 -718
  78. package/sdk-core/core-api/Cargo.toml +2 -1
  79. package/sdk-core/core-api/src/errors.rs +1 -34
  80. package/sdk-core/core-api/src/lib.rs +19 -9
  81. package/sdk-core/core-api/src/telemetry.rs +4 -6
  82. package/sdk-core/core-api/src/worker.rs +19 -1
  83. package/sdk-core/etc/deps.svg +115 -140
  84. package/sdk-core/etc/regen-depgraph.sh +5 -0
  85. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +86 -61
  86. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +29 -71
  87. package/sdk-core/histories/ends_empty_wft_complete.bin +0 -0
  88. package/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  89. package/sdk-core/histories/old_change_marker_format.bin +0 -0
  90. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +2 -1
  91. package/sdk-core/protos/api_upstream/Makefile +6 -6
  92. package/sdk-core/protos/api_upstream/build/go.mod +7 -0
  93. package/sdk-core/protos/api_upstream/build/go.sum +5 -0
  94. package/sdk-core/protos/api_upstream/build/tools.go +29 -0
  95. package/sdk-core/protos/api_upstream/go.mod +6 -0
  96. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +9 -2
  97. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +7 -26
  98. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
  99. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
  100. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +3 -7
  101. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
  102. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +8 -8
  103. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +25 -2
  104. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
  105. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
  106. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
  107. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
  108. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
  109. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
  110. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
  111. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
  112. package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
  113. package/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
  114. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +49 -26
  115. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
  116. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +5 -2
  117. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -2
  118. package/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
  119. package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
  120. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
  121. package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
  122. package/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
  123. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
  124. package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
  125. package/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
  126. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -2
  127. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -28
  128. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -4
  129. package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +7 -8
  130. package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +10 -7
  131. package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +19 -30
  132. package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
  133. package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
  134. package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +8 -0
  135. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +67 -60
  136. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +85 -84
  137. package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +9 -3
  138. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
  139. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
  140. package/sdk-core/sdk/Cargo.toml +5 -4
  141. package/sdk-core/sdk/src/lib.rs +108 -26
  142. package/sdk-core/sdk/src/workflow_context/options.rs +7 -1
  143. package/sdk-core/sdk/src/workflow_context.rs +24 -17
  144. package/sdk-core/sdk/src/workflow_future.rs +16 -15
  145. package/sdk-core/sdk-core-protos/Cargo.toml +5 -2
  146. package/sdk-core/sdk-core-protos/build.rs +36 -2
  147. package/sdk-core/sdk-core-protos/src/history_builder.rs +138 -106
  148. package/sdk-core/sdk-core-protos/src/history_info.rs +10 -1
  149. package/sdk-core/sdk-core-protos/src/lib.rs +272 -87
  150. package/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
  151. package/sdk-core/test-utils/Cargo.toml +3 -1
  152. package/sdk-core/test-utils/src/canned_histories.rs +106 -296
  153. package/sdk-core/test-utils/src/histfetch.rs +1 -1
  154. package/sdk-core/test-utils/src/lib.rs +82 -23
  155. package/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
  156. package/sdk-core/test-utils/src/workflows.rs +29 -0
  157. package/sdk-core/tests/fuzzy_workflow.rs +130 -0
  158. package/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
  159. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
  160. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
  161. package/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
  162. package/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
  163. package/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
  164. package/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
  165. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +161 -72
  166. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
  167. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
  168. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +80 -3
  169. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
  170. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
  171. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +94 -200
  172. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +2 -4
  173. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +34 -28
  174. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +76 -7
  175. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
  176. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
  177. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
  178. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
  179. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +7 -8
  180. package/sdk-core/tests/integ_tests/workflow_tests.rs +13 -14
  181. package/sdk-core/tests/main.rs +3 -13
  182. package/sdk-core/tests/runner.rs +75 -36
  183. package/sdk-core/tests/wf_input_replay.rs +32 -0
  184. package/src/conversions.rs +14 -8
  185. package/src/runtime.rs +9 -8
  186. package/ts/index.ts +8 -6
  187. package/sdk-core/bridge-ffi/Cargo.toml +0 -24
  188. package/sdk-core/bridge-ffi/LICENSE.txt +0 -23
  189. package/sdk-core/bridge-ffi/build.rs +0 -25
  190. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -224
  191. package/sdk-core/bridge-ffi/src/lib.rs +0 -746
  192. package/sdk-core/bridge-ffi/src/wrappers.rs +0 -221
  193. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
  194. package/sdk-core/sdk/src/conversions.rs +0 -8
@@ -1,3 +1,4 @@
1
+ use crate::integ_tests::workflow_tests::patches::changes_wf;
1
2
  use assert_matches::assert_matches;
2
3
  use parking_lot::Mutex;
3
4
  use std::{collections::HashSet, sync::Arc, time::Duration};
@@ -10,6 +11,7 @@ use temporal_sdk_core_protos::{
10
11
  workflow_commands::{ScheduleActivity, StartTimer},
11
12
  workflow_completion::WorkflowActivationCompletion,
12
13
  },
14
+ temporal::api::enums::v1::EventType,
13
15
  TestHistoryBuilder, DEFAULT_WORKFLOW_TYPE,
14
16
  };
15
17
  use temporal_sdk_core_test_utils::{
@@ -130,17 +132,39 @@ async fn replay_using_wf_function() {
130
132
  }
131
133
 
132
134
  #[tokio::test]
133
- async fn replay_ok_ending_with_terminated_or_timed_out() {
135
+ async fn replay_ending_wft_complete_with_commands_but_no_scheduled_started() {
136
+ let mut t = TestHistoryBuilder::default();
137
+ t.add_by_type(EventType::WorkflowExecutionStarted);
138
+ t.add_full_wf_task();
139
+
140
+ for i in 1..=2 {
141
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
142
+ t.add_timer_fired(timer_started_event_id, i.to_string());
143
+ t.add_full_wf_task();
144
+ }
145
+ let func = timers_wf(3);
146
+ let mut worker = replay_sdk_worker([test_hist_to_replay(t)]);
147
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
148
+ worker.run().await.unwrap();
149
+ }
150
+
151
+ async fn replay_abrupt_ending(t: TestHistoryBuilder) {
152
+ let func = timers_wf(1);
153
+ let mut worker = replay_sdk_worker([test_hist_to_replay(t)]);
154
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
155
+ worker.run().await.unwrap();
156
+ }
157
+ #[tokio::test]
158
+ async fn replay_ok_ending_with_terminated() {
134
159
  let mut t1 = canned_histories::single_timer("1");
135
160
  t1.add_workflow_execution_terminated();
161
+ replay_abrupt_ending(t1).await;
162
+ }
163
+ #[tokio::test]
164
+ async fn replay_ok_ending_with_timed_out() {
136
165
  let mut t2 = canned_histories::single_timer("1");
137
166
  t2.add_workflow_execution_timed_out();
138
- for t in [t1, t2] {
139
- let func = timers_wf(1);
140
- let mut worker = replay_sdk_worker([test_hist_to_replay(t)]);
141
- worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
142
- worker.run().await.unwrap();
143
- }
167
+ replay_abrupt_ending(t2).await;
144
168
  }
145
169
 
146
170
  #[rstest::rstest]
@@ -200,6 +224,51 @@ async fn multiple_histories_can_handle_dupe_run_ids() {
200
224
  worker.run().await.unwrap();
201
225
  }
202
226
 
227
+ // Verifies SDK can decode patch markers before changing them to use json encoding
228
+ #[tokio::test]
229
+ async fn replay_old_patch_format() {
230
+ let mut worker = replay_sdk_worker([HistoryForReplay::new(
231
+ history_from_proto_binary("histories/old_change_marker_format.bin")
232
+ .await
233
+ .unwrap(),
234
+ "fake".to_owned(),
235
+ )]);
236
+ worker.register_wf("writes_change_markers", changes_wf);
237
+ worker.run().await.unwrap();
238
+ }
239
+
240
+ #[tokio::test]
241
+ async fn replay_ends_with_empty_wft() {
242
+ let core = init_core_replay_preloaded(
243
+ "SayHelloWorkflow",
244
+ [HistoryForReplay::new(
245
+ history_from_proto_binary("histories/ends_empty_wft_complete.bin")
246
+ .await
247
+ .unwrap(),
248
+ "fake".to_owned(),
249
+ )],
250
+ );
251
+ let task = core.poll_workflow_activation().await.unwrap();
252
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
253
+ task.run_id,
254
+ vec![ScheduleActivity {
255
+ seq: 1,
256
+ activity_id: "1".to_string(),
257
+ activity_type: "say_hello".to_string(),
258
+ ..Default::default()
259
+ }
260
+ .into()],
261
+ ))
262
+ .await
263
+ .unwrap();
264
+ let task = core.poll_workflow_activation().await.unwrap();
265
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
266
+ .await
267
+ .unwrap();
268
+ let task = core.poll_workflow_activation().await.unwrap();
269
+ assert!(task.eviction_reason().is_some());
270
+ }
271
+
203
272
  fn timers_wf(num_timers: u32) -> WorkflowFunction {
204
273
  WorkflowFunction::new(move |ctx: WfContext| async move {
205
274
  for _ in 1..=num_timers {
@@ -14,6 +14,7 @@ const POST_RESET_SIG: &str = "post-reset";
14
14
  async fn reset_workflow() {
15
15
  let wf_name = "reset_me_wf";
16
16
  let mut starter = CoreWfStarter::new(wf_name);
17
+ starter.no_remote_activities();
17
18
  let mut worker = starter.worker().await;
18
19
  worker.fetch_results = false;
19
20
  let notify = Arc::new(Notify::new());
@@ -1,7 +1,9 @@
1
1
  use std::collections::HashMap;
2
2
 
3
3
  use futures::StreamExt;
4
- use temporal_client::{WorkflowClientTrait, WorkflowExecutionInfo, WorkflowOptions};
4
+ use temporal_client::{
5
+ SignalWithStartOptions, WorkflowClientTrait, WorkflowExecutionInfo, WorkflowOptions,
6
+ };
5
7
  use temporal_sdk::{
6
8
  ChildWorkflowOptions, Signal, SignalWorkflowOptions, WfContext, WorkflowResult,
7
9
  };
@@ -32,6 +34,7 @@ async fn signal_sender(ctx: WfContext) -> WorkflowResult<()> {
32
34
  async fn sends_signal_to_missing_wf() {
33
35
  let wf_name = "sends_signal_to_missing_wf";
34
36
  let mut starter = CoreWfStarter::new(wf_name);
37
+ starter.no_remote_activities();
35
38
  let mut worker = starter.worker().await;
36
39
  worker.register_wf(wf_name.to_owned(), signal_sender);
37
40
 
@@ -59,7 +62,6 @@ async fn signal_receiver(ctx: WfContext) -> WorkflowResult<()> {
59
62
 
60
63
  async fn signal_with_create_wf_receiver(ctx: WfContext) -> WorkflowResult<()> {
61
64
  let res = ctx.make_signal_channel(SIGNAME).next().await.unwrap();
62
- println!("HEADER: {:?}", res.headers);
63
65
  assert_eq!(&res.input, &[b"tada".into()]);
64
66
  assert_eq!(
65
67
  *res.headers.get("tupac").expect("tupac header exists"),
@@ -71,6 +73,7 @@ async fn signal_with_create_wf_receiver(ctx: WfContext) -> WorkflowResult<()> {
71
73
  #[tokio::test]
72
74
  async fn sends_signal_to_other_wf() {
73
75
  let mut starter = CoreWfStarter::new("sends_signal_to_other_wf");
76
+ starter.no_remote_activities();
74
77
  let mut worker = starter.worker().await;
75
78
  worker.register_wf("sender", signal_sender);
76
79
  worker.register_wf("receiver", signal_receiver);
@@ -99,24 +102,24 @@ async fn sends_signal_to_other_wf() {
99
102
  #[tokio::test]
100
103
  async fn sends_signal_with_create_wf() {
101
104
  let mut starter = CoreWfStarter::new("sends_signal_with_create_wf");
105
+ starter.no_remote_activities();
102
106
  let mut worker = starter.worker().await;
103
- worker.register_wf("receiversignal", signal_with_create_wf_receiver);
107
+ worker.register_wf("receiver_signal", signal_with_create_wf_receiver);
104
108
 
105
109
  let client = starter.get_client().await;
106
110
  let mut header: HashMap<String, Payload> = HashMap::new();
107
111
  header.insert("tupac".into(), "shakur".into());
112
+ let options = SignalWithStartOptions::builder()
113
+ .task_queue(worker.inner_mut().task_queue())
114
+ .workflow_id("sends_signal_with_create_wf")
115
+ .workflow_type("receiver_signal")
116
+ .signal_name(SIGNAME)
117
+ .signal_input(vec![b"tada".into()].into_payloads())
118
+ .signal_header(header.into())
119
+ .build()
120
+ .unwrap();
108
121
  let res = client
109
- .signal_with_start_workflow_execution(
110
- None,
111
- worker.inner_mut().task_queue().to_owned(),
112
- "sends_signal_with_create_wf".to_owned(),
113
- "receiversignal".to_owned(),
114
- None,
115
- WorkflowOptions::default(),
116
- SIGNAME.to_owned(),
117
- vec![b"tada".into()].into_payloads(),
118
- Some(header.into()),
119
- )
122
+ .signal_with_start_workflow_execution(options, WorkflowOptions::default())
120
123
  .await
121
124
  .expect("request succeeds.qed");
122
125
 
@@ -150,6 +153,7 @@ async fn signals_child(ctx: WfContext) -> WorkflowResult<()> {
150
153
  #[tokio::test]
151
154
  async fn sends_signal_to_child() {
152
155
  let mut starter = CoreWfStarter::new("sends_signal_to_child");
156
+ starter.no_remote_activities();
153
157
  let mut worker = starter.worker().await;
154
158
  worker.register_wf("child_signaler", signals_child);
155
159
  worker.register_wf("child_receiver", signal_receiver);
@@ -12,19 +12,12 @@ use tokio::sync::Barrier;
12
12
  async fn timer_workflow_not_sticky() {
13
13
  let wf_name = "timer_wf_not_sticky";
14
14
  let mut starter = CoreWfStarter::new(wf_name);
15
+ starter.no_remote_activities();
15
16
  starter.max_cached_workflows(0);
16
17
  let mut worker = starter.worker().await;
17
18
  worker.register_wf(wf_name.to_owned(), timer_wf);
18
19
 
19
- worker
20
- .submit_wf(
21
- wf_name.to_owned(),
22
- wf_name.to_owned(),
23
- vec![],
24
- WorkflowOptions::default(),
25
- )
26
- .await
27
- .unwrap();
20
+ starter.start_with_worker(wf_name, &mut worker).await;
28
21
  worker.run_until_done().await.unwrap();
29
22
  }
30
23
 
@@ -47,19 +40,12 @@ async fn timer_workflow_timeout_on_sticky() {
47
40
  // on a not-sticky queue
48
41
  let wf_name = "timer_workflow_timeout_on_sticky";
49
42
  let mut starter = CoreWfStarter::new(wf_name);
50
- starter.wft_timeout(Duration::from_secs(2));
43
+ starter.no_remote_activities();
44
+ starter.workflow_options.task_timeout = Some(Duration::from_secs(2));
51
45
  let mut worker = starter.worker().await;
52
46
  worker.register_wf(wf_name.to_owned(), timer_timeout_wf);
53
47
 
54
- worker
55
- .submit_wf(
56
- wf_name.to_owned(),
57
- wf_name.to_owned(),
58
- vec![],
59
- WorkflowOptions::default(),
60
- )
61
- .await
62
- .unwrap();
48
+ starter.start_with_worker(wf_name, &mut worker).await;
63
49
  worker.run_until_done().await.unwrap();
64
50
  // If it didn't run twice it didn't time out
65
51
  assert_eq!(RUN_CT.load(Ordering::SeqCst), 2);
@@ -69,7 +55,7 @@ async fn timer_workflow_timeout_on_sticky() {
69
55
  async fn cache_miss_ok() {
70
56
  let wf_name = "cache_miss_ok";
71
57
  let mut starter = CoreWfStarter::new(wf_name);
72
- starter.max_wft(1);
58
+ starter.no_remote_activities().max_wft(1);
73
59
  let mut worker = starter.worker().await;
74
60
 
75
61
  let barr: &'static Barrier = Box::leak(Box::new(Barrier::new(2)));
@@ -1,12 +1,13 @@
1
1
  use std::time::Duration;
2
- use temporal_client::WorkflowOptions;
2
+
3
3
  use temporal_sdk::{WfContext, WorkflowResult};
4
4
  use temporal_sdk_core_protos::coresdk::{
5
5
  workflow_commands::{CancelTimer, CompleteWorkflowExecution, StartTimer},
6
6
  workflow_completion::WorkflowActivationCompletion,
7
7
  };
8
8
  use temporal_sdk_core_test_utils::{
9
- init_core_and_create_wf, start_timer_cmd, CoreWfStarter, WorkerTestHelpers,
9
+ drain_pollers_and_shutdown, init_core_and_create_wf, start_timer_cmd, CoreWfStarter,
10
+ WorkerTestHelpers,
10
11
  };
11
12
 
12
13
  pub async fn timer_wf(command_sink: WfContext) -> WorkflowResult<()> {
@@ -18,18 +19,11 @@ pub async fn timer_wf(command_sink: WfContext) -> WorkflowResult<()> {
18
19
  async fn timer_workflow_workflow_driver() {
19
20
  let wf_name = "timer_wf_new";
20
21
  let mut starter = CoreWfStarter::new(wf_name);
22
+ starter.no_remote_activities();
21
23
  let mut worker = starter.worker().await;
22
24
  worker.register_wf(wf_name.to_owned(), timer_wf);
23
25
 
24
- worker
25
- .submit_wf(
26
- wf_name.to_owned(),
27
- wf_name.to_owned(),
28
- vec![],
29
- WorkflowOptions::default(),
30
- )
31
- .await
32
- .unwrap();
26
+ starter.start_with_worker(wf_name, &mut worker).await;
33
27
  worker.run_until_done().await.unwrap();
34
28
  }
35
29
 
@@ -37,6 +31,7 @@ async fn timer_workflow_workflow_driver() {
37
31
  async fn timer_workflow_manual() {
38
32
  let mut starter = init_core_and_create_wf("timer_workflow").await;
39
33
  let core = starter.get_worker().await;
34
+ starter.no_remote_activities();
40
35
  let task = core.poll_workflow_activation().await.unwrap();
41
36
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
42
37
  task.run_id,
@@ -50,13 +45,14 @@ async fn timer_workflow_manual() {
50
45
  .unwrap();
51
46
  let task = core.poll_workflow_activation().await.unwrap();
52
47
  core.complete_execution(&task.run_id).await;
53
- core.shutdown().await;
48
+ drain_pollers_and_shutdown(&core).await;
54
49
  }
55
50
 
56
51
  #[tokio::test]
57
52
  async fn timer_cancel_workflow() {
58
53
  let mut starter = init_core_and_create_wf("timer_cancel_workflow").await;
59
54
  let core = starter.get_worker().await;
55
+ starter.no_remote_activities();
60
56
  let task = core.poll_workflow_activation().await.unwrap();
61
57
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
62
58
  task.run_id,
@@ -115,17 +111,10 @@ async fn parallel_timer_wf(command_sink: WfContext) -> WorkflowResult<()> {
115
111
  async fn parallel_timers() {
116
112
  let wf_name = "parallel_timers";
117
113
  let mut starter = CoreWfStarter::new(wf_name);
114
+ starter.no_remote_activities();
118
115
  let mut worker = starter.worker().await;
119
116
  worker.register_wf(wf_name.to_owned(), parallel_timer_wf);
120
117
 
121
- worker
122
- .submit_wf(
123
- wf_name.to_owned(),
124
- wf_name.to_owned(),
125
- vec![],
126
- WorkflowOptions::default(),
127
- )
128
- .await
129
- .unwrap();
118
+ starter.start_with_worker(wf_name, &mut worker).await;
130
119
  worker.run_until_done().await.unwrap();
131
120
  }
@@ -1,9 +1,9 @@
1
- use log::warn;
2
1
  use std::{collections::HashMap, env};
3
2
  use temporal_client::{WorkflowClientTrait, WorkflowOptions};
4
3
  use temporal_sdk::{WfContext, WorkflowResult};
5
4
  use temporal_sdk_core_protos::coresdk::{AsJsonPayloadExt, FromJsonPayloadExt};
6
- use temporal_sdk_core_test_utils::{CoreWfStarter, INTEG_TEMPORALITE_USED_ENV_VAR};
5
+ use temporal_sdk_core_test_utils::{CoreWfStarter, INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR};
6
+ use tracing::warn;
7
7
  use uuid::Uuid;
8
8
 
9
9
  // These are initialized on the server as part of the autosetup container which we
@@ -24,9 +24,11 @@ async fn sends_upsert() {
24
24
  let wf_name = "sends_upsert_search_attrs";
25
25
  let wf_id = Uuid::new_v4();
26
26
  let mut starter = CoreWfStarter::new(wf_name);
27
+ starter.no_remote_activities();
27
28
  let mut worker = starter.worker().await;
28
- if env::var(INTEG_TEMPORALITE_USED_ENV_VAR).is_ok() {
29
- warn!("skipping sends_upsert -- does not work on temporalite");
29
+ // TODO: this should be supported in server 1.20, remove this condition when CLI is upgraded.
30
+ if env::var(INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR).is_ok() {
31
+ warn!("skipping sends_upsert -- does not work on temporal dev server");
30
32
  return;
31
33
  }
32
34
 
@@ -62,10 +64,7 @@ async fn sends_upsert() {
62
64
  let txt_attr_payload = search_attrs.get(TXT_ATTR).unwrap();
63
65
  let int_attr_payload = search_attrs.get(INT_ATTR).unwrap();
64
66
  for payload in [txt_attr_payload, int_attr_payload] {
65
- assert_eq!(
66
- &b"json/plain".to_vec(),
67
- payload.metadata.get("encoding").unwrap()
68
- );
67
+ assert!(payload.is_json_payload());
69
68
  }
70
69
  assert_eq!(
71
70
  "goodbye",
@@ -42,8 +42,8 @@ use temporal_sdk_core_protos::{
42
42
  temporal::api::{failure::v1::Failure, history::v1::history_event},
43
43
  };
44
44
  use temporal_sdk_core_test_utils::{
45
- history_from_proto_binary, init_core_and_create_wf, init_core_replay_preloaded,
46
- schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
45
+ drain_pollers_and_shutdown, history_from_proto_binary, init_core_and_create_wf,
46
+ init_core_replay_preloaded, schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
47
47
  };
48
48
  use tokio::time::sleep;
49
49
  use uuid::Uuid;
@@ -58,8 +58,7 @@ async fn parallel_workflows_same_queue() {
58
58
  let num_workflows = 25usize;
59
59
 
60
60
  let run_ids: Vec<_> = future::join_all(
61
- (0..num_workflows)
62
- .map(|i| starter.start_wf_with_id(format!("wf-id-{}", i), WorkflowOptions::default())),
61
+ (0..num_workflows).map(|i| starter.start_wf_with_id(format!("wf-id-{i}"))),
63
62
  )
64
63
  .await;
65
64
 
@@ -104,7 +103,7 @@ async fn parallel_workflows_same_queue() {
104
103
  for handle in handles {
105
104
  handle.await.unwrap()
106
105
  }
107
- core.shutdown().await;
106
+ drain_pollers_and_shutdown(&core).await;
108
107
  }
109
108
 
110
109
  static RUN_CT: AtomicUsize = AtomicUsize::new(0);
@@ -118,7 +117,7 @@ pub async fn cache_evictions_wf(command_sink: WfContext) -> WorkflowResult<()> {
118
117
  async fn workflow_lru_cache_evictions() {
119
118
  let wf_type = "workflow_lru_cache_evictions";
120
119
  let mut starter = CoreWfStarter::new(wf_type);
121
- starter.max_cached_workflows(1);
120
+ starter.no_remote_activities().max_cached_workflows(1);
122
121
  let mut worker = starter.worker().await;
123
122
  worker.register_wf(wf_type.to_string(), cache_evictions_wf);
124
123
 
@@ -163,7 +162,7 @@ async fn shutdown_aborts_actively_blocked_poll() {
163
162
  let tcore = core.clone();
164
163
  let handle = tokio::spawn(async move {
165
164
  std::thread::sleep(Duration::from_millis(100));
166
- tcore.shutdown().await;
165
+ drain_pollers_and_shutdown(&tcore).await;
167
166
  });
168
167
  assert_matches!(
169
168
  core.poll_workflow_activation().await.unwrap_err(),
@@ -415,11 +414,11 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
415
414
  res.jobs.as_slice(),
416
415
  [
417
416
  WorkflowActivationJob {
418
- variant: Some(workflow_activation_job::Variant::FireTimer(_)),
417
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
419
418
  },
420
419
  WorkflowActivationJob {
421
- variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
422
- }
420
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
421
+ },
423
422
  ]
424
423
  );
425
424
  core.complete_execution(&res.run_id).await;
@@ -435,8 +434,8 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
435
434
  wf_starter
436
435
  // Test needs eviction on and a short timeout
437
436
  .max_cached_workflows(0)
438
- .max_wft(1)
439
- .wft_timeout(Duration::from_secs(1));
437
+ .max_wft(1);
438
+ wf_starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
440
439
  let core = wf_starter.get_worker().await;
441
440
  let client = wf_starter.get_client().await;
442
441
  let task_q = wf_starter.get_task_queue();
@@ -460,7 +459,7 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
460
459
  .unwrap();
461
460
  wf_task
462
461
  };
463
- wf_starter.start_wf().await;
462
+ wf_starter.start_wf_with_id(wf_id.to_string()).await;
464
463
 
465
464
  // Poll and schedule the activity
466
465
  let wf_task = poll_sched_act().await;
@@ -572,7 +571,7 @@ async fn slow_completes_with_small_cache() {
572
571
  for i in 0..20 {
573
572
  worker
574
573
  .submit_wf(
575
- format!("{}_{}", wf_name, i),
574
+ format!("{wf_name}_{i}"),
576
575
  wf_name.to_owned(),
577
576
  vec![],
578
577
  WorkflowOptions::default(),
@@ -1,22 +1,12 @@
1
1
  //! Integration tests
2
- //!
3
- //! Note that integ tests which want to use the server (nearly all of them) *need* to use the
4
- //! `#[rstest]` macro and accept the TODO fixture to support auto setup & teardown of ephemeral
5
- //! local servers.
6
2
 
7
3
  #[macro_use]
8
4
  extern crate rstest;
5
+ #[macro_use]
6
+ extern crate temporal_sdk_core_test_utils;
9
7
 
10
8
  #[cfg(test)]
11
9
  mod integ_tests {
12
- #[macro_export]
13
- macro_rules! prost_dur {
14
- ($dur_call:ident $args:tt) => {
15
- std::time::Duration::$dur_call$args
16
- .try_into()
17
- .expect("test duration fits")
18
- };
19
- }
20
10
  mod client_tests;
21
11
  mod ephemeral_server_tests;
22
12
  mod heartbeat_tests;
@@ -46,7 +36,7 @@ mod integ_tests {
46
36
  let opts = get_integ_server_options();
47
37
  let runtime = CoreRuntime::new_assume_tokio(get_integ_telem_options()).unwrap();
48
38
  let mut retrying_client = opts
49
- .connect_no_namespace(runtime.metric_meter(), None)
39
+ .connect_no_namespace(runtime.metric_meter().as_deref(), None)
50
40
  .await
51
41
  .unwrap();
52
42
 
@@ -1,62 +1,101 @@
1
1
  use anyhow::{anyhow, bail};
2
+ use clap::Parser;
2
3
  use std::{
3
4
  env,
4
- env::args,
5
5
  path::{Path, PathBuf},
6
6
  process::Stdio,
7
7
  };
8
- use temporal_sdk_core::ephemeral_server::{TemporaliteConfigBuilder, TestServerConfigBuilder};
8
+ use temporal_sdk_core::ephemeral_server::{
9
+ TemporalDevServerConfigBuilder, TestServerConfigBuilder,
10
+ };
9
11
  use temporal_sdk_core_test_utils::{
10
- default_cached_download, INTEG_SERVER_TARGET_ENV_VAR, INTEG_TEMPORALITE_USED_ENV_VAR,
12
+ default_cached_download, INTEG_SERVER_TARGET_ENV_VAR, INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR,
11
13
  INTEG_TEST_SERVER_USED_ENV_VAR,
12
14
  };
13
15
  use tokio::{self, process::Command};
14
16
 
17
+ #[derive(clap::Parser)]
18
+ #[command(author, version, about, long_about = None)]
19
+ struct Cli {
20
+ /// Test harness to run. Anything defined as a `[[test]]` in core's `Cargo.toml` is valid.
21
+ #[arg(short, long, default_value = "integ_tests")]
22
+ test_name: String,
23
+
24
+ /// What kind of server to auto-launch, if any
25
+ #[arg(short, long, value_enum, default_value = "temporal-cli")]
26
+ server_kind: ServerKind,
27
+
28
+ /// Arguments to pass through to the `cargo test` command. Ex: `--release`
29
+ #[arg(short, long, allow_hyphen_values(true))]
30
+ cargo_test_args: Vec<String>,
31
+
32
+ /// The rest of the arguments will be passed through to the test harness
33
+ harness_args: Vec<String>,
34
+ }
35
+
36
+ #[derive(Copy, Clone, PartialEq, Eq, clap::ValueEnum)]
37
+ enum ServerKind {
38
+ /// Use Temporal-cli
39
+ TemporalCLI,
40
+ /// Use the Java test server
41
+ TestServer,
42
+ /// Do not automatically start any server
43
+ External,
44
+ }
45
+
15
46
  #[tokio::main]
16
47
  async fn main() -> Result<(), anyhow::Error> {
48
+ let Cli {
49
+ test_name,
50
+ server_kind,
51
+ cargo_test_args,
52
+ harness_args,
53
+ } = Cli::parse();
17
54
  let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
18
- let server_type = env::var("INTEG_SERVER_TYPE")
19
- .unwrap_or_else(|_| "temporalite".to_string())
20
- .to_lowercase();
21
55
  // Try building first, so that we error early on build failures & don't start server
56
+ let test_args_preamble = ["test", "--test", &test_name]
57
+ .into_iter()
58
+ .map(ToString::to_string)
59
+ .chain(cargo_test_args)
60
+ .collect::<Vec<_>>();
22
61
  let status = Command::new(&cargo)
23
- .args(["test", "--test", "integ_tests", "--no-run"])
62
+ .args([test_args_preamble.as_slice(), &["--no-run".to_string()]].concat())
24
63
  .status()
25
64
  .await?;
26
65
  if !status.success() {
27
66
  bail!("Building integration tests failed!");
28
67
  }
29
68
 
30
- // Move to clap if we start doing any more complicated input
31
- let (server, envs) = if server_type == "test-server" {
32
- let config = TestServerConfigBuilder::default()
33
- .exe(default_cached_download())
34
- .build()?;
35
- println!("Using java test server");
36
- (
37
- Some(config.start_server_with_output(Stdio::null()).await?),
38
- vec![(INTEG_TEST_SERVER_USED_ENV_VAR, "true")],
39
- )
40
- } else if server_type == "temporalite" {
41
- let config = TemporaliteConfigBuilder::default()
42
- .exe(default_cached_download())
43
- .build()?;
44
- println!("Using temporalite");
45
- (
46
- Some(config.start_server_with_output(Stdio::null()).await?),
47
- vec![(INTEG_TEMPORALITE_USED_ENV_VAR, "true")],
48
- )
49
- } else {
50
- println!("Not starting up a server. One should be running already.");
51
- (None, vec![])
69
+ let (server, envs) = match server_kind {
70
+ ServerKind::TemporalCLI => {
71
+ let config = TemporalDevServerConfigBuilder::default()
72
+ .exe(default_cached_download())
73
+ .build()?;
74
+ println!("Using temporal CLI");
75
+ (
76
+ Some(config.start_server_with_output(Stdio::null()).await?),
77
+ vec![(INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR, "true")],
78
+ )
79
+ }
80
+ ServerKind::TestServer => {
81
+ let config = TestServerConfigBuilder::default()
82
+ .exe(default_cached_download())
83
+ .build()?;
84
+ println!("Using java test server");
85
+ (
86
+ Some(config.start_server_with_output(Stdio::null()).await?),
87
+ vec![(INTEG_TEST_SERVER_USED_ENV_VAR, "true")],
88
+ )
89
+ }
90
+ ServerKind::External => {
91
+ println!("Not starting up a server. One should be running already.");
92
+ (None, vec![])
93
+ }
52
94
  };
53
95
 
54
- // Run the integ tests, passing through arguments
55
- let mut args = args();
56
- // Shift off binary name
57
- args.next();
58
96
  let mut cmd = Command::new(&cargo);
59
97
  if let Some(srv) = server.as_ref() {
98
+ println!("Running on {}", srv.target);
60
99
  cmd.env(
61
100
  INTEG_SERVER_TARGET_ENV_VAR,
62
101
  format!("http://{}", &srv.target),
@@ -66,10 +105,10 @@ async fn main() -> Result<(), anyhow::Error> {
66
105
  .envs(envs)
67
106
  .current_dir(project_root())
68
107
  .args(
69
- ["test", "--test", "integ_tests"]
108
+ test_args_preamble
70
109
  .into_iter()
71
- .map(ToString::to_string)
72
- .chain(args),
110
+ .chain(["--".to_string()])
111
+ .chain(harness_args),
73
112
  )
74
113
  .status()
75
114
  .await?;
@@ -0,0 +1,32 @@
1
+ use anyhow::Context;
2
+ use clap::Parser;
3
+ use futures_util::StreamExt;
4
+ use std::path::PathBuf;
5
+ use temporal_sdk_core::replay_wf_state_inputs;
6
+ use temporal_sdk_core_test_utils::{init_integ_telem, wf_input_saver::read_from_file};
7
+
8
+ #[derive(clap::Parser)]
9
+ #[command(author, version, about, long_about = None)]
10
+ struct Cli {
11
+ /// Path to file containing the saved wf input data
12
+ replay_data: PathBuf,
13
+ }
14
+
15
+ #[tokio::main]
16
+ async fn main() -> Result<(), anyhow::Error> {
17
+ init_integ_telem();
18
+ let Cli { replay_data } = Cli::parse();
19
+ let replay_dat = read_from_file(replay_data)
20
+ .await
21
+ .context("while reading replay data file")?;
22
+
23
+ replay_wf_state_inputs(
24
+ replay_dat.config,
25
+ replay_dat
26
+ .inputs
27
+ .map(|r| r.expect("Reading bytes from file works").to_vec()),
28
+ )
29
+ .await;
30
+
31
+ Ok(())
32
+ }