@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.
- package/Cargo.lock +90 -157
- package/Cargo.toml +1 -0
- package/index.d.ts +11 -27
- package/package.json +3 -3
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.buildkite/docker/Dockerfile +1 -1
- package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
- package/sdk-core/.cargo/config.toml +1 -0
- package/sdk-core/CODEOWNERS +1 -1
- package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +119 -86
- package/sdk-core/bridge-ffi/src/lib.rs +311 -315
- package/sdk-core/bridge-ffi/src/wrappers.rs +108 -113
- package/sdk-core/client/Cargo.toml +13 -9
- package/sdk-core/client/LICENSE.txt +23 -0
- package/sdk-core/client/src/lib.rs +286 -174
- package/sdk-core/client/src/metrics.rs +86 -12
- package/sdk-core/client/src/raw.rs +566 -0
- package/sdk-core/client/src/retry.rs +137 -99
- package/sdk-core/core/Cargo.toml +15 -10
- package/sdk-core/core/LICENSE.txt +23 -0
- package/sdk-core/core/benches/workflow_replay.rs +79 -0
- package/sdk-core/core/src/abstractions.rs +38 -0
- package/sdk-core/core/src/core_tests/activity_tasks.rs +108 -182
- package/sdk-core/core/src/core_tests/child_workflows.rs +16 -11
- package/sdk-core/core/src/core_tests/determinism.rs +24 -12
- package/sdk-core/core/src/core_tests/local_activities.rs +53 -27
- package/sdk-core/core/src/core_tests/mod.rs +30 -43
- package/sdk-core/core/src/core_tests/queries.rs +82 -81
- package/sdk-core/core/src/core_tests/workers.rs +111 -296
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +4 -4
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +257 -242
- package/sdk-core/core/src/lib.rs +73 -318
- package/sdk-core/core/src/pollers/mod.rs +4 -6
- package/sdk-core/core/src/pollers/poll_buffer.rs +20 -14
- package/sdk-core/core/src/protosext/mod.rs +7 -10
- package/sdk-core/core/src/replay/mod.rs +11 -150
- package/sdk-core/core/src/telemetry/metrics.rs +35 -2
- package/sdk-core/core/src/telemetry/mod.rs +49 -16
- package/sdk-core/core/src/telemetry/prometheus_server.rs +14 -35
- package/sdk-core/core/src/test_help/mod.rs +104 -170
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +57 -34
- package/sdk-core/core/src/worker/activities/local_activities.rs +95 -23
- package/sdk-core/core/src/worker/activities.rs +23 -16
- package/sdk-core/core/src/worker/client/mocks.rs +86 -0
- package/sdk-core/core/src/worker/client.rs +209 -0
- package/sdk-core/core/src/worker/mod.rs +207 -108
- package/sdk-core/core/src/workflow/driven_workflow.rs +21 -6
- package/sdk-core/core/src/workflow/history_update.rs +107 -24
- package/sdk-core/core/src/workflow/machines/activity_state_machine.rs +2 -3
- package/sdk-core/core/src/workflow/machines/child_workflow_state_machine.rs +2 -3
- package/sdk-core/core/src/workflow/machines/mod.rs +20 -17
- package/sdk-core/core/src/workflow/machines/signal_external_state_machine.rs +56 -19
- package/sdk-core/core/src/workflow/machines/transition_coverage.rs +5 -0
- package/sdk-core/core/src/workflow/machines/upsert_search_attributes_state_machine.rs +230 -22
- package/sdk-core/core/src/workflow/machines/workflow_machines.rs +81 -115
- package/sdk-core/core/src/workflow/machines/workflow_task_state_machine.rs +4 -4
- package/sdk-core/core/src/workflow/mod.rs +13 -1
- package/sdk-core/core/src/workflow/workflow_tasks/concurrency_manager.rs +70 -11
- package/sdk-core/core/src/workflow/workflow_tasks/mod.rs +65 -41
- package/sdk-core/core-api/Cargo.toml +9 -1
- package/sdk-core/core-api/LICENSE.txt +23 -0
- package/sdk-core/core-api/src/errors.rs +7 -38
- package/sdk-core/core-api/src/lib.rs +44 -52
- package/sdk-core/core-api/src/worker.rs +10 -2
- package/sdk-core/etc/deps.svg +127 -96
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +11 -7
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +10 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +6 -1
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +2 -1
- package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +3 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +12 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +25 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -0
- package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +19 -35
- package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +2 -6
- package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +53 -11
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +14 -7
- package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +3 -5
- package/sdk-core/sdk/Cargo.toml +16 -2
- package/sdk-core/sdk/LICENSE.txt +23 -0
- package/sdk-core/sdk/src/interceptors.rs +11 -0
- package/sdk-core/sdk/src/lib.rs +139 -151
- package/sdk-core/sdk/src/workflow_context/options.rs +86 -1
- package/sdk-core/sdk/src/workflow_context.rs +36 -17
- package/sdk-core/sdk/src/workflow_future.rs +19 -25
- package/sdk-core/sdk-core-protos/Cargo.toml +1 -1
- package/sdk-core/sdk-core-protos/build.rs +1 -0
- package/sdk-core/sdk-core-protos/src/history_info.rs +17 -4
- package/sdk-core/sdk-core-protos/src/lib.rs +251 -47
- package/sdk-core/test-utils/Cargo.toml +3 -1
- package/sdk-core/test-utils/src/canned_histories.rs +27 -0
- package/sdk-core/test-utils/src/histfetch.rs +3 -3
- package/sdk-core/test-utils/src/lib.rs +223 -68
- package/sdk-core/tests/integ_tests/client_tests.rs +27 -4
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +93 -14
- package/sdk-core/tests/integ_tests/polling_tests.rs +18 -12
- package/sdk-core/tests/integ_tests/queries_tests.rs +50 -53
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +117 -103
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +8 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +10 -5
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +7 -1
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +32 -9
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +7 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +76 -15
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +19 -3
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +39 -42
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +84 -0
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +30 -8
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +21 -6
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +26 -16
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +66 -0
- package/sdk-core/tests/integ_tests/workflow_tests.rs +78 -74
- package/sdk-core/tests/load_tests.rs +9 -6
- package/sdk-core/tests/main.rs +43 -10
- package/src/conversions.rs +7 -12
- package/src/lib.rs +322 -357
- package/sdk-core/client/src/mocks.rs +0 -167
- package/sdk-core/core/src/worker/dispatcher.rs +0 -171
- 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(
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
12
|
+
DEFAULT_WORKFLOW_TYPE,
|
|
12
13
|
};
|
|
13
14
|
use temporal_sdk_core_test_utils::{
|
|
14
|
-
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(&
|
|
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(
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
+
}
|