@temporalio/core-bridge 1.1.0 → 1.4.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 (124) hide show
  1. package/Cargo.lock +765 -128
  2. package/Cargo.toml +2 -2
  3. package/common.js +7 -3
  4. package/index.d.ts +118 -5
  5. package/index.js +2 -6
  6. package/package.json +2 -3
  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/scripts/build.js +4 -3
  13. package/sdk-core/.buildkite/docker/Dockerfile +2 -1
  14. package/sdk-core/.buildkite/pipeline.yml +2 -0
  15. package/sdk-core/.cargo/config.toml +1 -1
  16. package/sdk-core/ARCHITECTURE.md +2 -2
  17. package/sdk-core/README.md +12 -0
  18. package/sdk-core/bridge-ffi/Cargo.toml +2 -2
  19. package/sdk-core/bridge-ffi/src/lib.rs +2 -2
  20. package/sdk-core/client/Cargo.toml +7 -5
  21. package/sdk-core/client/src/lib.rs +354 -226
  22. package/sdk-core/client/src/metrics.rs +13 -11
  23. package/sdk-core/client/src/raw.rs +352 -107
  24. package/sdk-core/client/src/retry.rs +188 -147
  25. package/sdk-core/client/src/workflow_handle/mod.rs +1 -1
  26. package/sdk-core/core/Cargo.toml +28 -15
  27. package/sdk-core/core/src/core_tests/activity_tasks.rs +98 -33
  28. package/sdk-core/core/src/core_tests/child_workflows.rs +125 -3
  29. package/sdk-core/core/src/core_tests/local_activities.rs +6 -6
  30. package/sdk-core/core/src/core_tests/workers.rs +3 -2
  31. package/sdk-core/core/src/core_tests/workflow_tasks.rs +70 -2
  32. package/sdk-core/core/src/ephemeral_server/mod.rs +515 -0
  33. package/sdk-core/core/src/lib.rs +62 -28
  34. package/sdk-core/core/src/pollers/mod.rs +2 -0
  35. package/sdk-core/core/src/pollers/poll_buffer.rs +4 -4
  36. package/sdk-core/core/src/replay/mod.rs +3 -3
  37. package/sdk-core/core/src/retry_logic.rs +10 -9
  38. package/sdk-core/core/src/telemetry/metrics.rs +48 -39
  39. package/sdk-core/core/src/telemetry/mod.rs +46 -12
  40. package/sdk-core/core/src/telemetry/prometheus_server.rs +17 -13
  41. package/sdk-core/core/src/test_help/mod.rs +18 -8
  42. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +10 -10
  43. package/sdk-core/core/src/worker/activities/local_activities.rs +13 -13
  44. package/sdk-core/core/src/worker/activities.rs +6 -12
  45. package/sdk-core/core/src/worker/client/mocks.rs +1 -0
  46. package/sdk-core/core/src/worker/client.rs +193 -64
  47. package/sdk-core/core/src/worker/mod.rs +14 -19
  48. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -0
  49. package/sdk-core/core/src/worker/workflow/history_update.rs +5 -5
  50. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +133 -85
  51. package/sdk-core/core/src/worker/workflow/machines/mod.rs +3 -2
  52. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +160 -105
  53. package/sdk-core/core/src/worker/workflow/managed_run.rs +2 -1
  54. package/sdk-core/core/src/worker/workflow/mod.rs +62 -58
  55. package/sdk-core/core/src/worker/workflow/run_cache.rs +5 -3
  56. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +7 -5
  57. package/sdk-core/core-api/Cargo.toml +3 -3
  58. package/sdk-core/core-api/src/errors.rs +3 -11
  59. package/sdk-core/core-api/src/worker.rs +7 -0
  60. package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +1 -1
  61. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +1 -1
  62. package/sdk-core/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +2 -6
  63. package/sdk-core/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +29 -0
  64. package/sdk-core/protos/api_upstream/Makefile +2 -2
  65. package/sdk-core/protos/api_upstream/buf.yaml +1 -0
  66. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +86 -0
  67. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
  68. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +46 -0
  69. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +7 -0
  70. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +14 -0
  71. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +51 -0
  72. package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +18 -0
  73. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +57 -1
  74. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +1 -3
  75. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -2
  76. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +11 -0
  77. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +23 -0
  78. package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +46 -0
  79. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +1 -0
  80. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +172 -0
  81. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -0
  82. package/sdk-core/protos/grpc/health/v1/health.proto +63 -0
  83. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +18 -15
  84. package/sdk-core/protos/testsrv_upstream/Makefile +80 -0
  85. package/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
  86. package/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
  87. package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
  88. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
  89. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
  90. package/sdk-core/sdk/Cargo.toml +2 -2
  91. package/sdk-core/sdk/src/lib.rs +2 -2
  92. package/sdk-core/sdk/src/workflow_context/options.rs +36 -8
  93. package/sdk-core/sdk/src/workflow_context.rs +30 -6
  94. package/sdk-core/sdk/src/workflow_future.rs +4 -4
  95. package/sdk-core/sdk-core-protos/Cargo.toml +5 -5
  96. package/sdk-core/sdk-core-protos/build.rs +9 -1
  97. package/sdk-core/sdk-core-protos/src/history_builder.rs +6 -1
  98. package/sdk-core/sdk-core-protos/src/lib.rs +93 -32
  99. package/sdk-core/test-utils/Cargo.toml +3 -3
  100. package/sdk-core/test-utils/src/canned_histories.rs +58 -0
  101. package/sdk-core/test-utils/src/lib.rs +35 -12
  102. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +128 -0
  103. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +55 -5
  104. package/sdk-core/tests/integ_tests/polling_tests.rs +2 -1
  105. package/sdk-core/tests/integ_tests/queries_tests.rs +5 -5
  106. package/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
  107. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -10
  108. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
  109. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +14 -14
  110. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +2 -6
  111. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +12 -12
  112. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +12 -1
  113. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +3 -3
  114. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +8 -2
  115. package/sdk-core/tests/integ_tests/workflow_tests.rs +19 -4
  116. package/sdk-core/tests/load_tests.rs +2 -1
  117. package/sdk-core/tests/main.rs +17 -0
  118. package/sdk-core/tests/runner.rs +93 -0
  119. package/src/conversions.rs +157 -94
  120. package/src/helpers.rs +190 -0
  121. package/src/lib.rs +10 -912
  122. package/src/runtime.rs +436 -0
  123. package/src/testing.rs +67 -0
  124. package/src/worker.rs +465 -0
@@ -189,10 +189,10 @@ async fn local_act_retry_timer_backoff() {
189
189
  activity_type: "echo".to_string(),
190
190
  input: "hi".as_json_payload().expect("serializes fine"),
191
191
  retry_policy: RetryPolicy {
192
- initial_interval: Some(Duration::from_micros(15).into()),
192
+ initial_interval: Some(prost_dur!(from_micros(15))),
193
193
  // We want two local backoffs that are short. Third backoff will use timer
194
194
  backoff_coefficient: 1_000.,
195
- maximum_interval: Some(Duration::from_millis(1500).into()),
195
+ maximum_interval: Some(prost_dur!(from_millis(1500))),
196
196
  maximum_attempts: 4,
197
197
  non_retryable_error_types: vec![],
198
198
  },
@@ -318,9 +318,9 @@ async fn cancel_after_act_starts(
318
318
  activity_type: "echo".to_string(),
319
319
  input: "hi".as_json_payload().expect("serializes fine"),
320
320
  retry_policy: RetryPolicy {
321
- initial_interval: Some(bo_dur.into()),
321
+ initial_interval: Some(bo_dur.try_into().unwrap()),
322
322
  backoff_coefficient: 1.,
323
- maximum_interval: Some(bo_dur.into()),
323
+ maximum_interval: Some(bo_dur.try_into().unwrap()),
324
324
  // Retry forever until cancelled
325
325
  ..Default::default()
326
326
  },
@@ -410,9 +410,9 @@ async fn x_to_close_timeout(#[case] is_schedule: bool) {
410
410
  activity_type: "echo".to_string(),
411
411
  input: "hi".as_json_payload().expect("serializes fine"),
412
412
  retry_policy: RetryPolicy {
413
- initial_interval: Some(Duration::from_micros(15).into()),
413
+ initial_interval: Some(prost_dur!(from_micros(15))),
414
414
  backoff_coefficient: 1_000.,
415
- maximum_interval: Some(Duration::from_millis(1500).into()),
415
+ maximum_interval: Some(prost_dur!(from_millis(1500))),
416
416
  maximum_attempts: 4,
417
417
  non_retryable_error_types: vec![],
418
418
  },
@@ -467,9 +467,9 @@ async fn schedule_to_close_timeout_across_timer_backoff(#[case] cached: bool) {
467
467
  activity_type: "echo".to_string(),
468
468
  input: "hi".as_json_payload().expect("serializes fine"),
469
469
  retry_policy: RetryPolicy {
470
- initial_interval: Some(Duration::from_micros(15).into()),
470
+ initial_interval: Some(prost_dur!(from_micros(15))),
471
471
  backoff_coefficient: 1_000.,
472
- maximum_interval: Some(Duration::from_millis(1500).into()),
472
+ maximum_interval: Some(prost_dur!(from_millis(1500))),
473
473
  maximum_attempts: 40,
474
474
  non_retryable_error_types: vec![],
475
475
  },
@@ -538,9 +538,9 @@ async fn timer_backoff_concurrent_with_non_timer_backoff() {
538
538
  activity_type: "echo".to_string(),
539
539
  input: "hi".as_json_payload().expect("serializes fine"),
540
540
  retry_policy: RetryPolicy {
541
- initial_interval: Some(Duration::from_micros(15).into()),
541
+ initial_interval: Some(prost_dur!(from_micros(15))),
542
542
  backoff_coefficient: 1_000.,
543
- maximum_interval: Some(Duration::from_millis(1500).into()),
543
+ maximum_interval: Some(prost_dur!(from_millis(1500))),
544
544
  maximum_attempts: 4,
545
545
  non_retryable_error_types: vec![],
546
546
  },
@@ -551,9 +551,9 @@ async fn timer_backoff_concurrent_with_non_timer_backoff() {
551
551
  activity_type: "echo".to_string(),
552
552
  input: "hi".as_json_payload().expect("serializes fine"),
553
553
  retry_policy: RetryPolicy {
554
- initial_interval: Some(Duration::from_millis(15).into()),
554
+ initial_interval: Some(prost_dur!(from_millis(15))),
555
555
  backoff_coefficient: 10.,
556
- maximum_interval: Some(Duration::from_millis(1500).into()),
556
+ maximum_interval: Some(prost_dur!(from_millis(1500))),
557
557
  maximum_attempts: 4,
558
558
  non_retryable_error_types: vec![],
559
559
  },
@@ -593,9 +593,9 @@ async fn repro_nondeterminism_with_timer_bug() {
593
593
  activity_type: "delay".to_string(),
594
594
  input: "hi".as_json_payload().expect("serializes fine"),
595
595
  retry_policy: RetryPolicy {
596
- initial_interval: Some(Duration::from_micros(15).into()),
596
+ initial_interval: Some(prost_dur!(from_micros(15))),
597
597
  backoff_coefficient: 1_000.,
598
- maximum_interval: Some(Duration::from_millis(1500).into()),
598
+ maximum_interval: Some(prost_dur!(from_millis(1500))),
599
599
  maximum_attempts: 4,
600
600
  non_retryable_error_types: vec![],
601
601
  },
@@ -1,7 +1,6 @@
1
1
  use assert_matches::assert_matches;
2
2
  use std::time::Duration;
3
3
  use temporal_sdk::{WfContext, Worker, WorkflowFunction};
4
- use temporal_sdk_core::telemetry_init;
5
4
  use temporal_sdk_core_api::errors::{PollActivityError, PollWfError};
6
5
  use temporal_sdk_core_protos::{
7
6
  coresdk::{
@@ -12,8 +11,7 @@ use temporal_sdk_core_protos::{
12
11
  DEFAULT_WORKFLOW_TYPE,
13
12
  };
14
13
  use temporal_sdk_core_test_utils::{
15
- canned_histories, get_integ_telem_options, history_from_proto_binary,
16
- init_core_replay_preloaded, WorkerTestHelpers,
14
+ canned_histories, history_from_proto_binary, init_core_replay_preloaded, WorkerTestHelpers,
17
15
  };
18
16
  use tokio::join;
19
17
 
@@ -30,7 +28,7 @@ async fn timer_workflow_replay() {
30
28
  task.run_id,
31
29
  vec![StartTimer {
32
30
  seq: 0,
33
- start_to_fire_timeout: Some(Duration::from_secs(1).into()),
31
+ start_to_fire_timeout: Some(prost_dur!(from_secs(1))),
34
32
  }
35
33
  .into()],
36
34
  ))
@@ -101,7 +99,6 @@ async fn workflow_nondeterministic_replay() {
101
99
 
102
100
  #[tokio::test]
103
101
  async fn replay_using_wf_function() {
104
- telemetry_init(&get_integ_telem_options()).unwrap();
105
102
  let num_timers = 10;
106
103
  let t = canned_histories::long_sequential_timers(num_timers as usize);
107
104
  let func = timers_wf(num_timers);
@@ -118,7 +115,6 @@ async fn replay_ok_ending_with_terminated_or_timed_out() {
118
115
  t1.add_workflow_execution_terminated();
119
116
  let mut t2 = canned_histories::single_timer("1");
120
117
  t2.add_workflow_execution_timed_out();
121
- telemetry_init(&get_integ_telem_options()).unwrap();
122
118
  for t in [t1, t2] {
123
119
  let func = timers_wf(1);
124
120
  let (worker, _) = init_core_replay_preloaded(
@@ -46,13 +46,12 @@ async fn reset_workflow() {
46
46
  .await
47
47
  .unwrap();
48
48
 
49
- let client = starter.get_client().await;
49
+ let mut client = starter.get_client().await;
50
+ let client = Arc::make_mut(&mut client);
50
51
  let resetter_fut = async {
51
52
  notify.notified().await;
52
53
  // Do the reset
53
54
  client
54
- .get_client()
55
- .raw_retry_client()
56
55
  .reset_workflow_execution(ResetWorkflowExecutionRequest {
57
56
  namespace: NAMESPACE.to_owned(),
58
57
  workflow_execution: Some(WorkflowExecution {
@@ -69,15 +68,16 @@ async fn reset_workflow() {
69
68
 
70
69
  // Unblock the workflow by sending the signal. Run ID will have changed after reset so
71
70
  // we use empty run id
72
- client
73
- .signal_workflow_execution(
74
- wf_name.to_owned(),
75
- "".to_owned(),
76
- POST_RESET_SIG.to_owned(),
77
- None,
78
- )
79
- .await
80
- .unwrap();
71
+ WorkflowClientTrait::signal_workflow_execution(
72
+ client,
73
+ wf_name.to_owned(),
74
+ "".to_owned(),
75
+ POST_RESET_SIG.to_owned(),
76
+ None,
77
+ None,
78
+ )
79
+ .await
80
+ .unwrap();
81
81
 
82
82
  // Wait for the now-reset workflow to finish
83
83
  client
@@ -1,9 +1,11 @@
1
+ use std::collections::HashMap;
2
+
1
3
  use futures::StreamExt;
2
4
  use temporal_client::{WorkflowClientTrait, WorkflowExecutionInfo, WorkflowOptions};
3
5
  use temporal_sdk::{
4
6
  ChildWorkflowOptions, Signal, SignalWorkflowOptions, WfContext, WorkflowResult,
5
7
  };
6
- use temporal_sdk_core_protos::coresdk::IntoPayloadsExt;
8
+ use temporal_sdk_core_protos::{coresdk::IntoPayloadsExt, temporal::api::common::v1::Payload};
7
9
  use temporal_sdk_core_test_utils::CoreWfStarter;
8
10
  use uuid::Uuid;
9
11
 
@@ -57,7 +59,12 @@ async fn signal_receiver(ctx: WfContext) -> WorkflowResult<()> {
57
59
 
58
60
  async fn signal_with_create_wf_receiver(ctx: WfContext) -> WorkflowResult<()> {
59
61
  let res = ctx.make_signal_channel(SIGNAME).next().await.unwrap();
62
+ println!("HEADER: {:?}", res.headers);
60
63
  assert_eq!(&res.input, &[b"tada".into()]);
64
+ assert_eq!(
65
+ *res.headers.get("tupac").expect("tupac header exists"),
66
+ b"shakur".into()
67
+ );
61
68
  Ok(().into())
62
69
  }
63
70
 
@@ -96,15 +103,19 @@ async fn sends_signal_with_create_wf() {
96
103
  worker.register_wf("receiversignal", signal_with_create_wf_receiver);
97
104
 
98
105
  let client = starter.get_client().await;
106
+ let mut header: HashMap<String, Payload> = HashMap::new();
107
+ header.insert("tupac".into(), "shakur".into());
99
108
  let res = client
100
109
  .signal_with_start_workflow_execution(
101
110
  None,
102
111
  worker.inner_mut().task_queue().to_owned(),
103
112
  "sends_signal_with_create_wf".to_owned(),
104
113
  "receiversignal".to_owned(),
114
+ None,
105
115
  WorkflowOptions::default(),
106
116
  SIGNAME.to_owned(),
107
117
  vec![b"tada".into()].into_payloads(),
118
+ Some(header.into()),
108
119
  )
109
120
  .await
110
121
  .expect("request succeeds.qed");
@@ -42,7 +42,7 @@ async fn timer_workflow_manual() {
42
42
  task.run_id,
43
43
  vec![StartTimer {
44
44
  seq: 0,
45
- start_to_fire_timeout: Some(Duration::from_secs(1).into()),
45
+ start_to_fire_timeout: Some(prost_dur!(from_secs(1))),
46
46
  }
47
47
  .into()],
48
48
  ))
@@ -63,12 +63,12 @@ async fn timer_cancel_workflow() {
63
63
  vec![
64
64
  StartTimer {
65
65
  seq: 0,
66
- start_to_fire_timeout: Some(Duration::from_millis(50).into()),
66
+ start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
67
67
  }
68
68
  .into(),
69
69
  StartTimer {
70
70
  seq: 1,
71
- start_to_fire_timeout: Some(Duration::from_secs(10).into()),
71
+ start_to_fire_timeout: Some(prost_dur!(from_secs(10))),
72
72
  }
73
73
  .into(),
74
74
  ],
@@ -1,8 +1,9 @@
1
- use std::collections::HashMap;
1
+ use log::warn;
2
+ use std::{collections::HashMap, env};
2
3
  use temporal_client::{WorkflowClientTrait, WorkflowOptions};
3
4
  use temporal_sdk::{WfContext, WorkflowResult};
4
5
  use temporal_sdk_core_protos::coresdk::{AsJsonPayloadExt, FromJsonPayloadExt};
5
- use temporal_sdk_core_test_utils::CoreWfStarter;
6
+ use temporal_sdk_core_test_utils::{CoreWfStarter, INTEG_TEMPORALITE_USED_ENV_VAR};
6
7
  use uuid::Uuid;
7
8
 
8
9
  // These are initialized on the server as part of the autosetup container which we
@@ -24,6 +25,11 @@ async fn sends_upsert() {
24
25
  let wf_id = Uuid::new_v4();
25
26
  let mut starter = CoreWfStarter::new(wf_name);
26
27
  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");
30
+ return;
31
+ }
32
+
27
33
  worker.register_wf(wf_name, search_attr_updater);
28
34
  let run_id = worker
29
35
  .submit_wf(
@@ -223,7 +223,7 @@ async fn fail_wf_task(#[values(true, false)] replay: bool) {
223
223
  task.run_id,
224
224
  vec![StartTimer {
225
225
  seq: 0,
226
- start_to_fire_timeout: Some(Duration::from_millis(200).into()),
226
+ start_to_fire_timeout: Some(prost_dur!(from_millis(200))),
227
227
  }
228
228
  .into()],
229
229
  ))
@@ -279,6 +279,7 @@ async fn signal_workflow() {
279
279
  res.run_id.to_string(),
280
280
  signal_id_1.to_string(),
281
281
  None,
282
+ None,
282
283
  )
283
284
  .await
284
285
  .unwrap();
@@ -288,6 +289,7 @@ async fn signal_workflow() {
288
289
  res.run_id.to_string(),
289
290
  signal_id_2.to_string(),
290
291
  None,
292
+ None,
291
293
  )
292
294
  .await
293
295
  .unwrap();
@@ -345,7 +347,7 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
345
347
  res.run_id,
346
348
  vec![StartTimer {
347
349
  seq: 0,
348
- start_to_fire_timeout: Some(Duration::from_millis(10).into()),
350
+ start_to_fire_timeout: Some(prost_dur!(from_millis(10))),
349
351
  }
350
352
  .into()],
351
353
  ))
@@ -374,6 +376,7 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
374
376
  res.run_id.to_string(),
375
377
  signal_id_1.to_string(),
376
378
  None,
379
+ None,
377
380
  )
378
381
  .await
379
382
  .unwrap();
@@ -458,7 +461,13 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
458
461
  // Send the signals to the server & resolve activity -- sometimes this happens too fast
459
462
  sleep(Duration::from_millis(200)).await;
460
463
  client
461
- .signal_workflow_execution(wf_id.to_string(), rid, signal_at_start.to_string(), None)
464
+ .signal_workflow_execution(
465
+ wf_id.to_string(),
466
+ rid,
467
+ signal_at_start.to_string(),
468
+ None,
469
+ None,
470
+ )
462
471
  .await
463
472
  .unwrap();
464
473
  // Complete activity successfully.
@@ -470,7 +479,13 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
470
479
  .unwrap();
471
480
  let rid = wf_task.run_id.clone();
472
481
  client
473
- .signal_workflow_execution(wf_id.to_string(), rid, signal_at_complete.to_string(), None)
482
+ .signal_workflow_execution(
483
+ wf_id.to_string(),
484
+ rid,
485
+ signal_at_complete.to_string(),
486
+ None,
487
+ None,
488
+ )
474
489
  .await
475
490
  .unwrap();
476
491
  // Now poll again, it will be an eviction b/c non-sticky mode.
@@ -35,13 +35,13 @@ async fn activity_load() {
35
35
  let activity = ActivityOptions {
36
36
  activity_id: Some(activity_id.to_string()),
37
37
  activity_type: "test_activity".to_string(),
38
- input: Default::default(),
39
38
  task_queue,
40
39
  schedule_to_start_timeout: Some(activity_timeout),
41
40
  start_to_close_timeout: Some(activity_timeout),
42
41
  schedule_to_close_timeout: Some(activity_timeout),
43
42
  heartbeat_timeout: Some(activity_timeout),
44
43
  cancellation_type: ActivityCancellationType::TryCancel,
44
+ ..Default::default()
45
45
  };
46
46
  let res = ctx.activity(activity).await.unwrap_ok_payload();
47
47
  assert_eq!(res.data, payload_dat);
@@ -175,6 +175,7 @@ async fn workflow_load() {
175
175
  "".to_string(),
176
176
  SIGNAME.to_string(),
177
177
  None,
178
+ None,
178
179
  )
179
180
  })
180
181
  .collect();
@@ -1,11 +1,28 @@
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
+
7
+ #[macro_use]
8
+ extern crate rstest;
2
9
 
3
10
  #[cfg(test)]
4
11
  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
+ }
5
20
  mod client_tests;
21
+ mod ephemeral_server_tests;
6
22
  mod heartbeat_tests;
7
23
  mod polling_tests;
8
24
  mod queries_tests;
25
+ mod visibility_tests;
9
26
  mod workflow_tests;
10
27
 
11
28
  use std::str::FromStr;
@@ -0,0 +1,93 @@
1
+ use anyhow::{anyhow, bail};
2
+ use std::{
3
+ env,
4
+ env::args,
5
+ path::{Path, PathBuf},
6
+ process::Stdio,
7
+ };
8
+ use temporal_sdk_core::ephemeral_server::{TemporaliteConfigBuilder, TestServerConfigBuilder};
9
+ use temporal_sdk_core_test_utils::{
10
+ default_cached_download, INTEG_SERVER_TARGET_ENV_VAR, INTEG_TEMPORALITE_USED_ENV_VAR,
11
+ INTEG_TEST_SERVER_USED_ENV_VAR,
12
+ };
13
+ use tokio::{self, process::Command};
14
+
15
+ #[tokio::main]
16
+ async fn main() -> Result<(), anyhow::Error> {
17
+ 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
+ // Try building first, so that we error early on build failures & don't start server
22
+ let status = Command::new(&cargo)
23
+ .args(["test", "--test", "integ_tests", "--no-run"])
24
+ .status()
25
+ .await?;
26
+ if !status.success() {
27
+ bail!("Building integration tests failed!");
28
+ }
29
+
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![])
52
+ };
53
+
54
+ // Run the integ tests, passing through arguments
55
+ let mut args = args();
56
+ // Shift off binary name
57
+ args.next();
58
+ let mut cmd = Command::new(&cargo);
59
+ if let Some(srv) = server.as_ref() {
60
+ cmd.env(
61
+ INTEG_SERVER_TARGET_ENV_VAR,
62
+ format!("http://{}", &srv.target),
63
+ );
64
+ }
65
+ let status = cmd
66
+ .envs(envs)
67
+ .current_dir(project_root())
68
+ .args(
69
+ ["test", "--test", "integ_tests"]
70
+ .into_iter()
71
+ .map(ToString::to_string)
72
+ .chain(args),
73
+ )
74
+ .status()
75
+ .await?;
76
+
77
+ if let Some(mut srv) = server {
78
+ srv.shutdown().await?;
79
+ }
80
+ if status.success() {
81
+ Ok(())
82
+ } else {
83
+ Err(anyhow!("Integ tests failed!"))
84
+ }
85
+ }
86
+
87
+ fn project_root() -> PathBuf {
88
+ Path::new(&env!("CARGO_MANIFEST_DIR"))
89
+ .ancestors()
90
+ .nth(1)
91
+ .unwrap()
92
+ .to_path_buf()
93
+ }