@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,6 +1,7 @@
|
|
|
1
1
|
use assert_matches::assert_matches;
|
|
2
2
|
use futures::future::join_all;
|
|
3
3
|
use std::time::Duration;
|
|
4
|
+
use temporal_client::WorkflowOptions;
|
|
4
5
|
use temporal_sdk::{WfContext, WorkflowResult};
|
|
5
6
|
use temporal_sdk_core_protos::coresdk::{
|
|
6
7
|
activity_task::activity_task as act_task,
|
|
@@ -10,21 +11,23 @@ use temporal_sdk_core_protos::coresdk::{
|
|
|
10
11
|
IntoCompletion,
|
|
11
12
|
};
|
|
12
13
|
use temporal_sdk_core_test_utils::{
|
|
13
|
-
init_core_and_create_wf, schedule_activity_cmd,
|
|
14
|
+
init_core_and_create_wf, schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
|
|
14
15
|
};
|
|
15
16
|
use tokio::time::timeout;
|
|
16
17
|
|
|
17
18
|
#[tokio::test]
|
|
18
19
|
async fn out_of_order_completion_doesnt_hang() {
|
|
19
|
-
let
|
|
20
|
+
let mut starter = init_core_and_create_wf("out_of_order_completion_doesnt_hang").await;
|
|
21
|
+
let core = starter.get_worker().await;
|
|
22
|
+
let task_q = starter.get_task_queue();
|
|
20
23
|
let activity_id = "act-1";
|
|
21
|
-
let task = core.poll_workflow_activation(
|
|
24
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
22
25
|
// Complete workflow task and schedule activity and a timer that fires immediately
|
|
23
26
|
core.complete_workflow_activation(
|
|
24
27
|
vec![
|
|
25
28
|
schedule_activity_cmd(
|
|
26
29
|
0,
|
|
27
|
-
|
|
30
|
+
task_q,
|
|
28
31
|
activity_id,
|
|
29
32
|
ActivityCancellationType::TryCancel,
|
|
30
33
|
Duration::from_secs(60),
|
|
@@ -36,13 +39,13 @@ async fn out_of_order_completion_doesnt_hang() {
|
|
|
36
39
|
}
|
|
37
40
|
.into(),
|
|
38
41
|
]
|
|
39
|
-
.into_completion(
|
|
42
|
+
.into_completion(task.run_id),
|
|
40
43
|
)
|
|
41
44
|
.await
|
|
42
45
|
.unwrap();
|
|
43
46
|
// Poll activity and verify that it's been scheduled with correct parameters, we don't expect to
|
|
44
47
|
// complete it in this test as activity is try-cancelled.
|
|
45
|
-
let activity_task = core.poll_activity_task(
|
|
48
|
+
let activity_task = core.poll_activity_task().await.unwrap();
|
|
46
49
|
assert_matches!(
|
|
47
50
|
activity_task.variant,
|
|
48
51
|
Some(act_task::Variant::Start(start_activity)) => {
|
|
@@ -50,7 +53,7 @@ async fn out_of_order_completion_doesnt_hang() {
|
|
|
50
53
|
}
|
|
51
54
|
);
|
|
52
55
|
// Poll workflow task and verify that activity has failed.
|
|
53
|
-
let task = core.poll_workflow_activation(
|
|
56
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
54
57
|
assert_matches!(
|
|
55
58
|
task.jobs.as_slice(),
|
|
56
59
|
[
|
|
@@ -66,10 +69,9 @@ async fn out_of_order_completion_doesnt_hang() {
|
|
|
66
69
|
|
|
67
70
|
// Start polling again *before* we complete the WFT
|
|
68
71
|
let cc = core.clone();
|
|
69
|
-
let tq = task_q.clone();
|
|
70
72
|
let jh = tokio::spawn(async move {
|
|
71
73
|
// We want to fail the test if this takes too long -- we should not hit long poll timeout
|
|
72
|
-
let task = timeout(Duration::from_secs(1), cc.poll_workflow_activation(
|
|
74
|
+
let task = timeout(Duration::from_secs(1), cc.poll_workflow_activation())
|
|
73
75
|
.await
|
|
74
76
|
.expect("Poll should come back right away")
|
|
75
77
|
.unwrap();
|
|
@@ -79,14 +81,13 @@ async fn out_of_order_completion_doesnt_hang() {
|
|
|
79
81
|
variant: Some(workflow_activation_job::Variant::ResolveActivity(_)),
|
|
80
82
|
}]
|
|
81
83
|
);
|
|
82
|
-
cc.complete_execution(&
|
|
84
|
+
cc.complete_execution(&task.run_id).await;
|
|
83
85
|
});
|
|
84
86
|
|
|
85
87
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
86
88
|
// Then complete the (last) WFT with a request to cancel the AT, which should produce a
|
|
87
89
|
// pending activation, unblocking the (already started) poll
|
|
88
90
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
89
|
-
&task_q,
|
|
90
91
|
task.run_id,
|
|
91
92
|
vec![RequestCancelActivity { seq: 0 }.into()],
|
|
92
93
|
))
|
|
@@ -120,7 +121,12 @@ async fn can_paginate_long_history() {
|
|
|
120
121
|
let mut worker = starter.worker().await;
|
|
121
122
|
worker.register_wf(wf_name.to_owned(), many_parallel_timers_longhist);
|
|
122
123
|
worker
|
|
123
|
-
.submit_wf(
|
|
124
|
+
.submit_wf(
|
|
125
|
+
wf_name.to_owned(),
|
|
126
|
+
wf_name.to_owned(),
|
|
127
|
+
vec![],
|
|
128
|
+
WorkflowOptions::default(),
|
|
129
|
+
)
|
|
124
130
|
.await
|
|
125
131
|
.unwrap();
|
|
126
132
|
worker.run_until_done().await.unwrap();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
use assert_matches::assert_matches;
|
|
2
2
|
use futures::{prelude::stream::FuturesUnordered, FutureExt, StreamExt};
|
|
3
3
|
use std::time::Duration;
|
|
4
|
+
use temporal_client::WorkflowClientTrait;
|
|
4
5
|
use temporal_sdk_core_protos::{
|
|
5
6
|
coresdk::{
|
|
6
7
|
workflow_activation::{workflow_activation_job, WorkflowActivationJob},
|
|
@@ -9,16 +10,16 @@ use temporal_sdk_core_protos::{
|
|
|
9
10
|
},
|
|
10
11
|
temporal::api::{failure::v1::Failure, query::v1::WorkflowQuery},
|
|
11
12
|
};
|
|
12
|
-
use temporal_sdk_core_test_utils::{init_core_and_create_wf,
|
|
13
|
+
use temporal_sdk_core_test_utils::{init_core_and_create_wf, CoreWfStarter, WorkerTestHelpers};
|
|
13
14
|
|
|
14
15
|
#[tokio::test]
|
|
15
16
|
async fn simple_query_legacy() {
|
|
16
17
|
let query_resp = b"response";
|
|
17
|
-
let
|
|
18
|
-
let
|
|
19
|
-
let
|
|
18
|
+
let mut starter = init_core_and_create_wf("simple_query_legacy").await;
|
|
19
|
+
let core = starter.get_worker().await;
|
|
20
|
+
let workflow_id = starter.get_task_queue().to_string();
|
|
21
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
20
22
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
21
|
-
&task_q,
|
|
22
23
|
task.run_id.clone(),
|
|
23
24
|
vec![
|
|
24
25
|
StartTimer {
|
|
@@ -38,7 +39,9 @@ async fn simple_query_legacy() {
|
|
|
38
39
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
39
40
|
// Query after timer should have fired and there should be new WFT
|
|
40
41
|
let query_fut = async {
|
|
41
|
-
|
|
42
|
+
starter
|
|
43
|
+
.get_client()
|
|
44
|
+
.await
|
|
42
45
|
.query_workflow_execution(
|
|
43
46
|
workflow_id,
|
|
44
47
|
task.run_id.to_string(),
|
|
@@ -56,7 +59,7 @@ async fn simple_query_legacy() {
|
|
|
56
59
|
tokio::time::sleep(Duration::from_millis(400)).await;
|
|
57
60
|
// This poll *should* have the `queries` field populated, but doesn't, seemingly due to
|
|
58
61
|
// a server bug. So, complete the WF task of the first timer firing with empty commands
|
|
59
|
-
let task = core.poll_workflow_activation(
|
|
62
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
60
63
|
assert_matches!(
|
|
61
64
|
task.jobs.as_slice(),
|
|
62
65
|
[WorkflowActivationJob {
|
|
@@ -64,13 +67,12 @@ async fn simple_query_legacy() {
|
|
|
64
67
|
}]
|
|
65
68
|
);
|
|
66
69
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
67
|
-
&task_q,
|
|
68
70
|
task.run_id,
|
|
69
71
|
vec![],
|
|
70
72
|
))
|
|
71
73
|
.await
|
|
72
74
|
.unwrap();
|
|
73
|
-
let task = core.poll_workflow_activation(
|
|
75
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
74
76
|
// Poll again, and we end up getting a `query` field query response
|
|
75
77
|
let query = assert_matches!(
|
|
76
78
|
task.jobs.as_slice(),
|
|
@@ -80,7 +82,6 @@ async fn simple_query_legacy() {
|
|
|
80
82
|
);
|
|
81
83
|
// Complete the query
|
|
82
84
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
83
|
-
&task_q,
|
|
84
85
|
task.run_id,
|
|
85
86
|
QueryResult {
|
|
86
87
|
query_id: query.query_id.clone(),
|
|
@@ -96,8 +97,8 @@ async fn simple_query_legacy() {
|
|
|
96
97
|
.await
|
|
97
98
|
.unwrap();
|
|
98
99
|
// Finish the workflow
|
|
99
|
-
let task = core.poll_workflow_activation(
|
|
100
|
-
core.complete_execution(&
|
|
100
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
101
|
+
core.complete_execution(&task.run_id).await;
|
|
101
102
|
};
|
|
102
103
|
let (q_resp, _) = tokio::join!(query_fut, workflow_completions_future);
|
|
103
104
|
// Ensure query response is as expected
|
|
@@ -110,13 +111,14 @@ async fn simple_query_legacy() {
|
|
|
110
111
|
#[tokio::test]
|
|
111
112
|
async fn query_after_execution_complete(#[case] do_evict: bool) {
|
|
112
113
|
let query_resp = b"response";
|
|
113
|
-
let
|
|
114
|
+
let mut starter =
|
|
114
115
|
init_core_and_create_wf(&format!("after_done_query_evict-{}", do_evict)).await;
|
|
115
|
-
let
|
|
116
|
+
let core = &starter.get_worker().await;
|
|
117
|
+
let workflow_id = &starter.get_task_queue().to_string();
|
|
116
118
|
|
|
117
119
|
let do_workflow = |go_until_query: bool| async move {
|
|
118
120
|
loop {
|
|
119
|
-
let task = core.poll_workflow_activation(
|
|
121
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
120
122
|
|
|
121
123
|
// When we see the query, handle it.
|
|
122
124
|
if go_until_query {
|
|
@@ -125,7 +127,6 @@ async fn query_after_execution_complete(#[case] do_evict: bool) {
|
|
|
125
127
|
}] = task.jobs.as_slice()
|
|
126
128
|
{
|
|
127
129
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
128
|
-
task_q,
|
|
129
130
|
task.run_id,
|
|
130
131
|
QueryResult {
|
|
131
132
|
query_id: query.query_id.clone(),
|
|
@@ -150,12 +151,9 @@ async fn query_after_execution_complete(#[case] do_evict: bool) {
|
|
|
150
151
|
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
|
151
152
|
}]
|
|
152
153
|
) {
|
|
153
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::empty(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
))
|
|
157
|
-
.await
|
|
158
|
-
.unwrap();
|
|
154
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
|
|
155
|
+
.await
|
|
156
|
+
.unwrap();
|
|
159
157
|
continue;
|
|
160
158
|
}
|
|
161
159
|
assert_matches!(
|
|
@@ -165,10 +163,10 @@ async fn query_after_execution_complete(#[case] do_evict: bool) {
|
|
|
165
163
|
}]
|
|
166
164
|
);
|
|
167
165
|
let run_id = task.run_id.clone();
|
|
168
|
-
core.complete_timer(
|
|
166
|
+
core.complete_timer(&task.run_id, 1, Duration::from_millis(500))
|
|
169
167
|
.await;
|
|
170
|
-
let task = core.poll_workflow_activation(
|
|
171
|
-
core.complete_execution(
|
|
168
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
169
|
+
core.complete_execution(&task.run_id).await;
|
|
172
170
|
if !go_until_query {
|
|
173
171
|
break run_id;
|
|
174
172
|
}
|
|
@@ -179,13 +177,13 @@ async fn query_after_execution_complete(#[case] do_evict: bool) {
|
|
|
179
177
|
assert!(!run_id.is_empty());
|
|
180
178
|
|
|
181
179
|
if do_evict {
|
|
182
|
-
core.request_workflow_eviction(
|
|
180
|
+
core.request_workflow_eviction(run_id);
|
|
183
181
|
}
|
|
184
182
|
// Spam some queries (sending multiple queries after WF closed covers a possible path where
|
|
185
183
|
// we could screw-up re-applying the final WFT)
|
|
186
184
|
let mut query_futs = FuturesUnordered::new();
|
|
187
185
|
for _ in 0..3 {
|
|
188
|
-
let gw =
|
|
186
|
+
let gw = starter.get_client().await.clone();
|
|
189
187
|
let query_fut = async move {
|
|
190
188
|
let q_resp = gw
|
|
191
189
|
.query_workflow_execution(
|
|
@@ -218,20 +216,20 @@ async fn repros_query_dropped_on_floor() {
|
|
|
218
216
|
let mut wf_starter = CoreWfStarter::new("repros_query_dropped_on_floor");
|
|
219
217
|
// Easiest way I discovered to reliably trigger new query path is with a WFT timeout
|
|
220
218
|
wf_starter.wft_timeout(Duration::from_secs(1));
|
|
221
|
-
let core = wf_starter.
|
|
222
|
-
let task_q = wf_starter.get_task_queue();
|
|
219
|
+
let core = wf_starter.get_worker().await;
|
|
220
|
+
let task_q = wf_starter.get_task_queue().to_string();
|
|
223
221
|
wf_starter.start_wf().await;
|
|
222
|
+
let client = wf_starter.get_client().await;
|
|
224
223
|
|
|
225
|
-
let task = core.poll_workflow_activation(
|
|
226
|
-
core.complete_timer(
|
|
224
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
225
|
+
core.complete_timer(&task.run_id, 1, Duration::from_millis(500))
|
|
227
226
|
.await;
|
|
228
227
|
|
|
229
228
|
// Poll for a task we will time out
|
|
230
|
-
let task = core.poll_workflow_activation(
|
|
229
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
231
230
|
tokio::time::sleep(Duration::from_secs(2)).await;
|
|
232
231
|
// Complete now-timed-out task (add a new timer)
|
|
233
232
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
234
|
-
task_q,
|
|
235
233
|
task.run_id.clone(),
|
|
236
234
|
vec![],
|
|
237
235
|
))
|
|
@@ -240,9 +238,9 @@ async fn repros_query_dropped_on_floor() {
|
|
|
240
238
|
|
|
241
239
|
let run_id = task.run_id.to_string();
|
|
242
240
|
let q1_fut = async {
|
|
243
|
-
|
|
241
|
+
client
|
|
244
242
|
.query_workflow_execution(
|
|
245
|
-
task_q.
|
|
243
|
+
task_q.clone(),
|
|
246
244
|
run_id,
|
|
247
245
|
WorkflowQuery {
|
|
248
246
|
query_type: "query_1".to_string(),
|
|
@@ -255,9 +253,9 @@ async fn repros_query_dropped_on_floor() {
|
|
|
255
253
|
};
|
|
256
254
|
let run_id = task.run_id.to_string();
|
|
257
255
|
let q2_fut = async {
|
|
258
|
-
|
|
256
|
+
client
|
|
259
257
|
.query_workflow_execution(
|
|
260
|
-
task_q.
|
|
258
|
+
task_q.clone(),
|
|
261
259
|
run_id,
|
|
262
260
|
WorkflowQuery {
|
|
263
261
|
query_type: "query_2".to_string(),
|
|
@@ -272,7 +270,7 @@ async fn repros_query_dropped_on_floor() {
|
|
|
272
270
|
let mut seen_q1 = false;
|
|
273
271
|
let mut seen_q2 = false;
|
|
274
272
|
while !seen_q1 || !seen_q2 {
|
|
275
|
-
let task = core.poll_workflow_activation(
|
|
273
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
276
274
|
|
|
277
275
|
if matches!(
|
|
278
276
|
task.jobs[0],
|
|
@@ -280,8 +278,8 @@ async fn repros_query_dropped_on_floor() {
|
|
|
280
278
|
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
|
281
279
|
}
|
|
282
280
|
) {
|
|
283
|
-
let task = core.poll_workflow_activation(
|
|
284
|
-
core.complete_timer(
|
|
281
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
282
|
+
core.complete_timer(&task.run_id, 1, Duration::from_millis(500))
|
|
285
283
|
.await;
|
|
286
284
|
continue;
|
|
287
285
|
}
|
|
@@ -293,7 +291,7 @@ async fn repros_query_dropped_on_floor() {
|
|
|
293
291
|
}
|
|
294
292
|
) {
|
|
295
293
|
// If we get the timer firing after replay, be done.
|
|
296
|
-
core.complete_execution(
|
|
294
|
+
core.complete_execution(&task.run_id).await;
|
|
297
295
|
}
|
|
298
296
|
|
|
299
297
|
// There should be a query job (really, there should be both... server only sends one?)
|
|
@@ -312,7 +310,6 @@ async fn repros_query_dropped_on_floor() {
|
|
|
312
310
|
};
|
|
313
311
|
// Complete the query
|
|
314
312
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
315
|
-
task_q,
|
|
316
313
|
task.run_id,
|
|
317
314
|
vec![QueryResult {
|
|
318
315
|
query_id: query.query_id.clone(),
|
|
@@ -338,11 +335,11 @@ async fn repros_query_dropped_on_floor() {
|
|
|
338
335
|
#[tokio::test]
|
|
339
336
|
async fn fail_legacy_query() {
|
|
340
337
|
let query_err = "oh no broken";
|
|
341
|
-
let
|
|
342
|
-
let
|
|
343
|
-
let
|
|
338
|
+
let mut starter = init_core_and_create_wf("fail_legacy_query").await;
|
|
339
|
+
let core = starter.get_worker().await;
|
|
340
|
+
let workflow_id = starter.get_task_queue().to_string();
|
|
341
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
344
342
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
345
|
-
&task_q,
|
|
346
343
|
task.run_id.clone(),
|
|
347
344
|
vec![
|
|
348
345
|
StartTimer {
|
|
@@ -362,7 +359,9 @@ async fn fail_legacy_query() {
|
|
|
362
359
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
363
360
|
// Query after timer should have fired and there should be new WFT
|
|
364
361
|
let query_fut = async {
|
|
365
|
-
|
|
362
|
+
starter
|
|
363
|
+
.get_client()
|
|
364
|
+
.await
|
|
366
365
|
.query_workflow_execution(
|
|
367
366
|
workflow_id.to_string(),
|
|
368
367
|
task.run_id.to_string(),
|
|
@@ -380,7 +379,7 @@ async fn fail_legacy_query() {
|
|
|
380
379
|
tokio::time::sleep(Duration::from_millis(400)).await;
|
|
381
380
|
// This poll *should* have the `queries` field populated, but doesn't, seemingly due to
|
|
382
381
|
// a server bug. So, complete the WF task of the first timer firing with empty commands
|
|
383
|
-
let task = core.poll_workflow_activation(
|
|
382
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
384
383
|
assert_matches!(
|
|
385
384
|
task.jobs.as_slice(),
|
|
386
385
|
[WorkflowActivationJob {
|
|
@@ -388,13 +387,12 @@ async fn fail_legacy_query() {
|
|
|
388
387
|
}]
|
|
389
388
|
);
|
|
390
389
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
391
|
-
&task_q,
|
|
392
390
|
task.run_id,
|
|
393
391
|
vec![],
|
|
394
392
|
))
|
|
395
393
|
.await
|
|
396
394
|
.unwrap();
|
|
397
|
-
let task = core.poll_workflow_activation(
|
|
395
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
398
396
|
// Poll again, and we end up getting a `query` field query response
|
|
399
397
|
assert_matches!(
|
|
400
398
|
task.jobs.as_slice(),
|
|
@@ -404,7 +402,6 @@ async fn fail_legacy_query() {
|
|
|
404
402
|
);
|
|
405
403
|
// Fail this task
|
|
406
404
|
core.complete_workflow_activation(WorkflowActivationCompletion::fail(
|
|
407
|
-
&task_q,
|
|
408
405
|
task.run_id,
|
|
409
406
|
Failure {
|
|
410
407
|
message: query_err.to_string(),
|
|
@@ -414,8 +411,8 @@ async fn fail_legacy_query() {
|
|
|
414
411
|
.await
|
|
415
412
|
.unwrap();
|
|
416
413
|
// Finish the workflow
|
|
417
|
-
let task = core.poll_workflow_activation(
|
|
418
|
-
core.complete_execution(&
|
|
414
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
415
|
+
core.complete_execution(&task.run_id).await;
|
|
419
416
|
};
|
|
420
417
|
let (q_resp, _) = tokio::join!(query_fut, workflow_completions_future);
|
|
421
418
|
// Ensure query response is a failure and has the right message
|