@temporalio/core-bridge 0.19.2 → 0.20.2

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 (125) hide show
  1. package/Cargo.lock +90 -157
  2. package/Cargo.toml +1 -0
  3. package/index.d.ts +11 -27
  4. package/package.json +3 -3
  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 +1 -1
  11. package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
  12. package/sdk-core/.cargo/config.toml +1 -0
  13. package/sdk-core/CODEOWNERS +1 -1
  14. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +119 -86
  15. package/sdk-core/bridge-ffi/src/lib.rs +311 -315
  16. package/sdk-core/bridge-ffi/src/wrappers.rs +108 -113
  17. package/sdk-core/client/Cargo.toml +13 -9
  18. package/sdk-core/client/LICENSE.txt +23 -0
  19. package/sdk-core/client/src/lib.rs +286 -174
  20. package/sdk-core/client/src/metrics.rs +86 -12
  21. package/sdk-core/client/src/raw.rs +566 -0
  22. package/sdk-core/client/src/retry.rs +137 -99
  23. package/sdk-core/core/Cargo.toml +15 -10
  24. package/sdk-core/core/LICENSE.txt +23 -0
  25. package/sdk-core/core/benches/workflow_replay.rs +79 -0
  26. package/sdk-core/core/src/abstractions.rs +38 -0
  27. package/sdk-core/core/src/core_tests/activity_tasks.rs +108 -182
  28. package/sdk-core/core/src/core_tests/child_workflows.rs +16 -11
  29. package/sdk-core/core/src/core_tests/determinism.rs +24 -12
  30. package/sdk-core/core/src/core_tests/local_activities.rs +53 -27
  31. package/sdk-core/core/src/core_tests/mod.rs +30 -43
  32. package/sdk-core/core/src/core_tests/queries.rs +82 -81
  33. package/sdk-core/core/src/core_tests/workers.rs +111 -296
  34. package/sdk-core/core/src/core_tests/workflow_cancels.rs +4 -4
  35. package/sdk-core/core/src/core_tests/workflow_tasks.rs +257 -242
  36. package/sdk-core/core/src/lib.rs +73 -318
  37. package/sdk-core/core/src/pollers/mod.rs +4 -6
  38. package/sdk-core/core/src/pollers/poll_buffer.rs +20 -14
  39. package/sdk-core/core/src/protosext/mod.rs +7 -10
  40. package/sdk-core/core/src/replay/mod.rs +11 -150
  41. package/sdk-core/core/src/telemetry/metrics.rs +35 -2
  42. package/sdk-core/core/src/telemetry/mod.rs +49 -16
  43. package/sdk-core/core/src/telemetry/prometheus_server.rs +14 -35
  44. package/sdk-core/core/src/test_help/mod.rs +104 -170
  45. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +57 -34
  46. package/sdk-core/core/src/worker/activities/local_activities.rs +95 -23
  47. package/sdk-core/core/src/worker/activities.rs +23 -16
  48. package/sdk-core/core/src/worker/client/mocks.rs +86 -0
  49. package/sdk-core/core/src/worker/client.rs +209 -0
  50. package/sdk-core/core/src/worker/mod.rs +207 -108
  51. package/sdk-core/core/src/workflow/driven_workflow.rs +21 -6
  52. package/sdk-core/core/src/workflow/history_update.rs +107 -24
  53. package/sdk-core/core/src/workflow/machines/activity_state_machine.rs +2 -3
  54. package/sdk-core/core/src/workflow/machines/child_workflow_state_machine.rs +2 -3
  55. package/sdk-core/core/src/workflow/machines/mod.rs +20 -17
  56. package/sdk-core/core/src/workflow/machines/signal_external_state_machine.rs +56 -19
  57. package/sdk-core/core/src/workflow/machines/transition_coverage.rs +5 -0
  58. package/sdk-core/core/src/workflow/machines/upsert_search_attributes_state_machine.rs +230 -22
  59. package/sdk-core/core/src/workflow/machines/workflow_machines.rs +81 -115
  60. package/sdk-core/core/src/workflow/machines/workflow_task_state_machine.rs +4 -4
  61. package/sdk-core/core/src/workflow/mod.rs +13 -1
  62. package/sdk-core/core/src/workflow/workflow_tasks/concurrency_manager.rs +70 -11
  63. package/sdk-core/core/src/workflow/workflow_tasks/mod.rs +65 -41
  64. package/sdk-core/core-api/Cargo.toml +9 -1
  65. package/sdk-core/core-api/LICENSE.txt +23 -0
  66. package/sdk-core/core-api/src/errors.rs +7 -38
  67. package/sdk-core/core-api/src/lib.rs +44 -52
  68. package/sdk-core/core-api/src/worker.rs +10 -2
  69. package/sdk-core/etc/deps.svg +127 -96
  70. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +11 -7
  71. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +10 -0
  72. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +6 -1
  73. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +6 -0
  74. package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +6 -0
  75. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +2 -1
  76. package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +3 -0
  77. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +12 -0
  78. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +25 -0
  79. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -0
  80. package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +19 -35
  81. package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +2 -6
  82. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +53 -11
  83. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +14 -7
  84. package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +3 -5
  85. package/sdk-core/sdk/Cargo.toml +16 -2
  86. package/sdk-core/sdk/LICENSE.txt +23 -0
  87. package/sdk-core/sdk/src/interceptors.rs +11 -0
  88. package/sdk-core/sdk/src/lib.rs +139 -151
  89. package/sdk-core/sdk/src/workflow_context/options.rs +86 -1
  90. package/sdk-core/sdk/src/workflow_context.rs +36 -17
  91. package/sdk-core/sdk/src/workflow_future.rs +19 -25
  92. package/sdk-core/sdk-core-protos/Cargo.toml +1 -1
  93. package/sdk-core/sdk-core-protos/build.rs +1 -0
  94. package/sdk-core/sdk-core-protos/src/history_info.rs +17 -4
  95. package/sdk-core/sdk-core-protos/src/lib.rs +251 -47
  96. package/sdk-core/test-utils/Cargo.toml +3 -1
  97. package/sdk-core/test-utils/src/canned_histories.rs +27 -0
  98. package/sdk-core/test-utils/src/histfetch.rs +3 -3
  99. package/sdk-core/test-utils/src/lib.rs +223 -68
  100. package/sdk-core/tests/integ_tests/client_tests.rs +27 -4
  101. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +93 -14
  102. package/sdk-core/tests/integ_tests/polling_tests.rs +18 -12
  103. package/sdk-core/tests/integ_tests/queries_tests.rs +50 -53
  104. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +117 -103
  105. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +8 -1
  106. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +10 -5
  107. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +7 -1
  108. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +32 -9
  109. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +7 -1
  110. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +76 -15
  111. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +19 -3
  112. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +39 -42
  113. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +84 -0
  114. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +30 -8
  115. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +21 -6
  116. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +26 -16
  117. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +66 -0
  118. package/sdk-core/tests/integ_tests/workflow_tests.rs +78 -74
  119. package/sdk-core/tests/load_tests.rs +9 -6
  120. package/sdk-core/tests/main.rs +43 -10
  121. package/src/conversions.rs +7 -12
  122. package/src/lib.rs +322 -357
  123. package/sdk-core/client/src/mocks.rs +0 -167
  124. package/sdk-core/core/src/worker/dispatcher.rs +0 -171
  125. package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +0 -61
@@ -1,4 +1,5 @@
1
1
  use std::time::Duration;
2
+ use temporal_client::{WorkflowClientTrait, WorkflowOptions};
2
3
  use temporal_sdk::{WfContext, WfExitValue, WorkflowResult};
3
4
  use temporal_sdk_core_protos::temporal::api::enums::v1::WorkflowExecutionStatus;
4
5
  use temporal_sdk_core_test_utils::CoreWfStarter;
@@ -20,19 +21,24 @@ async fn cancelled_wf(mut ctx: WfContext) -> WorkflowResult<()> {
20
21
  async fn cancel_during_timer() {
21
22
  let wf_name = "cancel_during_timer";
22
23
  let mut starter = CoreWfStarter::new(wf_name);
23
- let core = starter.get_core().await;
24
24
  let mut worker = starter.worker().await;
25
+ let client = starter.get_client().await;
25
26
  worker.register_wf(wf_name.to_string(), cancelled_wf);
26
27
 
27
28
  worker
28
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
29
+ .submit_wf(
30
+ wf_name.to_owned(),
31
+ wf_name.to_owned(),
32
+ vec![],
33
+ WorkflowOptions::default(),
34
+ )
29
35
  .await
30
36
  .unwrap();
31
37
 
32
38
  let canceller = async {
33
39
  tokio::time::sleep(Duration::from_millis(500)).await;
34
40
  // Cancel the workflow externally
35
- core.server_gateway()
41
+ client
36
42
  .cancel_workflow_execution(wf_name.to_string(), None)
37
43
  .await
38
44
  .unwrap();
@@ -40,8 +46,7 @@ async fn cancel_during_timer() {
40
46
 
41
47
  let (_, res) = tokio::join!(canceller, worker.run_until_done());
42
48
  res.unwrap();
43
- let desc = core
44
- .server_gateway()
49
+ let desc = client
45
50
  .describe_workflow_execution(wf_name.to_string(), None)
46
51
  .await
47
52
  .unwrap();
@@ -1,4 +1,5 @@
1
1
  use anyhow::anyhow;
2
+ use temporal_client::WorkflowOptions;
2
3
  use temporal_sdk::{ChildWorkflowOptions, WfContext, WorkflowResult};
3
4
  use temporal_sdk_core_protos::coresdk::child_workflow::{child_workflow_result, Success};
4
5
  use temporal_sdk_core_test_utils::CoreWfStarter;
@@ -38,7 +39,12 @@ async fn child_workflow_happy_path() {
38
39
  worker.incr_expected_run_count(1); // Expect another WF to be run as child
39
40
 
40
41
  worker
41
- .submit_wf("parent".to_string(), PARENT_WF_TYPE.to_owned(), vec![])
42
+ .submit_wf(
43
+ "parent".to_string(),
44
+ PARENT_WF_TYPE.to_owned(),
45
+ vec![],
46
+ WorkflowOptions::default(),
47
+ )
42
48
  .await
43
49
  .unwrap();
44
50
  worker.run_until_done().await.unwrap();
@@ -1,4 +1,5 @@
1
1
  use std::time::Duration;
2
+ use temporal_client::WorkflowOptions;
2
3
  use temporal_sdk::{WfContext, WfExitValue, WorkflowResult};
3
4
  use temporal_sdk_core_protos::coresdk::workflow_commands::ContinueAsNewWorkflowExecution;
4
5
  use temporal_sdk_core_test_utils::CoreWfStarter;
@@ -24,17 +25,39 @@ async fn continue_as_new_happy_path() {
24
25
  worker.register_wf(wf_name.to_string(), continue_as_new_wf);
25
26
 
26
27
  worker
27
- .submit_wf(wf_name.to_string(), wf_name.to_string(), vec![[1].into()])
28
+ .submit_wf(
29
+ wf_name.to_string(),
30
+ wf_name.to_string(),
31
+ vec![[1].into()],
32
+ WorkflowOptions::default(),
33
+ )
28
34
  .await
29
35
  .unwrap();
36
+ // The four additional runs
37
+ worker.incr_expected_run_count(4);
30
38
  worker.run_until_done().await.unwrap();
39
+ }
31
40
 
32
- // Terminate the continued workflow
33
- starter
34
- .get_core()
35
- .await
36
- .server_gateway()
37
- .terminate_workflow_execution(wf_name.to_owned(), None)
38
- .await
39
- .unwrap();
41
+ #[tokio::test]
42
+ async fn continue_as_new_multiple_concurrent() {
43
+ let wf_name = "continue_as_new_multiple_concurrent";
44
+ let mut starter = CoreWfStarter::new(wf_name);
45
+ starter.max_cached_workflows(3).max_wft(3);
46
+ let mut worker = starter.worker().await;
47
+ worker.register_wf(wf_name.to_string(), continue_as_new_wf);
48
+
49
+ let wf_names = (1..=20).map(|i| format!("{}-{}", wf_name, i));
50
+ for name in wf_names.clone() {
51
+ worker
52
+ .submit_wf(
53
+ name.to_string(),
54
+ wf_name.to_string(),
55
+ vec![[1].into()],
56
+ WorkflowOptions::default(),
57
+ )
58
+ .await
59
+ .unwrap();
60
+ }
61
+ worker.incr_expected_run_count(20 * 4);
62
+ worker.run_until_done().await.unwrap();
40
63
  }
@@ -2,6 +2,7 @@ use std::{
2
2
  sync::atomic::{AtomicUsize, Ordering},
3
3
  time::Duration,
4
4
  };
5
+ use temporal_client::WorkflowOptions;
5
6
  use temporal_sdk::{ActivityOptions, WfContext, WorkflowResult};
6
7
  use temporal_sdk_core_test_utils::CoreWfStarter;
7
8
 
@@ -39,7 +40,12 @@ async fn test_determinism_error_then_recovers() {
39
40
 
40
41
  worker.register_wf(wf_name.to_owned(), timer_wf_nondeterministic);
41
42
  worker
42
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
43
+ .submit_wf(
44
+ wf_name.to_owned(),
45
+ wf_name.to_owned(),
46
+ vec![],
47
+ WorkflowOptions::default(),
48
+ )
43
49
  .await
44
50
  .unwrap();
45
51
  worker.run_until_done().await.unwrap();
@@ -1,6 +1,7 @@
1
1
  use anyhow::anyhow;
2
2
  use futures::future::join_all;
3
3
  use std::time::Duration;
4
+ use temporal_client::WorkflowOptions;
4
5
  use temporal_sdk::{
5
6
  act_cancelled, act_is_cancelled, ActivityCancelledError, CancellableFuture,
6
7
  LocalActivityOptions, WfContext, WorkflowResult,
@@ -37,7 +38,12 @@ async fn one_local_activity() {
37
38
  worker.register_activity("echo_activity", echo);
38
39
 
39
40
  worker
40
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
41
+ .submit_wf(
42
+ wf_name.to_owned(),
43
+ wf_name.to_owned(),
44
+ vec![],
45
+ WorkflowOptions::default(),
46
+ )
41
47
  .await
42
48
  .unwrap();
43
49
  worker.run_until_done().await.unwrap();
@@ -63,7 +69,12 @@ async fn local_act_concurrent_with_timer() {
63
69
  worker.register_activity("echo_activity", echo);
64
70
 
65
71
  worker
66
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
72
+ .submit_wf(
73
+ wf_name.to_owned(),
74
+ wf_name.to_owned(),
75
+ vec![],
76
+ WorkflowOptions::default(),
77
+ )
67
78
  .await
68
79
  .unwrap();
69
80
  worker.run_until_done().await.unwrap();
@@ -90,7 +101,12 @@ async fn local_act_then_timer_then_wait_result() {
90
101
  worker.register_activity("echo_activity", echo);
91
102
 
92
103
  worker
93
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
104
+ .submit_wf(
105
+ wf_name.to_owned(),
106
+ wf_name.to_owned(),
107
+ vec![],
108
+ WorkflowOptions::default(),
109
+ )
94
110
  .await
95
111
  .unwrap();
96
112
  worker.run_until_done().await.unwrap();
@@ -109,7 +125,12 @@ async fn long_running_local_act_with_timer() {
109
125
  });
110
126
 
111
127
  worker
112
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
128
+ .submit_wf(
129
+ wf_name.to_owned(),
130
+ wf_name.to_owned(),
131
+ vec![],
132
+ WorkflowOptions::default(),
133
+ )
113
134
  .await
114
135
  .unwrap();
115
136
  worker.run_until_done().await.unwrap();
@@ -142,7 +163,12 @@ async fn local_act_fanout() {
142
163
  worker.register_activity("echo_activity", echo);
143
164
 
144
165
  worker
145
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
166
+ .submit_wf(
167
+ wf_name.to_owned(),
168
+ wf_name.to_owned(),
169
+ vec![],
170
+ WorkflowOptions::default(),
171
+ )
146
172
  .await
147
173
  .unwrap();
148
174
  worker.run_until_done().await.unwrap();
@@ -178,12 +204,17 @@ async fn local_act_retry_timer_backoff() {
178
204
  });
179
205
 
180
206
  let run_id = worker
181
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
207
+ .submit_wf(
208
+ wf_name.to_owned(),
209
+ wf_name.to_owned(),
210
+ vec![],
211
+ WorkflowOptions::default(),
212
+ )
182
213
  .await
183
214
  .unwrap();
184
215
  worker.run_until_done().await.unwrap();
185
216
  starter
186
- .fetch_history_and_replay(wf_name, run_id, &mut worker)
217
+ .fetch_history_and_replay(wf_name, run_id, worker.inner_mut())
187
218
  .await
188
219
  .unwrap();
189
220
  }
@@ -229,11 +260,16 @@ async fn cancel_immediate(#[case] cancel_type: ActivityCancellationType) {
229
260
  });
230
261
 
231
262
  worker
232
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
263
+ .submit_wf(
264
+ wf_name.to_owned(),
265
+ wf_name.to_owned(),
266
+ vec![],
267
+ WorkflowOptions::default(),
268
+ )
233
269
  .await
234
270
  .unwrap();
235
271
  worker
236
- .run_until_done_shutdown_hook(|| manual_cancel.cancel())
272
+ .run_until_done_shutdown_hook(move || manual_cancel.cancel())
237
273
  .await
238
274
  .unwrap();
239
275
  }
@@ -318,11 +354,16 @@ async fn cancel_after_act_starts(
318
354
  });
319
355
 
320
356
  worker
321
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
357
+ .submit_wf(
358
+ wf_name.to_owned(),
359
+ wf_name.to_owned(),
360
+ vec![],
361
+ WorkflowOptions::default(),
362
+ )
322
363
  .await
323
364
  .unwrap();
324
365
  worker
325
- .run_until_done_shutdown_hook(|| manual_cancel.cancel())
366
+ .run_until_done_shutdown_hook(move || manual_cancel.cancel())
326
367
  .await
327
368
  .unwrap();
328
369
  }
@@ -376,7 +417,12 @@ async fn x_to_close_timeout(#[case] is_schedule: bool) {
376
417
  });
377
418
 
378
419
  worker
379
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
420
+ .submit_wf(
421
+ wf_name.to_owned(),
422
+ wf_name.to_owned(),
423
+ vec![],
424
+ WorkflowOptions::default(),
425
+ )
380
426
  .await
381
427
  .unwrap();
382
428
  worker.run_until_done().await.unwrap();
@@ -421,7 +467,12 @@ async fn schedule_to_close_timeout_across_timer_backoff(#[case] cached: bool) {
421
467
  });
422
468
 
423
469
  worker
424
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
470
+ .submit_wf(
471
+ wf_name.to_owned(),
472
+ wf_name.to_owned(),
473
+ vec![],
474
+ WorkflowOptions::default(),
475
+ )
425
476
  .await
426
477
  .unwrap();
427
478
  worker.run_until_done().await.unwrap();
@@ -441,7 +492,12 @@ async fn eviction_wont_make_local_act_get_dropped() {
441
492
  });
442
493
 
443
494
  worker
444
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
495
+ .submit_wf(
496
+ wf_name.to_owned(),
497
+ wf_name.to_owned(),
498
+ vec![],
499
+ WorkflowOptions::default(),
500
+ )
445
501
  .await
446
502
  .unwrap();
447
503
  worker.run_until_done().await.unwrap();
@@ -489,7 +545,12 @@ async fn timer_backoff_concurrent_with_non_timer_backoff() {
489
545
  });
490
546
 
491
547
  worker
492
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
548
+ .submit_wf(
549
+ wf_name.to_owned(),
550
+ wf_name.to_owned(),
551
+ vec![],
552
+ WorkflowOptions::default(),
553
+ )
493
554
  .await
494
555
  .unwrap();
495
556
  worker.run_until_done().await.unwrap();
@@ -2,6 +2,7 @@ use std::{
2
2
  sync::atomic::{AtomicBool, Ordering},
3
3
  time::Duration,
4
4
  };
5
+ use temporal_client::WorkflowOptions;
5
6
  use temporal_sdk::{WfContext, WorkflowResult};
6
7
  use temporal_sdk_core_test_utils::CoreWfStarter;
7
8
 
@@ -30,7 +31,12 @@ async fn writes_change_markers() {
30
31
  worker.register_wf(wf_name.to_owned(), changes_wf);
31
32
 
32
33
  worker
33
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
34
+ .submit_wf(
35
+ wf_name.to_owned(),
36
+ wf_name.to_owned(),
37
+ vec![],
38
+ WorkflowOptions::default(),
39
+ )
34
40
  .await
35
41
  .unwrap();
36
42
  worker.run_until_done().await.unwrap();
@@ -65,7 +71,12 @@ async fn can_add_change_markers() {
65
71
  worker.register_wf(wf_name.to_owned(), no_change_then_change_wf);
66
72
 
67
73
  worker
68
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
74
+ .submit_wf(
75
+ wf_name.to_owned(),
76
+ wf_name.to_owned(),
77
+ vec![],
78
+ WorkflowOptions::default(),
79
+ )
69
80
  .await
70
81
  .unwrap();
71
82
  worker.run_until_done().await.unwrap();
@@ -90,7 +101,12 @@ async fn replaying_with_patch_marker() {
90
101
  worker.register_wf(wf_name.to_owned(), replay_with_change_marker_wf);
91
102
 
92
103
  worker
93
- .submit_wf(wf_name.to_owned(), wf_name.to_owned(), vec![])
104
+ .submit_wf(
105
+ wf_name.to_owned(),
106
+ wf_name.to_owned(),
107
+ vec![],
108
+ WorkflowOptions::default(),
109
+ )
94
110
  .await
95
111
  .unwrap();
96
112
  worker.run_until_done().await.unwrap();
@@ -1,6 +1,7 @@
1
1
  use assert_matches::assert_matches;
2
2
  use std::time::Duration;
3
- use temporal_sdk_core::{replay::mock_gateway_from_history, ServerGatewayApis};
3
+ use temporal_sdk::{WfContext, Worker, WorkflowFunction};
4
+ use temporal_sdk_core::telemetry_init;
4
5
  use temporal_sdk_core_api::errors::{PollActivityError, PollWfError};
5
6
  use temporal_sdk_core_protos::{
6
7
  coresdk::{
@@ -8,24 +9,24 @@ use temporal_sdk_core_protos::{
8
9
  workflow_commands::{ScheduleActivity, StartTimer},
9
10
  workflow_completion::WorkflowActivationCompletion,
10
11
  },
11
- temporal::api::workflowservice::v1::PollWorkflowTaskQueueResponse,
12
+ DEFAULT_WORKFLOW_TYPE,
12
13
  };
13
14
  use temporal_sdk_core_test_utils::{
14
- history_from_proto_binary, init_core_replay_preloaded, CoreTestHelpers,
15
+ canned_histories, get_integ_telem_options, history_from_proto_binary,
16
+ init_core_replay_preloaded, WorkerTestHelpers,
15
17
  };
16
18
  use tokio::join;
17
19
 
18
20
  #[tokio::test]
19
21
  async fn timer_workflow_replay() {
20
- let (core, task_q) = init_core_replay_preloaded(
22
+ let (core, _) = init_core_replay_preloaded(
21
23
  "timer_workflow_replay",
22
24
  &history_from_proto_binary("histories/timer_workflow_history.bin")
23
25
  .await
24
26
  .unwrap(),
25
27
  );
26
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
28
+ let task = core.poll_workflow_activation().await.unwrap();
27
29
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
28
- &task_q,
29
30
  task.run_id,
30
31
  vec![StartTimer {
31
32
  seq: 0,
@@ -35,70 +36,44 @@ async fn timer_workflow_replay() {
35
36
  ))
36
37
  .await
37
38
  .unwrap();
38
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
39
+ let task = core.poll_workflow_activation().await.unwrap();
39
40
  // Verify that an in-progress poll is interrupted by completion finishing processing history
40
41
  let act_poll_fut = async {
41
42
  assert_matches!(
42
- core.poll_activity_task(&task_q).await,
43
+ core.poll_activity_task().await,
43
44
  Err(PollActivityError::ShutDown)
44
45
  );
45
46
  };
46
47
  let poll_fut = async {
47
48
  assert_matches!(
48
- core.poll_workflow_activation(&task_q).await,
49
+ core.poll_workflow_activation().await,
49
50
  Err(PollWfError::ShutDown)
50
51
  );
51
52
  };
52
53
  let complete_fut = async {
53
- core.complete_execution(&task_q, &task.run_id).await;
54
+ core.complete_execution(&task.run_id).await;
54
55
  };
55
56
  join!(act_poll_fut, poll_fut, complete_fut);
56
57
 
57
58
  // Subsequent polls should still return shutdown
58
59
  assert_matches!(
59
- core.poll_workflow_activation(&task_q).await,
60
+ core.poll_workflow_activation().await,
60
61
  Err(PollWfError::ShutDown)
61
62
  );
62
63
 
63
64
  core.shutdown().await;
64
65
  }
65
66
 
66
- // Regression test to verify mock replayers don't interfere with each other
67
- #[tokio::test]
68
- async fn two_cores_replay() {
69
- let hist = history_from_proto_binary("histories/fail_wf_task.bin")
70
- .await
71
- .unwrap();
72
-
73
- let mock_1 = mock_gateway_from_history(&hist, "a");
74
- let mock_2 = mock_gateway_from_history(&hist, "b");
75
- assert_ne!(
76
- mock_1
77
- .poll_workflow_task("a".to_string(), false)
78
- .await
79
- .unwrap(),
80
- PollWorkflowTaskQueueResponse::default()
81
- );
82
- assert_ne!(
83
- mock_2
84
- .poll_workflow_task("b".to_string(), false)
85
- .await
86
- .unwrap(),
87
- PollWorkflowTaskQueueResponse::default()
88
- );
89
- }
90
-
91
67
  #[tokio::test]
92
68
  async fn workflow_nondeterministic_replay() {
93
- let (core, task_q) = init_core_replay_preloaded(
69
+ let (core, _) = init_core_replay_preloaded(
94
70
  "timer_workflow_replay",
95
71
  &history_from_proto_binary("histories/timer_workflow_history.bin")
96
72
  .await
97
73
  .unwrap(),
98
74
  );
99
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
75
+ let task = core.poll_workflow_activation().await.unwrap();
100
76
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
101
- &task_q,
102
77
  task.run_id,
103
78
  vec![ScheduleActivity {
104
79
  seq: 0,
@@ -110,16 +85,38 @@ async fn workflow_nondeterministic_replay() {
110
85
  ))
111
86
  .await
112
87
  .unwrap();
113
- let task = core.poll_workflow_activation(&task_q).await.unwrap();
88
+ let task = core.poll_workflow_activation().await.unwrap();
114
89
  assert_eq!(task.eviction_reason(), Some(EvictionReason::Nondeterminism));
115
90
  // Complete eviction
116
- core.complete_workflow_activation(WorkflowActivationCompletion::empty(&task_q, task.run_id))
91
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
117
92
  .await
118
93
  .unwrap();
119
94
  // Call shutdown explicitly because we saw a nondeterminism eviction
120
95
  core.shutdown().await;
121
96
  assert_matches!(
122
- core.poll_workflow_activation(&task_q).await,
97
+ core.poll_workflow_activation().await,
123
98
  Err(PollWfError::ShutDown)
124
99
  );
125
100
  }
101
+
102
+ #[tokio::test]
103
+ async fn replay_using_wf_function() {
104
+ telemetry_init(&get_integ_telem_options()).unwrap();
105
+ let num_timers = 10;
106
+ let t = canned_histories::long_sequential_timers(num_timers as usize);
107
+ let func = timers_wf(num_timers);
108
+ let (worker, _) =
109
+ init_core_replay_preloaded("replay_bench", &t.get_full_history_info().unwrap().into());
110
+ let mut worker = Worker::new_from_core(worker, "replay_bench".to_string());
111
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
112
+ worker.run().await.unwrap();
113
+ }
114
+
115
+ fn timers_wf(num_timers: u32) -> WorkflowFunction {
116
+ WorkflowFunction::new(move |ctx: WfContext| async move {
117
+ for _ in 1..=num_timers {
118
+ ctx.timer(Duration::from_secs(1)).await;
119
+ }
120
+ Ok(().into())
121
+ })
122
+ }
@@ -0,0 +1,84 @@
1
+ use futures::StreamExt;
2
+ use std::{sync::Arc, time::Duration};
3
+ use temporal_client::{WorkflowClientTrait, WorkflowOptions, WorkflowService};
4
+ use temporal_sdk::WfContext;
5
+ use temporal_sdk_core_protos::temporal::api::{
6
+ common::v1::WorkflowExecution, workflowservice::v1::ResetWorkflowExecutionRequest,
7
+ };
8
+ use temporal_sdk_core_test_utils::{CoreWfStarter, NAMESPACE};
9
+ use tokio::sync::Notify;
10
+
11
+ const POST_RESET_SIG: &str = "post-reset";
12
+
13
+ #[tokio::test]
14
+ async fn reset_workflow() {
15
+ let wf_name = "reset_me_wf";
16
+ let mut starter = CoreWfStarter::new(wf_name);
17
+ let mut worker = starter.worker().await;
18
+ let notify = Arc::new(Notify::new());
19
+
20
+ let wf_notify = notify.clone();
21
+ worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| {
22
+ let notify = wf_notify.clone();
23
+ async move {
24
+ // Make a couple workflow tasks
25
+ ctx.timer(Duration::from_secs(1)).await;
26
+ ctx.timer(Duration::from_secs(1)).await;
27
+ // Tell outer scope to send the reset
28
+ notify.notify_one();
29
+ let _ = ctx
30
+ .make_signal_channel(POST_RESET_SIG)
31
+ .next()
32
+ .await
33
+ .unwrap();
34
+ Ok(().into())
35
+ }
36
+ });
37
+
38
+ let run_id = worker
39
+ .submit_wf(
40
+ wf_name.to_owned(),
41
+ wf_name.to_owned(),
42
+ vec![],
43
+ WorkflowOptions::default(),
44
+ )
45
+ .await
46
+ .unwrap();
47
+
48
+ let client = starter.get_client().await;
49
+ let resetter_fut = async {
50
+ notify.notified().await;
51
+ // Do the reset
52
+ client
53
+ .get_client()
54
+ .raw_retry_client()
55
+ .reset_workflow_execution(ResetWorkflowExecutionRequest {
56
+ namespace: NAMESPACE.to_owned(),
57
+ workflow_execution: Some(WorkflowExecution {
58
+ workflow_id: wf_name.to_owned(),
59
+ run_id: run_id.clone(),
60
+ }),
61
+ // End of first WFT
62
+ workflow_task_finish_event_id: 4,
63
+ request_id: "test-req-id".to_owned(),
64
+ ..Default::default()
65
+ })
66
+ .await
67
+ .unwrap();
68
+
69
+ // Unblock the workflow by sending the signal. Run ID will have changed after reset so
70
+ // we use empty run id
71
+ client
72
+ .signal_workflow_execution(
73
+ wf_name.to_owned(),
74
+ "".to_owned(),
75
+ POST_RESET_SIG.to_owned(),
76
+ None,
77
+ )
78
+ .await
79
+ .unwrap();
80
+ };
81
+ let run_fut = worker.run_until_done();
82
+ let (_, rr) = tokio::join!(resetter_fut, run_fut);
83
+ rr.unwrap();
84
+ }