@temporalio/core-bridge 1.5.2 → 1.6.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 (153) hide show
  1. package/Cargo.lock +255 -48
  2. package/package.json +4 -4
  3. package/releases/aarch64-apple-darwin/index.node +0 -0
  4. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  5. package/releases/x86_64-apple-darwin/index.node +0 -0
  6. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  7. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  8. package/sdk-core/.buildkite/pipeline.yml +1 -3
  9. package/sdk-core/.cargo/config.toml +5 -2
  10. package/sdk-core/.github/workflows/heavy.yml +28 -0
  11. package/sdk-core/Cargo.toml +1 -1
  12. package/sdk-core/README.md +9 -5
  13. package/sdk-core/client/src/lib.rs +211 -36
  14. package/sdk-core/client/src/raw.rs +1 -1
  15. package/sdk-core/client/src/retry.rs +32 -20
  16. package/sdk-core/core/Cargo.toml +23 -9
  17. package/sdk-core/core/src/abstractions.rs +11 -0
  18. package/sdk-core/core/src/core_tests/activity_tasks.rs +6 -5
  19. package/sdk-core/core/src/core_tests/local_activities.rs +263 -22
  20. package/sdk-core/core/src/core_tests/queries.rs +2 -2
  21. package/sdk-core/core/src/core_tests/workflow_tasks.rs +249 -5
  22. package/sdk-core/core/src/ephemeral_server/mod.rs +5 -6
  23. package/sdk-core/core/src/lib.rs +2 -0
  24. package/sdk-core/core/src/protosext/mod.rs +1 -1
  25. package/sdk-core/core/src/telemetry/log_export.rs +1 -1
  26. package/sdk-core/core/src/telemetry/mod.rs +23 -8
  27. package/sdk-core/core/src/test_help/mod.rs +8 -1
  28. package/sdk-core/core/src/worker/activities/local_activities.rs +259 -125
  29. package/sdk-core/core/src/worker/activities.rs +3 -2
  30. package/sdk-core/core/src/worker/mod.rs +53 -26
  31. package/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
  32. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
  33. package/sdk-core/core/src/worker/workflow/history_update.rs +835 -277
  34. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +9 -17
  35. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +3 -5
  36. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -2
  37. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +3 -5
  38. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -2
  39. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +1 -2
  40. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -2
  41. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +73 -51
  42. package/sdk-core/core/src/worker/workflow/machines/mod.rs +3 -3
  43. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +4 -4
  44. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -2
  45. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +3 -5
  46. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +6 -7
  47. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  48. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +4 -4
  49. package/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
  50. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +89 -58
  51. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +4 -7
  52. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +21 -9
  53. package/sdk-core/core/src/worker/workflow/managed_run.rs +1021 -360
  54. package/sdk-core/core/src/worker/workflow/mod.rs +306 -346
  55. package/sdk-core/core/src/worker/workflow/run_cache.rs +29 -53
  56. package/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
  57. package/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
  58. package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +115 -0
  59. package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
  60. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +444 -714
  61. package/sdk-core/core-api/Cargo.toml +2 -0
  62. package/sdk-core/core-api/src/errors.rs +1 -34
  63. package/sdk-core/core-api/src/lib.rs +6 -2
  64. package/sdk-core/core-api/src/worker.rs +14 -1
  65. package/sdk-core/etc/deps.svg +115 -140
  66. package/sdk-core/etc/regen-depgraph.sh +5 -0
  67. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -6
  68. package/sdk-core/fsm/rustfsm_trait/src/lib.rs +7 -3
  69. package/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  70. package/sdk-core/protos/api_upstream/Makefile +5 -5
  71. package/sdk-core/protos/api_upstream/build/go.mod +7 -0
  72. package/sdk-core/protos/api_upstream/build/go.sum +5 -0
  73. package/sdk-core/protos/api_upstream/build/tools.go +29 -0
  74. package/sdk-core/protos/api_upstream/go.mod +6 -0
  75. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +9 -2
  76. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +12 -19
  77. package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +2 -2
  78. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
  79. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +3 -2
  80. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
  81. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +3 -3
  82. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +20 -2
  83. package/sdk-core/protos/api_upstream/temporal/api/{update/v1/message.proto → enums/v1/interaction_type.proto} +11 -18
  84. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
  85. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
  86. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
  87. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
  88. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
  89. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +2 -13
  90. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
  91. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
  92. package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
  93. package/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
  94. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +13 -19
  95. package/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +87 -0
  96. package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -2
  97. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +2 -2
  98. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -2
  99. package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
  100. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
  101. package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
  102. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
  103. package/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
  104. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -2
  105. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +13 -8
  106. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
  107. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  108. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
  109. package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
  110. package/sdk-core/sdk/Cargo.toml +4 -3
  111. package/sdk-core/sdk/src/lib.rs +87 -21
  112. package/sdk-core/sdk/src/workflow_future.rs +7 -12
  113. package/sdk-core/sdk-core-protos/Cargo.toml +5 -2
  114. package/sdk-core/sdk-core-protos/build.rs +36 -2
  115. package/sdk-core/sdk-core-protos/src/history_builder.rs +26 -19
  116. package/sdk-core/sdk-core-protos/src/history_info.rs +4 -0
  117. package/sdk-core/sdk-core-protos/src/lib.rs +78 -34
  118. package/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
  119. package/sdk-core/test-utils/Cargo.toml +3 -1
  120. package/sdk-core/test-utils/src/histfetch.rs +1 -1
  121. package/sdk-core/test-utils/src/lib.rs +50 -18
  122. package/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
  123. package/sdk-core/test-utils/src/workflows.rs +29 -0
  124. package/sdk-core/tests/fuzzy_workflow.rs +130 -0
  125. package/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +114 -7
  126. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -2
  127. package/sdk-core/tests/integ_tests/metrics_tests.rs +1 -1
  128. package/sdk-core/tests/integ_tests/polling_tests.rs +1 -39
  129. package/sdk-core/tests/integ_tests/queries_tests.rs +2 -127
  130. package/sdk-core/tests/integ_tests/visibility_tests.rs +52 -5
  131. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +74 -1
  132. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +5 -13
  133. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +1 -1
  134. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +2 -10
  135. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +69 -197
  136. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +4 -28
  137. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +12 -7
  138. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +14 -14
  139. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +3 -19
  140. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +3 -19
  141. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +1 -1
  142. package/sdk-core/tests/integ_tests/workflow_tests.rs +5 -6
  143. package/sdk-core/tests/main.rs +2 -12
  144. package/sdk-core/tests/runner.rs +71 -34
  145. package/sdk-core/tests/wf_input_replay.rs +32 -0
  146. package/sdk-core/bridge-ffi/Cargo.toml +0 -24
  147. package/sdk-core/bridge-ffi/LICENSE.txt +0 -23
  148. package/sdk-core/bridge-ffi/build.rs +0 -25
  149. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -224
  150. package/sdk-core/bridge-ffi/src/lib.rs +0 -746
  151. package/sdk-core/bridge-ffi/src/wrappers.rs +0 -221
  152. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
  153. package/sdk-core/sdk/src/conversions.rs +0 -8
@@ -1,11 +1,13 @@
1
1
  use anyhow::anyhow;
2
2
  use futures::future::join_all;
3
- use futures_util::stream::{FuturesUnordered, StreamExt};
4
- use std::time::Duration;
5
- use temporal_client::{WorkflowClientTrait, WorkflowOptions};
3
+ use std::{
4
+ sync::atomic::{AtomicU8, Ordering},
5
+ time::Duration,
6
+ };
7
+ use temporal_client::WorkflowOptions;
6
8
  use temporal_sdk::{
7
- interceptors::WorkerInterceptor, ActContext, ActivityCancelledError, ActivityOptions,
8
- CancellableFuture, LocalActivityOptions, WfContext, WorkflowResult,
9
+ interceptors::WorkerInterceptor, ActContext, ActivityCancelledError, CancellableFuture,
10
+ LocalActivityOptions, WfContext, WorkflowResult,
9
11
  };
10
12
  use temporal_sdk_core::replay::HistoryForReplay;
11
13
  use temporal_sdk_core_protos::{
@@ -13,11 +15,12 @@ use temporal_sdk_core_protos::{
13
15
  workflow_commands::ActivityCancellationType,
14
16
  workflow_completion::WorkflowActivationCompletion, AsJsonPayloadExt,
15
17
  },
16
- temporal::api::common::v1::RetryPolicy,
18
+ temporal::api::{common::v1::RetryPolicy, enums::v1::TimeoutType},
17
19
  TestHistoryBuilder,
18
20
  };
19
21
  use temporal_sdk_core_test_utils::{
20
- history_from_proto_binary, init_integ_telem, replay_sdk_worker, CoreWfStarter,
22
+ history_from_proto_binary, init_integ_telem, replay_sdk_worker, workflows::la_problem_workflow,
23
+ CoreWfStarter,
21
24
  };
22
25
  use tokio_util::sync::CancellationToken;
23
26
 
@@ -46,15 +49,7 @@ async fn one_local_activity() {
46
49
  worker.register_wf(wf_name.to_owned(), one_local_activity_wf);
47
50
  worker.register_activity("echo_activity", echo);
48
51
 
49
- worker
50
- .submit_wf(
51
- wf_name.to_owned(),
52
- wf_name.to_owned(),
53
- vec![],
54
- WorkflowOptions::default(),
55
- )
56
- .await
57
- .unwrap();
52
+ starter.start_with_worker(wf_name, &mut worker).await;
58
53
  worker.run_until_done().await.unwrap();
59
54
  }
60
55
 
@@ -77,15 +72,7 @@ async fn local_act_concurrent_with_timer() {
77
72
  worker.register_wf(wf_name.to_owned(), local_act_concurrent_with_timer_wf);
78
73
  worker.register_activity("echo_activity", echo);
79
74
 
80
- worker
81
- .submit_wf(
82
- wf_name.to_owned(),
83
- wf_name.to_owned(),
84
- vec![],
85
- WorkflowOptions::default(),
86
- )
87
- .await
88
- .unwrap();
75
+ starter.start_with_worker(wf_name, &mut worker).await;
89
76
  worker.run_until_done().await.unwrap();
90
77
  }
91
78
 
@@ -109,15 +96,7 @@ async fn local_act_then_timer_then_wait_result() {
109
96
  worker.register_wf(wf_name.to_owned(), local_act_then_timer_then_wait);
110
97
  worker.register_activity("echo_activity", echo);
111
98
 
112
- worker
113
- .submit_wf(
114
- wf_name.to_owned(),
115
- wf_name.to_owned(),
116
- vec![],
117
- WorkflowOptions::default(),
118
- )
119
- .await
120
- .unwrap();
99
+ starter.start_with_worker(wf_name, &mut worker).await;
121
100
  worker.run_until_done().await.unwrap();
122
101
  }
123
102
 
@@ -125,7 +104,7 @@ async fn local_act_then_timer_then_wait_result() {
125
104
  async fn long_running_local_act_with_timer() {
126
105
  let wf_name = "long_running_local_act_with_timer";
127
106
  let mut starter = CoreWfStarter::new(wf_name);
128
- starter.wft_timeout(Duration::from_secs(1));
107
+ starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
129
108
  let mut worker = starter.worker().await;
130
109
  worker.register_wf(wf_name.to_owned(), local_act_then_timer_then_wait);
131
110
  worker.register_activity("echo_activity", |_ctx: ActContext, str: String| async {
@@ -133,15 +112,7 @@ async fn long_running_local_act_with_timer() {
133
112
  Ok(str)
134
113
  });
135
114
 
136
- worker
137
- .submit_wf(
138
- wf_name.to_owned(),
139
- wf_name.to_owned(),
140
- vec![],
141
- WorkflowOptions::default(),
142
- )
143
- .await
144
- .unwrap();
115
+ starter.start_with_worker(wf_name, &mut worker).await;
145
116
  worker.run_until_done().await.unwrap();
146
117
  }
147
118
 
@@ -150,7 +121,7 @@ pub async fn local_act_fanout_wf(ctx: WfContext) -> WorkflowResult<()> {
150
121
  .map(|i| {
151
122
  ctx.local_activity(LocalActivityOptions {
152
123
  activity_type: "echo_activity".to_string(),
153
- input: format!("Hi {}", i)
124
+ input: format!("Hi {i}")
154
125
  .as_json_payload()
155
126
  .expect("serializes fine"),
156
127
  ..Default::default()
@@ -171,15 +142,7 @@ async fn local_act_fanout() {
171
142
  worker.register_wf(wf_name.to_owned(), local_act_fanout_wf);
172
143
  worker.register_activity("echo_activity", echo);
173
144
 
174
- worker
175
- .submit_wf(
176
- wf_name.to_owned(),
177
- wf_name.to_owned(),
178
- vec![],
179
- WorkflowOptions::default(),
180
- )
181
- .await
182
- .unwrap();
145
+ starter.start_with_worker(wf_name, &mut worker).await;
183
146
  worker.run_until_done().await.unwrap();
184
147
  }
185
148
 
@@ -234,7 +197,7 @@ async fn local_act_retry_timer_backoff() {
234
197
  #[case::abandon(ActivityCancellationType::Abandon)]
235
198
  #[tokio::test]
236
199
  async fn cancel_immediate(#[case] cancel_type: ActivityCancellationType) {
237
- let wf_name = format!("cancel_immediate_{:?}", cancel_type);
200
+ let wf_name = format!("cancel_immediate_{cancel_type:?}");
238
201
  let mut starter = CoreWfStarter::new(&wf_name);
239
202
  let mut worker = starter.worker().await;
240
203
  worker.register_wf(&wf_name, move |ctx: WfContext| async move {
@@ -268,15 +231,7 @@ async fn cancel_immediate(#[case] cancel_type: ActivityCancellationType) {
268
231
  }
269
232
  });
270
233
 
271
- worker
272
- .submit_wf(
273
- wf_name.to_owned(),
274
- wf_name.to_owned(),
275
- vec![],
276
- WorkflowOptions::default(),
277
- )
278
- .await
279
- .unwrap();
234
+ starter.start_with_worker(wf_name, &mut worker).await;
280
235
  worker
281
236
  .run_until_done_intercepted(Some(LACancellerInterceptor {
282
237
  token: manual_cancel,
@@ -310,12 +265,9 @@ async fn cancel_after_act_starts(
310
265
  )]
311
266
  cancel_type: ActivityCancellationType,
312
267
  ) {
313
- let wf_name = format!(
314
- "cancel_after_act_starts_timer_{:?}_{:?}",
315
- cancel_on_backoff, cancel_type
316
- );
268
+ let wf_name = format!("cancel_after_act_starts_{cancel_on_backoff:?}_{cancel_type:?}");
317
269
  let mut starter = CoreWfStarter::new(&wf_name);
318
- starter.wft_timeout(Duration::from_secs(1));
270
+ starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
319
271
  let mut worker = starter.worker().await;
320
272
  let bo_dur = cancel_on_backoff.unwrap_or_else(|| Duration::from_secs(1));
321
273
  worker.register_wf(&wf_name, move |ctx: WfContext| async move {
@@ -375,21 +327,14 @@ async fn cancel_after_act_starts(
375
327
  }
376
328
  });
377
329
 
378
- worker
379
- .submit_wf(
380
- wf_name.to_owned(),
381
- wf_name.to_owned(),
382
- vec![],
383
- WorkflowOptions::default(),
384
- )
385
- .await
386
- .unwrap();
330
+ starter.start_with_worker(&wf_name, &mut worker).await;
387
331
  worker
388
332
  .run_until_done_intercepted(Some(LACancellerInterceptor {
389
333
  token: manual_cancel,
390
334
  }))
391
335
  .await
392
336
  .unwrap();
337
+ starter.shutdown().await;
393
338
  }
394
339
 
395
340
  #[rstest::rstest]
@@ -408,6 +353,11 @@ async fn x_to_close_timeout(#[case] is_schedule: bool) {
408
353
  } else {
409
354
  (None, Some(Duration::from_secs(2)))
410
355
  };
356
+ let timeout_type = if is_schedule {
357
+ TimeoutType::ScheduleToClose
358
+ } else {
359
+ TimeoutType::StartToClose
360
+ };
411
361
 
412
362
  worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| async move {
413
363
  let res = ctx
@@ -427,7 +377,7 @@ async fn x_to_close_timeout(#[case] is_schedule: bool) {
427
377
  ..Default::default()
428
378
  })
429
379
  .await;
430
- assert!(res.timed_out());
380
+ assert_eq!(res.timed_out(), Some(timeout_type));
431
381
  Ok(().into())
432
382
  });
433
383
  worker.register_activity("echo", |ctx: ActContext, _: String| async move {
@@ -440,15 +390,7 @@ async fn x_to_close_timeout(#[case] is_schedule: bool) {
440
390
  Ok(())
441
391
  });
442
392
 
443
- worker
444
- .submit_wf(
445
- wf_name.to_owned(),
446
- wf_name.to_owned(),
447
- vec![],
448
- WorkflowOptions::default(),
449
- )
450
- .await
451
- .unwrap();
393
+ starter.start_with_worker(wf_name, &mut worker).await;
452
394
  worker.run_until_done().await.unwrap();
453
395
  }
454
396
 
@@ -472,43 +414,37 @@ async fn schedule_to_close_timeout_across_timer_backoff(#[case] cached: bool) {
472
414
  activity_type: "echo".to_string(),
473
415
  input: "hi".as_json_payload().expect("serializes fine"),
474
416
  retry_policy: RetryPolicy {
475
- initial_interval: Some(prost_dur!(from_micros(15))),
417
+ initial_interval: Some(prost_dur!(from_millis(15))),
476
418
  backoff_coefficient: 1_000.,
477
- maximum_interval: Some(prost_dur!(from_millis(1500))),
419
+ maximum_interval: Some(prost_dur!(from_millis(1000))),
478
420
  maximum_attempts: 40,
479
421
  non_retryable_error_types: vec![],
480
422
  },
481
- timer_backoff_threshold: Some(Duration::from_secs(1)),
482
- schedule_to_close_timeout: Some(Duration::from_secs(3)),
423
+ timer_backoff_threshold: Some(Duration::from_millis(500)),
424
+ schedule_to_close_timeout: Some(Duration::from_secs(2)),
483
425
  ..Default::default()
484
426
  })
485
427
  .await;
486
- assert!(res.timed_out());
428
+ assert_eq!(res.timed_out(), Some(TimeoutType::ScheduleToClose));
487
429
  Ok(().into())
488
430
  });
489
- worker.register_activity("echo", |_: ActContext, _: String| async {
431
+ let num_attempts: &'static _ = Box::leak(Box::new(AtomicU8::new(0)));
432
+ worker.register_activity("echo", move |_: ActContext, _: String| async {
433
+ num_attempts.fetch_add(1, Ordering::Relaxed);
490
434
  Result::<(), _>::Err(anyhow!("Oh no I failed!"))
491
435
  });
492
436
 
493
- worker
494
- .submit_wf(
495
- wf_name.to_owned(),
496
- wf_name.to_owned(),
497
- vec![],
498
- WorkflowOptions::default(),
499
- )
500
- .await
501
- .unwrap();
437
+ starter.start_with_worker(wf_name, &mut worker).await;
502
438
  worker.run_until_done().await.unwrap();
439
+ // 3 attempts b/c first backoff is very small, then the next 2 attempts take at least 2 seconds
440
+ // b/c of timer backoff.
441
+ assert_eq!(3, num_attempts.load(Ordering::Relaxed));
503
442
  }
504
443
 
505
444
  #[rstest::rstest]
506
445
  #[tokio::test]
507
446
  async fn eviction_wont_make_local_act_get_dropped(#[values(true, false)] short_wft_timeout: bool) {
508
- let wf_name = format!(
509
- "eviction_wont_make_local_act_get_dropped_{}",
510
- short_wft_timeout
511
- );
447
+ let wf_name = format!("eviction_wont_make_local_act_get_dropped_{short_wft_timeout}");
512
448
  let mut starter = CoreWfStarter::new(&wf_name);
513
449
  starter.max_cached_workflows(0);
514
450
  let mut worker = starter.worker().await;
@@ -574,15 +510,7 @@ async fn timer_backoff_concurrent_with_non_timer_backoff() {
574
510
  Result::<(), _>::Err(anyhow!("Oh no I failed!"))
575
511
  });
576
512
 
577
- worker
578
- .submit_wf(
579
- wf_name.to_owned(),
580
- wf_name.to_owned(),
581
- vec![],
582
- WorkflowOptions::default(),
583
- )
584
- .await
585
- .unwrap();
513
+ starter.start_with_worker(wf_name, &mut worker).await;
586
514
  worker.run_until_done().await.unwrap();
587
515
  }
588
516
 
@@ -613,7 +541,7 @@ async fn repro_nondeterminism_with_timer_bug() {
613
541
  _ = r1 => {
614
542
  t1.cancel(&ctx);
615
543
  },
616
- };
544
+ }
617
545
  ctx.timer(Duration::from_secs(1)).await;
618
546
  Ok(().into())
619
547
  });
@@ -638,85 +566,6 @@ async fn repro_nondeterminism_with_timer_bug() {
638
566
  .unwrap();
639
567
  }
640
568
 
641
- async fn la_problem_workflow(ctx: WfContext) -> WorkflowResult<()> {
642
- ctx.local_activity(LocalActivityOptions {
643
- activity_type: "delay".to_string(),
644
- input: "hi".as_json_payload().expect("serializes fine"),
645
- retry_policy: RetryPolicy {
646
- initial_interval: Some(prost_dur!(from_micros(15))),
647
- backoff_coefficient: 1_000.,
648
- maximum_interval: Some(prost_dur!(from_millis(1500))),
649
- maximum_attempts: 4,
650
- non_retryable_error_types: vec![],
651
- },
652
- timer_backoff_threshold: Some(Duration::from_secs(1)),
653
- ..Default::default()
654
- })
655
- .await;
656
- ctx.activity(ActivityOptions {
657
- activity_type: "delay".to_string(),
658
- start_to_close_timeout: Some(Duration::from_secs(20)),
659
- input: "hi!".as_json_payload().expect("serializes fine"),
660
- ..Default::default()
661
- })
662
- .await;
663
- Ok(().into())
664
- }
665
-
666
- // Expensive to run - worth enabling on a stress/regression pipeline.
667
- #[ignore]
668
- #[tokio::test(flavor = "multi_thread", worker_threads = 4)]
669
- async fn evict_while_la_running_no_interference() {
670
- let wf_name = "evict_while_la_running_no_interference";
671
- let mut starter = CoreWfStarter::new(wf_name);
672
- starter.max_local_at(20);
673
- starter.max_cached_workflows(20);
674
- let mut worker = starter.worker().await;
675
-
676
- worker.register_wf(wf_name.to_owned(), la_problem_workflow);
677
- worker.register_activity("delay", |_: ActContext, _: String| async {
678
- tokio::time::sleep(Duration::from_secs(15)).await;
679
- Ok(())
680
- });
681
-
682
- let client = starter.get_client().await;
683
- let subfs = FuturesUnordered::new();
684
- for i in 1..100 {
685
- let wf_id = format!("{}-{}", wf_name, i);
686
- let run_id = worker
687
- .submit_wf(
688
- &wf_id,
689
- wf_name.to_owned(),
690
- vec![],
691
- WorkflowOptions::default(),
692
- )
693
- .await
694
- .unwrap();
695
- let cw = worker.core_worker.clone();
696
- let client = client.clone();
697
- subfs.push(async move {
698
- // Evict the workflow
699
- tokio::time::sleep(Duration::from_secs(1)).await;
700
- cw.request_workflow_eviction(&run_id);
701
- // Wake up workflow by sending signal
702
- client
703
- .signal_workflow_execution(
704
- wf_id,
705
- run_id.clone(),
706
- "whaatever".to_string(),
707
- None,
708
- None,
709
- )
710
- .await
711
- .unwrap();
712
- });
713
- }
714
- let runf = async {
715
- worker.run_until_done().await.unwrap();
716
- };
717
- tokio::join!(subfs.collect::<Vec<_>>(), runf);
718
- }
719
-
720
569
  #[rstest::rstest]
721
570
  #[tokio::test]
722
571
  async fn weird_la_nondeterminism_repro(#[values(true, false)] fix_hist: bool) {
@@ -758,7 +607,6 @@ async fn second_weird_la_nondeterminism_repro() {
758
607
  // Chop off uninteresting ending
759
608
  hist.events.truncate(24);
760
609
  let mut thb = TestHistoryBuilder::from_history(hist.events);
761
- // thb.add_workflow_task_completed();
762
610
  thb.add_workflow_execution_completed();
763
611
  hist = thb.get_full_history_info().unwrap().into();
764
612
 
@@ -773,3 +621,27 @@ async fn second_weird_la_nondeterminism_repro() {
773
621
  });
774
622
  worker.run().await.unwrap();
775
623
  }
624
+
625
+ #[tokio::test]
626
+ async fn third_weird_la_nondeterminism_repro() {
627
+ init_integ_telem();
628
+ let mut hist = history_from_proto_binary(
629
+ "histories/evict_while_la_running_no_interference-16_history.bin",
630
+ )
631
+ .await
632
+ .unwrap();
633
+ let mut thb = TestHistoryBuilder::from_history(hist.events);
634
+ thb.add_workflow_task_scheduled_and_started();
635
+ hist = thb.get_full_history_info().unwrap().into();
636
+
637
+ let mut worker = replay_sdk_worker([HistoryForReplay::new(hist, "fake".to_owned())]);
638
+ worker.register_wf(
639
+ "evict_while_la_running_no_interference",
640
+ la_problem_workflow,
641
+ );
642
+ worker.register_activity("delay", |_: ActContext, _: String| async {
643
+ tokio::time::sleep(Duration::from_secs(15)).await;
644
+ Ok(())
645
+ });
646
+ worker.run().await.unwrap();
647
+ }
@@ -2,7 +2,7 @@ use std::{
2
2
  sync::atomic::{AtomicBool, Ordering},
3
3
  time::Duration,
4
4
  };
5
- use temporal_client::WorkflowOptions;
5
+
6
6
  use temporal_sdk::{WfContext, WorkflowResult};
7
7
  use temporal_sdk_core_test_utils::CoreWfStarter;
8
8
 
@@ -30,15 +30,7 @@ async fn writes_change_markers() {
30
30
  let mut worker = starter.worker().await;
31
31
  worker.register_wf(wf_name.to_owned(), changes_wf);
32
32
 
33
- worker
34
- .submit_wf(
35
- wf_name.to_owned(),
36
- wf_name.to_owned(),
37
- vec![],
38
- WorkflowOptions::default(),
39
- )
40
- .await
41
- .unwrap();
33
+ starter.start_with_worker(wf_name, &mut worker).await;
42
34
  worker.run_until_done().await.unwrap();
43
35
  }
44
36
 
@@ -70,15 +62,7 @@ async fn can_add_change_markers() {
70
62
  let mut worker = starter.worker().await;
71
63
  worker.register_wf(wf_name.to_owned(), no_change_then_change_wf);
72
64
 
73
- worker
74
- .submit_wf(
75
- wf_name.to_owned(),
76
- wf_name.to_owned(),
77
- vec![],
78
- WorkflowOptions::default(),
79
- )
80
- .await
81
- .unwrap();
65
+ starter.start_with_worker(wf_name, &mut worker).await;
82
66
  worker.run_until_done().await.unwrap();
83
67
  }
84
68
 
@@ -100,14 +84,6 @@ async fn replaying_with_patch_marker() {
100
84
  let mut worker = starter.worker().await;
101
85
  worker.register_wf(wf_name.to_owned(), replay_with_change_marker_wf);
102
86
 
103
- worker
104
- .submit_wf(
105
- wf_name.to_owned(),
106
- wf_name.to_owned(),
107
- vec![],
108
- WorkflowOptions::default(),
109
- )
110
- .await
111
- .unwrap();
87
+ starter.start_with_worker(wf_name, &mut worker).await;
112
88
  worker.run_until_done().await.unwrap();
113
89
  }
@@ -129,18 +129,23 @@ async fn replay_using_wf_function() {
129
129
  worker.run().await.unwrap();
130
130
  }
131
131
 
132
+ async fn replay_abrupt_ending(t: TestHistoryBuilder) {
133
+ let func = timers_wf(1);
134
+ let mut worker = replay_sdk_worker([test_hist_to_replay(t)]);
135
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
136
+ worker.run().await.unwrap();
137
+ }
132
138
  #[tokio::test]
133
- async fn replay_ok_ending_with_terminated_or_timed_out() {
139
+ async fn replay_ok_ending_with_terminated() {
134
140
  let mut t1 = canned_histories::single_timer("1");
135
141
  t1.add_workflow_execution_terminated();
142
+ replay_abrupt_ending(t1).await;
143
+ }
144
+ #[tokio::test]
145
+ async fn replay_ok_ending_with_timed_out() {
136
146
  let mut t2 = canned_histories::single_timer("1");
137
147
  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
- }
148
+ replay_abrupt_ending(t2).await;
144
149
  }
145
150
 
146
151
  #[rstest::rstest]
@@ -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
  };
@@ -59,7 +61,6 @@ async fn signal_receiver(ctx: WfContext) -> WorkflowResult<()> {
59
61
 
60
62
  async fn signal_with_create_wf_receiver(ctx: WfContext) -> WorkflowResult<()> {
61
63
  let res = ctx.make_signal_channel(SIGNAME).next().await.unwrap();
62
- println!("HEADER: {:?}", res.headers);
63
64
  assert_eq!(&res.input, &[b"tada".into()]);
64
65
  assert_eq!(
65
66
  *res.headers.get("tupac").expect("tupac header exists"),
@@ -100,23 +101,22 @@ async fn sends_signal_to_other_wf() {
100
101
  async fn sends_signal_with_create_wf() {
101
102
  let mut starter = CoreWfStarter::new("sends_signal_with_create_wf");
102
103
  let mut worker = starter.worker().await;
103
- worker.register_wf("receiversignal", signal_with_create_wf_receiver);
104
+ worker.register_wf("receiver_signal", signal_with_create_wf_receiver);
104
105
 
105
106
  let client = starter.get_client().await;
106
107
  let mut header: HashMap<String, Payload> = HashMap::new();
107
108
  header.insert("tupac".into(), "shakur".into());
109
+ let options = SignalWithStartOptions::builder()
110
+ .task_queue(worker.inner_mut().task_queue())
111
+ .workflow_id("sends_signal_with_create_wf")
112
+ .workflow_type("receiver_signal")
113
+ .signal_name(SIGNAME)
114
+ .signal_input(vec![b"tada".into()].into_payloads())
115
+ .signal_header(header.into())
116
+ .build()
117
+ .unwrap();
108
118
  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
- )
119
+ .signal_with_start_workflow_execution(options, WorkflowOptions::default())
120
120
  .await
121
121
  .expect("request succeeds.qed");
122
122
 
@@ -16,15 +16,7 @@ async fn timer_workflow_not_sticky() {
16
16
  let mut worker = starter.worker().await;
17
17
  worker.register_wf(wf_name.to_owned(), timer_wf);
18
18
 
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();
19
+ starter.start_with_worker(wf_name, &mut worker).await;
28
20
  worker.run_until_done().await.unwrap();
29
21
  }
30
22
 
@@ -47,19 +39,11 @@ async fn timer_workflow_timeout_on_sticky() {
47
39
  // on a not-sticky queue
48
40
  let wf_name = "timer_workflow_timeout_on_sticky";
49
41
  let mut starter = CoreWfStarter::new(wf_name);
50
- starter.wft_timeout(Duration::from_secs(2));
42
+ starter.workflow_options.task_timeout = Some(Duration::from_secs(2));
51
43
  let mut worker = starter.worker().await;
52
44
  worker.register_wf(wf_name.to_owned(), timer_timeout_wf);
53
45
 
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();
46
+ starter.start_with_worker(wf_name, &mut worker).await;
63
47
  worker.run_until_done().await.unwrap();
64
48
  // If it didn't run twice it didn't time out
65
49
  assert_eq!(RUN_CT.load(Ordering::SeqCst), 2);
@@ -1,5 +1,5 @@
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},
@@ -21,15 +21,7 @@ async fn timer_workflow_workflow_driver() {
21
21
  let mut worker = starter.worker().await;
22
22
  worker.register_wf(wf_name.to_owned(), timer_wf);
23
23
 
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();
24
+ starter.start_with_worker(wf_name, &mut worker).await;
33
25
  worker.run_until_done().await.unwrap();
34
26
  }
35
27
 
@@ -118,14 +110,6 @@ async fn parallel_timers() {
118
110
  let mut worker = starter.worker().await;
119
111
  worker.register_wf(wf_name.to_owned(), parallel_timer_wf);
120
112
 
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();
113
+ starter.start_with_worker(wf_name, &mut worker).await;
130
114
  worker.run_until_done().await.unwrap();
131
115
  }
@@ -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
5
  use temporal_sdk_core_test_utils::{CoreWfStarter, INTEG_TEMPORALITE_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