@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
|
@@ -3,13 +3,14 @@ use crate::{
|
|
|
3
3
|
job_assert,
|
|
4
4
|
replay::TestHistoryBuilder,
|
|
5
5
|
test_help::{
|
|
6
|
-
|
|
7
|
-
gen_assert_and_fail, gen_assert_and_reply, hist_to_poll_resp,
|
|
6
|
+
build_fake_worker, build_mock_pollers, build_multihist_mock_sg, canned_histories,
|
|
7
|
+
gen_assert_and_fail, gen_assert_and_reply, hist_to_poll_resp, mock_worker, poll_and_reply,
|
|
8
8
|
poll_and_reply_clears_outstanding_evicts, single_hist_mock_sg, FakeWfResponses,
|
|
9
9
|
MockPollCfg, MocksHolder, ResponseType, NO_MORE_WORK_ERROR_MSG, TEST_Q,
|
|
10
10
|
},
|
|
11
|
+
worker::client::mocks::mock_workflow_client,
|
|
11
12
|
workflow::WorkflowCachingPolicy::{self, AfterEveryReply, NonSticky},
|
|
12
|
-
|
|
13
|
+
Worker,
|
|
13
14
|
};
|
|
14
15
|
use rstest::{fixture, rstest};
|
|
15
16
|
use std::{
|
|
@@ -17,50 +18,53 @@ use std::{
|
|
|
17
18
|
sync::atomic::{AtomicU64, AtomicUsize, Ordering},
|
|
18
19
|
time::Duration,
|
|
19
20
|
};
|
|
20
|
-
use
|
|
21
|
+
use temporal_sdk_core_api::Worker as WorkerTrait;
|
|
21
22
|
use temporal_sdk_core_protos::{
|
|
22
23
|
coresdk::{
|
|
23
24
|
activity_result::{self as ar, activity_resolution, ActivityResolution},
|
|
24
25
|
workflow_activation::{
|
|
25
|
-
workflow_activation_job, FireTimer, ResolveActivity,
|
|
26
|
-
WorkflowActivationJob,
|
|
26
|
+
remove_from_cache::EvictionReason, workflow_activation_job, FireTimer, ResolveActivity,
|
|
27
|
+
StartWorkflow, UpdateRandomSeed, WorkflowActivationJob,
|
|
27
28
|
},
|
|
28
29
|
workflow_commands::{
|
|
29
30
|
ActivityCancellationType, CancelTimer, CompleteWorkflowExecution,
|
|
30
31
|
FailWorkflowExecution, RequestCancelActivity, ScheduleActivity,
|
|
31
32
|
},
|
|
33
|
+
workflow_completion::WorkflowActivationCompletion,
|
|
32
34
|
},
|
|
33
35
|
temporal::api::{
|
|
34
36
|
enums::v1::{EventType, WorkflowTaskFailedCause},
|
|
35
37
|
failure::v1::Failure,
|
|
36
|
-
history::v1::{history_event, TimerFiredEventAttributes},
|
|
37
|
-
workflowservice::v1::
|
|
38
|
+
history::v1::{history_event, History, TimerFiredEventAttributes},
|
|
39
|
+
workflowservice::v1::{
|
|
40
|
+
GetWorkflowExecutionHistoryResponse, RespondWorkflowTaskCompletedResponse,
|
|
41
|
+
},
|
|
38
42
|
},
|
|
39
43
|
};
|
|
40
44
|
use temporal_sdk_core_test_utils::{fanout_tasks, start_timer_cmd};
|
|
41
45
|
|
|
42
46
|
#[fixture(hist_batches = &[])]
|
|
43
|
-
fn single_timer_setup(hist_batches: &'static [usize]) ->
|
|
47
|
+
fn single_timer_setup(hist_batches: &'static [usize]) -> Worker {
|
|
44
48
|
let wfid = "fake_wf_id";
|
|
45
49
|
|
|
46
50
|
let t = canned_histories::single_timer("1");
|
|
47
|
-
|
|
51
|
+
build_fake_worker(wfid, t, hist_batches)
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
#[fixture(hist_batches = &[])]
|
|
51
|
-
fn single_activity_setup(hist_batches: &'static [usize]) ->
|
|
55
|
+
fn single_activity_setup(hist_batches: &'static [usize]) -> Worker {
|
|
52
56
|
let wfid = "fake_wf_id";
|
|
53
57
|
|
|
54
58
|
let t = canned_histories::single_activity("fake_activity");
|
|
55
|
-
|
|
59
|
+
build_fake_worker(wfid, t, hist_batches)
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
#[fixture(hist_batches = &[])]
|
|
59
|
-
fn single_activity_failure_setup(hist_batches: &'static [usize]) ->
|
|
63
|
+
fn single_activity_failure_setup(hist_batches: &'static [usize]) -> Worker {
|
|
60
64
|
let wfid = "fake_wf_id";
|
|
61
65
|
|
|
62
66
|
let t = canned_histories::single_failed_activity("fake_activity");
|
|
63
|
-
|
|
67
|
+
build_fake_worker(wfid, t, hist_batches)
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
#[rstest]
|
|
@@ -69,9 +73,9 @@ fn single_activity_failure_setup(hist_batches: &'static [usize]) -> CoreSDK {
|
|
|
69
73
|
#[case::incremental_evict(single_timer_setup(&[1, 2]), AfterEveryReply)]
|
|
70
74
|
#[case::replay_evict(single_timer_setup(&[2, 2]), AfterEveryReply)]
|
|
71
75
|
#[tokio::test]
|
|
72
|
-
async fn single_timer(#[case]
|
|
76
|
+
async fn single_timer(#[case] worker: Worker, #[case] evict: WorkflowCachingPolicy) {
|
|
73
77
|
poll_and_reply(
|
|
74
|
-
&
|
|
78
|
+
&worker,
|
|
75
79
|
evict,
|
|
76
80
|
&[
|
|
77
81
|
gen_assert_and_reply(
|
|
@@ -87,16 +91,16 @@ async fn single_timer(#[case] core: CoreSDK, #[case] evict: WorkflowCachingPolic
|
|
|
87
91
|
.await;
|
|
88
92
|
}
|
|
89
93
|
|
|
90
|
-
#[rstest(
|
|
94
|
+
#[rstest(worker,
|
|
91
95
|
case::incremental(single_activity_setup(&[1, 2])),
|
|
92
96
|
case::incremental_activity_failure(single_activity_failure_setup(&[1, 2])),
|
|
93
97
|
case::replay(single_activity_setup(&[2])),
|
|
94
98
|
case::replay_activity_failure(single_activity_failure_setup(&[2]))
|
|
95
99
|
)]
|
|
96
100
|
#[tokio::test]
|
|
97
|
-
async fn single_activity_completion(
|
|
101
|
+
async fn single_activity_completion(worker: Worker) {
|
|
98
102
|
poll_and_reply(
|
|
99
|
-
&
|
|
103
|
+
&worker,
|
|
100
104
|
NonSticky,
|
|
101
105
|
&[
|
|
102
106
|
gen_assert_and_reply(
|
|
@@ -127,7 +131,7 @@ async fn parallel_timer_test_across_wf_bridge(hist_batches: &'static [usize]) {
|
|
|
127
131
|
timer_1_id.to_string().as_str(),
|
|
128
132
|
timer_2_id.to_string().as_str(),
|
|
129
133
|
);
|
|
130
|
-
let core =
|
|
134
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
131
135
|
|
|
132
136
|
poll_and_reply(
|
|
133
137
|
&core,
|
|
@@ -179,7 +183,7 @@ async fn timer_cancel(hist_batches: &'static [usize]) {
|
|
|
179
183
|
timer_id.to_string().as_str(),
|
|
180
184
|
cancel_timer_id.to_string().as_str(),
|
|
181
185
|
);
|
|
182
|
-
let core =
|
|
186
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
183
187
|
|
|
184
188
|
poll_and_reply(
|
|
185
189
|
&core,
|
|
@@ -216,7 +220,7 @@ async fn scheduled_activity_cancellation_try_cancel(hist_batches: &'static [usiz
|
|
|
216
220
|
let signal_id = "signal";
|
|
217
221
|
|
|
218
222
|
let t = canned_histories::cancel_scheduled_activity(activity_id, signal_id);
|
|
219
|
-
let core =
|
|
223
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
220
224
|
|
|
221
225
|
poll_and_reply(
|
|
222
226
|
&core,
|
|
@@ -254,7 +258,7 @@ async fn scheduled_activity_timeout(hist_batches: &'static [usize]) {
|
|
|
254
258
|
let activity_id = "fake_activity";
|
|
255
259
|
|
|
256
260
|
let t = canned_histories::scheduled_activity_timeout(activity_id);
|
|
257
|
-
let core =
|
|
261
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
258
262
|
poll_and_reply(
|
|
259
263
|
&core,
|
|
260
264
|
NonSticky,
|
|
@@ -306,7 +310,7 @@ async fn started_activity_timeout(hist_batches: &'static [usize]) {
|
|
|
306
310
|
let activity_seq = 1;
|
|
307
311
|
|
|
308
312
|
let t = canned_histories::started_activity_timeout(activity_seq.to_string().as_str());
|
|
309
|
-
let core =
|
|
313
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
310
314
|
|
|
311
315
|
poll_and_reply(
|
|
312
316
|
&core,
|
|
@@ -361,7 +365,7 @@ async fn cancelled_activity_timeout(hist_batches: &'static [usize]) {
|
|
|
361
365
|
let signal_id = "signal";
|
|
362
366
|
|
|
363
367
|
let t = canned_histories::scheduled_cancelled_activity_timeout(activity_id, signal_id);
|
|
364
|
-
let core =
|
|
368
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
365
369
|
|
|
366
370
|
poll_and_reply(
|
|
367
371
|
&core,
|
|
@@ -408,7 +412,7 @@ async fn scheduled_activity_cancellation_abandon(hist_batches: &'static [usize])
|
|
|
408
412
|
activity_id.to_string().as_str(),
|
|
409
413
|
signal_id,
|
|
410
414
|
);
|
|
411
|
-
let core =
|
|
415
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
412
416
|
|
|
413
417
|
verify_activity_cancellation(&core, activity_id, ActivityCancellationType::Abandon).await;
|
|
414
418
|
}
|
|
@@ -424,7 +428,7 @@ async fn started_activity_cancellation_abandon(hist_batches: &'static [usize]) {
|
|
|
424
428
|
activity_id.to_string().as_str(),
|
|
425
429
|
signal_id,
|
|
426
430
|
);
|
|
427
|
-
let core =
|
|
431
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
428
432
|
|
|
429
433
|
verify_activity_cancellation(&core, activity_id, ActivityCancellationType::Abandon).await;
|
|
430
434
|
}
|
|
@@ -440,7 +444,7 @@ async fn scheduled_activity_cancellation_try_cancel_task_canceled(hist_batches:
|
|
|
440
444
|
activity_id.to_string().as_str(),
|
|
441
445
|
signal_id,
|
|
442
446
|
);
|
|
443
|
-
let core =
|
|
447
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
444
448
|
|
|
445
449
|
verify_activity_cancellation(&core, activity_id, ActivityCancellationType::TryCancel).await;
|
|
446
450
|
}
|
|
@@ -456,19 +460,19 @@ async fn started_activity_cancellation_try_cancel_task_canceled(hist_batches: &'
|
|
|
456
460
|
activity_id.to_string().as_str(),
|
|
457
461
|
signal_id,
|
|
458
462
|
);
|
|
459
|
-
let core =
|
|
463
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
460
464
|
|
|
461
465
|
verify_activity_cancellation(&core, activity_id, ActivityCancellationType::TryCancel).await;
|
|
462
466
|
}
|
|
463
467
|
|
|
464
468
|
/// Verification for try cancel & abandon histories
|
|
465
469
|
async fn verify_activity_cancellation(
|
|
466
|
-
|
|
470
|
+
worker: &Worker,
|
|
467
471
|
activity_seq: u32,
|
|
468
472
|
cancel_type: ActivityCancellationType,
|
|
469
473
|
) {
|
|
470
474
|
poll_and_reply(
|
|
471
|
-
|
|
475
|
+
worker,
|
|
472
476
|
NonSticky,
|
|
473
477
|
&[
|
|
474
478
|
gen_assert_and_reply(
|
|
@@ -513,7 +517,7 @@ async fn scheduled_activity_cancellation_wait_for_cancellation(hist_batches: &'s
|
|
|
513
517
|
activity_id.to_string().as_str(),
|
|
514
518
|
signal_id,
|
|
515
519
|
);
|
|
516
|
-
let core =
|
|
520
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
517
521
|
|
|
518
522
|
verify_activity_cancellation_wait_for_cancellation(activity_id, &core).await;
|
|
519
523
|
}
|
|
@@ -529,14 +533,14 @@ async fn started_activity_cancellation_wait_for_cancellation(hist_batches: &'sta
|
|
|
529
533
|
activity_id.to_string().as_str(),
|
|
530
534
|
signal_id,
|
|
531
535
|
);
|
|
532
|
-
let core =
|
|
536
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
533
537
|
|
|
534
538
|
verify_activity_cancellation_wait_for_cancellation(activity_id, &core).await;
|
|
535
539
|
}
|
|
536
540
|
|
|
537
|
-
async fn verify_activity_cancellation_wait_for_cancellation(activity_id: u32,
|
|
541
|
+
async fn verify_activity_cancellation_wait_for_cancellation(activity_id: u32, worker: &Worker) {
|
|
538
542
|
poll_and_reply(
|
|
539
|
-
|
|
543
|
+
worker,
|
|
540
544
|
NonSticky,
|
|
541
545
|
&[
|
|
542
546
|
gen_assert_and_reply(
|
|
@@ -586,7 +590,7 @@ async fn workflow_update_random_seed_on_workflow_reset() {
|
|
|
586
590
|
timer_1_id.to_string().as_str(),
|
|
587
591
|
new_run_id,
|
|
588
592
|
);
|
|
589
|
-
let core =
|
|
593
|
+
let core = build_fake_worker(wfid, t, &[2]);
|
|
590
594
|
|
|
591
595
|
poll_and_reply(
|
|
592
596
|
&core,
|
|
@@ -640,7 +644,7 @@ async fn cancel_timer_before_sent_wf_bridge() {
|
|
|
640
644
|
t.add_full_wf_task();
|
|
641
645
|
t.add_workflow_execution_completed();
|
|
642
646
|
|
|
643
|
-
let core =
|
|
647
|
+
let core = build_fake_worker(wfid, t, &[1]);
|
|
644
648
|
|
|
645
649
|
poll_and_reply(
|
|
646
650
|
&core,
|
|
@@ -678,12 +682,11 @@ async fn complete_activation_with_failure(
|
|
|
678
682
|
wf_id: wfid.to_string(),
|
|
679
683
|
hist,
|
|
680
684
|
response_batches: batches.iter().map(Into::into).collect(),
|
|
681
|
-
task_q: TEST_Q.to_owned(),
|
|
682
685
|
}],
|
|
683
686
|
true,
|
|
684
687
|
Some(1),
|
|
685
688
|
);
|
|
686
|
-
let core =
|
|
689
|
+
let core = mock_worker(mock_sg);
|
|
687
690
|
|
|
688
691
|
poll_and_reply(
|
|
689
692
|
&core,
|
|
@@ -711,7 +714,7 @@ async fn simple_timer_fail_wf_execution(hist_batches: &'static [usize]) {
|
|
|
711
714
|
let timer_id = 1;
|
|
712
715
|
|
|
713
716
|
let t = canned_histories::single_timer(timer_id.to_string().as_str());
|
|
714
|
-
let core =
|
|
717
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
715
718
|
|
|
716
719
|
poll_and_reply(
|
|
717
720
|
&core,
|
|
@@ -742,7 +745,7 @@ async fn two_signals(hist_batches: &'static [usize]) {
|
|
|
742
745
|
let wfid = "fake_wf_id";
|
|
743
746
|
|
|
744
747
|
let t = canned_histories::two_signals("sig1", "sig2");
|
|
745
|
-
let core =
|
|
748
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
746
749
|
|
|
747
750
|
poll_and_reply(
|
|
748
751
|
&core,
|
|
@@ -786,14 +789,13 @@ async fn workflow_failures_only_reported_once() {
|
|
|
786
789
|
wf_id: wfid.to_string(),
|
|
787
790
|
hist,
|
|
788
791
|
response_batches: response_batches.into_iter().map(Into::into).collect(),
|
|
789
|
-
task_q: TEST_Q.to_owned(),
|
|
790
792
|
}],
|
|
791
793
|
true,
|
|
792
794
|
// We should only call the server to say we failed twice (once after each success)
|
|
793
795
|
Some(2),
|
|
794
796
|
);
|
|
795
797
|
let omap = mocks.outstanding_task_map.clone();
|
|
796
|
-
let core =
|
|
798
|
+
let core = mock_worker(mocks);
|
|
797
799
|
|
|
798
800
|
poll_and_reply_clears_outstanding_evicts(
|
|
799
801
|
&core,
|
|
@@ -835,13 +837,11 @@ async fn max_concurrent_wft_respected() {
|
|
|
835
837
|
wf_id: "wf1".to_string(),
|
|
836
838
|
hist: t1,
|
|
837
839
|
response_batches: vec![ResponseType::AllHistory],
|
|
838
|
-
task_q: TEST_Q.to_string(),
|
|
839
840
|
},
|
|
840
841
|
FakeWfResponses {
|
|
841
842
|
wf_id: "wf2".to_string(),
|
|
842
843
|
hist: t2,
|
|
843
844
|
response_batches: vec![ResponseType::AllHistory],
|
|
844
|
-
task_q: TEST_Q.to_string(),
|
|
845
845
|
},
|
|
846
846
|
],
|
|
847
847
|
true,
|
|
@@ -850,30 +850,29 @@ async fn max_concurrent_wft_respected() {
|
|
|
850
850
|
let mut mock = build_mock_pollers(mh);
|
|
851
851
|
// Limit the core to two outstanding workflow tasks, hence we should only see polling
|
|
852
852
|
// happen twice, since we will not actually finish the two workflows
|
|
853
|
-
mock.worker_cfg(
|
|
853
|
+
mock.worker_cfg(|cfg| {
|
|
854
854
|
cfg.max_cached_workflows = 2;
|
|
855
855
|
cfg.max_outstanding_workflow_tasks = 2;
|
|
856
856
|
});
|
|
857
|
-
let core =
|
|
857
|
+
let core = mock_worker(mock);
|
|
858
858
|
|
|
859
859
|
// Poll twice in a row before completing -- we should be at limit
|
|
860
|
-
let r1 = core.poll_workflow_activation(
|
|
860
|
+
let r1 = core.poll_workflow_activation().await.unwrap();
|
|
861
861
|
let r1_run_id = r1.run_id.clone();
|
|
862
|
-
let r2 = core.poll_workflow_activation(
|
|
862
|
+
let r2 = core.poll_workflow_activation().await.unwrap();
|
|
863
863
|
// Now we immediately poll for new work, and complete the r1 activation. The poll must not
|
|
864
864
|
// unblock until the completion goes through.
|
|
865
865
|
let last_finisher = AtomicUsize::new(0);
|
|
866
866
|
let (_, mut r1) = tokio::join! {
|
|
867
867
|
async {
|
|
868
868
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
869
|
-
TEST_Q,
|
|
870
869
|
r1.run_id,
|
|
871
870
|
start_timer_cmd(1, Duration::from_secs(1)))
|
|
872
871
|
).await.unwrap();
|
|
873
872
|
last_finisher.store(1, Ordering::SeqCst);
|
|
874
873
|
},
|
|
875
874
|
async {
|
|
876
|
-
let r = core.poll_workflow_activation(
|
|
875
|
+
let r = core.poll_workflow_activation().await.unwrap();
|
|
877
876
|
last_finisher.store(2, Ordering::SeqCst);
|
|
878
877
|
r
|
|
879
878
|
}
|
|
@@ -884,38 +883,35 @@ async fn max_concurrent_wft_respected() {
|
|
|
884
883
|
// Since we never did anything with r2, all subsequent activations should be for wf1
|
|
885
884
|
for i in 2..=20 {
|
|
886
885
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
887
|
-
TEST_Q,
|
|
888
886
|
r1.run_id,
|
|
889
887
|
start_timer_cmd(i, Duration::from_secs(1)),
|
|
890
888
|
))
|
|
891
889
|
.await
|
|
892
890
|
.unwrap();
|
|
893
|
-
r1 = core.poll_workflow_activation(
|
|
891
|
+
r1 = core.poll_workflow_activation().await.unwrap();
|
|
894
892
|
assert_eq!(r1.run_id, r1_run_id);
|
|
895
893
|
}
|
|
896
894
|
// Finish the tasks so we can shut down
|
|
897
895
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
898
|
-
TEST_Q,
|
|
899
896
|
r1.run_id,
|
|
900
897
|
CompleteWorkflowExecution { result: None }.into(),
|
|
901
898
|
))
|
|
902
899
|
.await
|
|
903
900
|
.unwrap();
|
|
904
901
|
// Evict r2
|
|
905
|
-
core.request_workflow_eviction(
|
|
902
|
+
core.request_workflow_eviction(&r2.run_id);
|
|
906
903
|
// We have to properly complete the outstanding task (or the mock will be confused why a task
|
|
907
904
|
// failure was reported)
|
|
908
905
|
let _ = core
|
|
909
906
|
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
910
|
-
TEST_Q,
|
|
911
907
|
r2.run_id,
|
|
912
908
|
start_timer_cmd(1, Duration::from_secs(1)),
|
|
913
909
|
))
|
|
914
910
|
.await;
|
|
915
911
|
// Get and complete eviction
|
|
916
|
-
let r2 = core.poll_workflow_activation(
|
|
912
|
+
let r2 = core.poll_workflow_activation().await.unwrap();
|
|
917
913
|
let _ = core
|
|
918
|
-
.complete_workflow_activation(WorkflowActivationCompletion::empty(
|
|
914
|
+
.complete_workflow_activation(WorkflowActivationCompletion::empty(r2.run_id))
|
|
919
915
|
.await;
|
|
920
916
|
core.shutdown().await;
|
|
921
917
|
}
|
|
@@ -925,7 +921,7 @@ async fn max_concurrent_wft_respected() {
|
|
|
925
921
|
async fn activity_not_canceled_on_replay_repro(hist_batches: &'static [usize]) {
|
|
926
922
|
let wfid = "fake_wf_id";
|
|
927
923
|
let t = canned_histories::unsent_at_cancel_repro();
|
|
928
|
-
let core =
|
|
924
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
929
925
|
let activity_id = 1;
|
|
930
926
|
|
|
931
927
|
poll_and_reply(
|
|
@@ -971,7 +967,7 @@ async fn activity_not_canceled_on_replay_repro(hist_batches: &'static [usize]) {
|
|
|
971
967
|
async fn activity_not_canceled_when_also_completed_repro(hist_batches: &'static [usize]) {
|
|
972
968
|
let wfid = "fake_wf_id";
|
|
973
969
|
let t = canned_histories::cancel_not_sent_when_also_complete_repro();
|
|
974
|
-
let core =
|
|
970
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
975
971
|
let activity_id = 1;
|
|
976
972
|
|
|
977
973
|
poll_and_reply(
|
|
@@ -1020,45 +1016,40 @@ async fn lots_of_workflows() {
|
|
|
1020
1016
|
wf_id,
|
|
1021
1017
|
hist,
|
|
1022
1018
|
response_batches: vec![1.into(), 2.into()],
|
|
1023
|
-
task_q: TEST_Q.to_owned(),
|
|
1024
1019
|
}
|
|
1025
1020
|
});
|
|
1026
1021
|
let mock = build_multihist_mock_sg(hists, false, None);
|
|
1027
|
-
let
|
|
1022
|
+
let worker = &mock_worker(mock);
|
|
1028
1023
|
|
|
1029
1024
|
fanout_tasks(5, |_| async move {
|
|
1030
|
-
while let Ok(wft) =
|
|
1025
|
+
while let Ok(wft) = worker.poll_workflow_activation().await {
|
|
1031
1026
|
let job = &wft.jobs[0];
|
|
1032
1027
|
let reply = match job.variant {
|
|
1033
1028
|
Some(workflow_activation_job::Variant::StartWorkflow(_)) => {
|
|
1034
1029
|
start_timer_cmd(1, Duration::from_secs(1))
|
|
1035
1030
|
}
|
|
1036
1031
|
Some(workflow_activation_job::Variant::RemoveFromCache(_)) => {
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1032
|
+
worker
|
|
1033
|
+
.complete_workflow_activation(WorkflowActivationCompletion::empty(
|
|
1034
|
+
wft.run_id,
|
|
1035
|
+
))
|
|
1036
|
+
.await
|
|
1037
|
+
.unwrap();
|
|
1042
1038
|
continue;
|
|
1043
1039
|
}
|
|
1044
1040
|
_ => CompleteWorkflowExecution { result: None }.into(),
|
|
1045
1041
|
};
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1042
|
+
worker
|
|
1043
|
+
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1044
|
+
wft.run_id, reply,
|
|
1045
|
+
))
|
|
1046
|
+
.await
|
|
1047
|
+
.unwrap();
|
|
1051
1048
|
}
|
|
1052
1049
|
})
|
|
1053
1050
|
.await;
|
|
1054
|
-
assert_eq!(
|
|
1055
|
-
|
|
1056
|
-
.get(TEST_Q)
|
|
1057
|
-
.unwrap()
|
|
1058
|
-
.outstanding_workflow_tasks(),
|
|
1059
|
-
0
|
|
1060
|
-
);
|
|
1061
|
-
core.shutdown().await;
|
|
1051
|
+
assert_eq!(worker.outstanding_workflow_tasks(), 0);
|
|
1052
|
+
worker.shutdown().await;
|
|
1062
1053
|
}
|
|
1063
1054
|
|
|
1064
1055
|
#[rstest(hist_batches, case::incremental(&[1, 2]), case::replay(&[2]))]
|
|
@@ -1066,7 +1057,7 @@ async fn lots_of_workflows() {
|
|
|
1066
1057
|
async fn wft_timeout_repro(hist_batches: &'static [usize]) {
|
|
1067
1058
|
let wfid = "fake_wf_id";
|
|
1068
1059
|
let t = canned_histories::wft_timeout_repro();
|
|
1069
|
-
let core =
|
|
1060
|
+
let core = build_fake_worker(wfid, t, hist_batches);
|
|
1070
1061
|
let activity_id = 1;
|
|
1071
1062
|
|
|
1072
1063
|
poll_and_reply(
|
|
@@ -1105,23 +1096,22 @@ async fn wft_timeout_repro(hist_batches: &'static [usize]) {
|
|
|
1105
1096
|
async fn complete_after_eviction() {
|
|
1106
1097
|
let wfid = "fake_wf_id";
|
|
1107
1098
|
let t = canned_histories::single_timer("1");
|
|
1108
|
-
let mut mock =
|
|
1099
|
+
let mut mock = mock_workflow_client();
|
|
1109
1100
|
mock.expect_complete_workflow_task().times(0);
|
|
1110
1101
|
let mock = single_hist_mock_sg(wfid, t, &[2], mock, true);
|
|
1111
|
-
let core =
|
|
1102
|
+
let core = mock_worker(mock);
|
|
1112
1103
|
|
|
1113
|
-
let activation = core.poll_workflow_activation(
|
|
1104
|
+
let activation = core.poll_workflow_activation().await.unwrap();
|
|
1114
1105
|
// We just got start workflow, immediately evict
|
|
1115
|
-
core.request_workflow_eviction(
|
|
1106
|
+
core.request_workflow_eviction(&activation.run_id);
|
|
1116
1107
|
// Original task must be completed before we get the eviction
|
|
1117
1108
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1118
|
-
TEST_Q,
|
|
1119
1109
|
activation.run_id,
|
|
1120
1110
|
start_timer_cmd(1, Duration::from_secs(1)),
|
|
1121
1111
|
))
|
|
1122
1112
|
.await
|
|
1123
1113
|
.unwrap();
|
|
1124
|
-
let eviction_activation = core.poll_workflow_activation(
|
|
1114
|
+
let eviction_activation = core.poll_workflow_activation().await.unwrap();
|
|
1125
1115
|
assert_matches!(
|
|
1126
1116
|
eviction_activation.jobs.as_slice(),
|
|
1127
1117
|
[
|
|
@@ -1135,7 +1125,6 @@ async fn complete_after_eviction() {
|
|
|
1135
1125
|
);
|
|
1136
1126
|
// Complete the activation containing the eviction, the way we normally would have
|
|
1137
1127
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
1138
|
-
TEST_Q,
|
|
1139
1128
|
eviction_activation.run_id,
|
|
1140
1129
|
vec![CompleteWorkflowExecution { result: None }.into()],
|
|
1141
1130
|
))
|
|
@@ -1150,19 +1139,18 @@ async fn sends_appropriate_sticky_task_queue_responses() {
|
|
|
1150
1139
|
// include the information that tells the server to enqueue the next task on a sticky queue.
|
|
1151
1140
|
let wfid = "fake_wf_id";
|
|
1152
1141
|
let t = canned_histories::single_timer("1");
|
|
1153
|
-
let mut mock =
|
|
1142
|
+
let mut mock = mock_workflow_client();
|
|
1154
1143
|
mock.expect_complete_workflow_task()
|
|
1155
1144
|
.withf(|comp| comp.sticky_attributes.is_some())
|
|
1156
1145
|
.times(1)
|
|
1157
1146
|
.returning(|_| Ok(Default::default()));
|
|
1158
1147
|
mock.expect_complete_workflow_task().times(0);
|
|
1159
1148
|
let mut mock = single_hist_mock_sg(wfid, t, &[1], mock, false);
|
|
1160
|
-
mock.worker_cfg(
|
|
1161
|
-
let core =
|
|
1149
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
|
|
1150
|
+
let core = mock_worker(mock);
|
|
1162
1151
|
|
|
1163
|
-
let activation = core.poll_workflow_activation(
|
|
1152
|
+
let activation = core.poll_workflow_activation().await.unwrap();
|
|
1164
1153
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1165
|
-
TEST_Q,
|
|
1166
1154
|
activation.run_id,
|
|
1167
1155
|
start_timer_cmd(1, Duration::from_secs(1)),
|
|
1168
1156
|
))
|
|
@@ -1175,19 +1163,18 @@ async fn sends_appropriate_sticky_task_queue_responses() {
|
|
|
1175
1163
|
async fn new_server_work_while_eviction_outstanding_doesnt_overwrite_activation() {
|
|
1176
1164
|
let wfid = "fake_wf_id";
|
|
1177
1165
|
let t = canned_histories::single_timer("1");
|
|
1178
|
-
let mock = single_hist_mock_sg(wfid, t, &[1, 2],
|
|
1179
|
-
let core =
|
|
1166
|
+
let mock = single_hist_mock_sg(wfid, t, &[1, 2], mock_workflow_client(), false);
|
|
1167
|
+
let core = mock_worker(mock);
|
|
1180
1168
|
|
|
1181
1169
|
// Poll for and complete first workflow task
|
|
1182
|
-
let activation = core.poll_workflow_activation(
|
|
1170
|
+
let activation = core.poll_workflow_activation().await.unwrap();
|
|
1183
1171
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1184
|
-
TEST_Q,
|
|
1185
1172
|
activation.run_id,
|
|
1186
1173
|
start_timer_cmd(1, Duration::from_secs(1)),
|
|
1187
1174
|
))
|
|
1188
1175
|
.await
|
|
1189
1176
|
.unwrap();
|
|
1190
|
-
let eviction_activation = core.poll_workflow_activation(
|
|
1177
|
+
let eviction_activation = core.poll_workflow_activation().await.unwrap();
|
|
1191
1178
|
assert_matches!(
|
|
1192
1179
|
eviction_activation.jobs.as_slice(),
|
|
1193
1180
|
[WorkflowActivationJob {
|
|
@@ -1196,7 +1183,7 @@ async fn new_server_work_while_eviction_outstanding_doesnt_overwrite_activation(
|
|
|
1196
1183
|
);
|
|
1197
1184
|
// Poll again. We should not overwrite the eviction with the new work from the server to fire
|
|
1198
1185
|
// the timer, so polling will try again, and run into the mock being out of responses.
|
|
1199
|
-
let act = core.poll_workflow_activation(
|
|
1186
|
+
let act = core.poll_workflow_activation().await;
|
|
1200
1187
|
assert_matches!(act, Err(PollWfError::TonicError(err))
|
|
1201
1188
|
if err.message() == NO_MORE_WORK_ERROR_MSG);
|
|
1202
1189
|
core.shutdown().await;
|
|
@@ -1237,22 +1224,21 @@ async fn buffered_work_drained_on_shutdown() {
|
|
|
1237
1224
|
))
|
|
1238
1225
|
.take(50),
|
|
1239
1226
|
);
|
|
1240
|
-
let mut mock =
|
|
1227
|
+
let mut mock = mock_workflow_client();
|
|
1241
1228
|
mock.expect_complete_workflow_task()
|
|
1242
1229
|
.returning(|_| Ok(RespondWorkflowTaskCompletedResponse::default()));
|
|
1243
|
-
let mut mock = MocksHolder::
|
|
1230
|
+
let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
|
|
1244
1231
|
// Cache on to avoid being super repetitive
|
|
1245
|
-
mock.worker_cfg(
|
|
1246
|
-
let core = &
|
|
1232
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
|
|
1233
|
+
let core = &mock_worker(mock);
|
|
1247
1234
|
|
|
1248
1235
|
// Poll for first WFT
|
|
1249
|
-
let act1 = core.poll_workflow_activation(
|
|
1236
|
+
let act1 = core.poll_workflow_activation().await.unwrap();
|
|
1250
1237
|
let poll_fut = async move {
|
|
1251
1238
|
// Now poll again, which will start spinning, and buffer the next WFT with timer fired in it
|
|
1252
1239
|
// - it won't stop spinning until the first task is complete
|
|
1253
|
-
let t = core.poll_workflow_activation(
|
|
1240
|
+
let t = core.poll_workflow_activation().await.unwrap();
|
|
1254
1241
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
1255
|
-
TEST_Q,
|
|
1256
1242
|
t.run_id,
|
|
1257
1243
|
vec![CompleteWorkflowExecution { result: None }.into()],
|
|
1258
1244
|
))
|
|
@@ -1261,7 +1247,6 @@ async fn buffered_work_drained_on_shutdown() {
|
|
|
1261
1247
|
};
|
|
1262
1248
|
let complete_first = async move {
|
|
1263
1249
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1264
|
-
TEST_Q,
|
|
1265
1250
|
act1.run_id,
|
|
1266
1251
|
start_timer_cmd(1, Duration::from_secs(1)),
|
|
1267
1252
|
))
|
|
@@ -1279,7 +1264,7 @@ async fn buffered_work_drained_on_shutdown() {
|
|
|
1279
1264
|
async fn buffering_tasks_doesnt_count_toward_outstanding_max() {
|
|
1280
1265
|
let wfid = "fake_wf_id";
|
|
1281
1266
|
let t = canned_histories::single_timer("1");
|
|
1282
|
-
let mock =
|
|
1267
|
+
let mock = mock_workflow_client();
|
|
1283
1268
|
let mut tasks = VecDeque::new();
|
|
1284
1269
|
// A way bigger task list than allowed outstanding tasks
|
|
1285
1270
|
tasks.extend(
|
|
@@ -1291,18 +1276,18 @@ async fn buffering_tasks_doesnt_count_toward_outstanding_max() {
|
|
|
1291
1276
|
))
|
|
1292
1277
|
.take(20),
|
|
1293
1278
|
);
|
|
1294
|
-
let mut mock = MocksHolder::
|
|
1295
|
-
mock.worker_cfg(
|
|
1279
|
+
let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
|
|
1280
|
+
mock.worker_cfg(|wc| {
|
|
1296
1281
|
wc.max_cached_workflows = 10;
|
|
1297
1282
|
wc.max_outstanding_workflow_tasks = 5;
|
|
1298
1283
|
});
|
|
1299
|
-
let core =
|
|
1284
|
+
let core = mock_worker(mock);
|
|
1300
1285
|
// Poll for first WFT
|
|
1301
|
-
core.poll_workflow_activation(
|
|
1286
|
+
core.poll_workflow_activation().await.unwrap();
|
|
1302
1287
|
// This will error out when the mock runs out of responses. Otherwise it would hang when we
|
|
1303
1288
|
// hit the max
|
|
1304
1289
|
assert_matches!(
|
|
1305
|
-
core.poll_workflow_activation(
|
|
1290
|
+
core.poll_workflow_activation().await.unwrap_err(),
|
|
1306
1291
|
PollWfError::TonicError(_)
|
|
1307
1292
|
);
|
|
1308
1293
|
}
|
|
@@ -1315,21 +1300,20 @@ async fn fail_wft_then_recover() {
|
|
|
1315
1300
|
t,
|
|
1316
1301
|
// We need to deliver all of history twice because of eviction
|
|
1317
1302
|
[ResponseType::AllHistory, ResponseType::AllHistory],
|
|
1318
|
-
|
|
1303
|
+
mock_workflow_client(),
|
|
1319
1304
|
);
|
|
1320
1305
|
mh.num_expected_fails = Some(1);
|
|
1321
1306
|
mh.expect_fail_wft_matcher =
|
|
1322
1307
|
Box::new(|_, cause, _| matches!(cause, WorkflowTaskFailedCause::NonDeterministicError));
|
|
1323
1308
|
let mut mock = build_mock_pollers(mh);
|
|
1324
|
-
mock.worker_cfg(
|
|
1309
|
+
mock.worker_cfg(|wc| {
|
|
1325
1310
|
wc.max_cached_workflows = 2;
|
|
1326
1311
|
});
|
|
1327
|
-
let core =
|
|
1312
|
+
let core = mock_worker(mock);
|
|
1328
1313
|
|
|
1329
|
-
let act = core.poll_workflow_activation(
|
|
1314
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
1330
1315
|
// Start an activity instead of a timer, triggering nondeterminism error
|
|
1331
1316
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
1332
|
-
TEST_Q,
|
|
1333
1317
|
act.run_id.clone(),
|
|
1334
1318
|
vec![ScheduleActivity {
|
|
1335
1319
|
activity_id: "fake_activity".to_string(),
|
|
@@ -1340,7 +1324,7 @@ async fn fail_wft_then_recover() {
|
|
|
1340
1324
|
.await
|
|
1341
1325
|
.unwrap();
|
|
1342
1326
|
// We must handle an eviction now
|
|
1343
|
-
let evict_act = core.poll_workflow_activation(
|
|
1327
|
+
let evict_act = core.poll_workflow_activation().await.unwrap();
|
|
1344
1328
|
assert_eq!(evict_act.run_id, act.run_id);
|
|
1345
1329
|
assert_matches!(
|
|
1346
1330
|
evict_act.jobs.as_slice(),
|
|
@@ -1348,23 +1332,19 @@ async fn fail_wft_then_recover() {
|
|
|
1348
1332
|
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
|
1349
1333
|
}]
|
|
1350
1334
|
);
|
|
1351
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::empty(
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
))
|
|
1355
|
-
.await
|
|
1356
|
-
.unwrap();
|
|
1335
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(evict_act.run_id))
|
|
1336
|
+
.await
|
|
1337
|
+
.unwrap();
|
|
1357
1338
|
|
|
1358
1339
|
// Workflow starting over, this time issue the right command
|
|
1359
|
-
let act = core.poll_workflow_activation(
|
|
1340
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
1360
1341
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
1361
|
-
TEST_Q,
|
|
1362
1342
|
act.run_id,
|
|
1363
1343
|
vec![start_timer_cmd(1, Duration::from_secs(1))],
|
|
1364
1344
|
))
|
|
1365
1345
|
.await
|
|
1366
1346
|
.unwrap();
|
|
1367
|
-
let act = core.poll_workflow_activation(
|
|
1347
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
1368
1348
|
assert_matches!(
|
|
1369
1349
|
act.jobs.as_slice(),
|
|
1370
1350
|
[WorkflowActivationJob {
|
|
@@ -1372,7 +1352,6 @@ async fn fail_wft_then_recover() {
|
|
|
1372
1352
|
},]
|
|
1373
1353
|
);
|
|
1374
1354
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
1375
|
-
TEST_Q,
|
|
1376
1355
|
act.run_id,
|
|
1377
1356
|
vec![CompleteWorkflowExecution { result: None }.into()],
|
|
1378
1357
|
))
|
|
@@ -1390,15 +1369,19 @@ async fn poll_response_triggers_wf_error() {
|
|
|
1390
1369
|
t.add_full_wf_task();
|
|
1391
1370
|
t.add_workflow_execution_completed();
|
|
1392
1371
|
|
|
1393
|
-
let mut mh =
|
|
1394
|
-
|
|
1372
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
1373
|
+
"fake_wf_id",
|
|
1374
|
+
t,
|
|
1375
|
+
[ResponseType::AllHistory],
|
|
1376
|
+
mock_workflow_client(),
|
|
1377
|
+
);
|
|
1395
1378
|
// Since applying the poll response immediately generates an error core will start polling again
|
|
1396
1379
|
// Rather than panic on bad expectation we want to return the magic "no more work" error
|
|
1397
1380
|
mh.enforce_correct_number_of_polls = false;
|
|
1398
1381
|
let mock = build_mock_pollers(mh);
|
|
1399
|
-
let core =
|
|
1382
|
+
let core = mock_worker(mock);
|
|
1400
1383
|
// Poll for first WFT, which is immediately an eviction
|
|
1401
|
-
let act = core.poll_workflow_activation(
|
|
1384
|
+
let act = core.poll_workflow_activation().await;
|
|
1402
1385
|
assert_matches!(act, Err(PollWfError::TonicError(err))
|
|
1403
1386
|
if err.message() == NO_MORE_WORK_ERROR_MSG);
|
|
1404
1387
|
}
|
|
@@ -1419,47 +1402,46 @@ async fn lang_slower_than_wft_timeouts() {
|
|
|
1419
1402
|
hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string()),
|
|
1420
1403
|
hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string()),
|
|
1421
1404
|
];
|
|
1422
|
-
let mut mock =
|
|
1405
|
+
let mut mock = mock_workflow_client();
|
|
1423
1406
|
mock.expect_complete_workflow_task()
|
|
1424
1407
|
.times(1)
|
|
1425
1408
|
.returning(|_| Err(tonic::Status::not_found("Workflow task not found.")));
|
|
1426
1409
|
mock.expect_complete_workflow_task()
|
|
1427
1410
|
.times(1)
|
|
1428
1411
|
.returning(|_| Ok(Default::default()));
|
|
1429
|
-
let mut mock = MocksHolder::
|
|
1430
|
-
mock.worker_cfg(
|
|
1412
|
+
let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
|
|
1413
|
+
mock.worker_cfg(|wc| {
|
|
1431
1414
|
wc.max_cached_workflows = 2;
|
|
1432
1415
|
});
|
|
1433
|
-
let core =
|
|
1416
|
+
let core = mock_worker(mock);
|
|
1434
1417
|
|
|
1435
|
-
let wf_task = core.poll_workflow_activation(
|
|
1436
|
-
let poll_until_no_work = core.poll_workflow_activation(
|
|
1418
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
1419
|
+
let poll_until_no_work = core.poll_workflow_activation().await;
|
|
1437
1420
|
assert_matches!(poll_until_no_work, Err(PollWfError::TonicError(err))
|
|
1438
1421
|
if err.message() == NO_MORE_WORK_ERROR_MSG);
|
|
1439
1422
|
// This completion runs into a workflow task not found error, since it's completing a stale
|
|
1440
1423
|
// task.
|
|
1441
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::empty(
|
|
1424
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
|
|
1442
1425
|
.await
|
|
1443
1426
|
.unwrap();
|
|
1444
1427
|
// Now we should get an eviction
|
|
1445
|
-
let wf_task = core.poll_workflow_activation(
|
|
1428
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
1446
1429
|
assert_matches!(
|
|
1447
1430
|
wf_task.jobs.as_slice(),
|
|
1448
1431
|
[WorkflowActivationJob {
|
|
1449
1432
|
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
|
1450
1433
|
}]
|
|
1451
1434
|
);
|
|
1452
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::empty(
|
|
1435
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
|
|
1453
1436
|
.await
|
|
1454
1437
|
.unwrap();
|
|
1455
1438
|
// The last WFT buffered should be applied now
|
|
1456
|
-
let start_again = core.poll_workflow_activation(
|
|
1439
|
+
let start_again = core.poll_workflow_activation().await.unwrap();
|
|
1457
1440
|
assert_matches!(
|
|
1458
1441
|
start_again.jobs[0].variant,
|
|
1459
1442
|
Some(workflow_activation_job::Variant::StartWorkflow(_))
|
|
1460
1443
|
);
|
|
1461
1444
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
1462
|
-
TEST_Q,
|
|
1463
1445
|
start_again.run_id,
|
|
1464
1446
|
vec![CompleteWorkflowExecution { result: None }.into()],
|
|
1465
1447
|
))
|
|
@@ -1479,14 +1461,13 @@ async fn tries_cancel_of_completed_activity() {
|
|
|
1479
1461
|
t.add_activity_task_completed(scheduled_event_id, started_event_id, Default::default());
|
|
1480
1462
|
t.add_workflow_task_scheduled_and_started();
|
|
1481
1463
|
|
|
1482
|
-
let mock =
|
|
1464
|
+
let mock = mock_workflow_client();
|
|
1483
1465
|
let mut mock = single_hist_mock_sg("fake_wf_id", t, &[1, 2], mock, true);
|
|
1484
|
-
mock.worker_cfg(
|
|
1485
|
-
let core =
|
|
1466
|
+
mock.worker_cfg(|cfg| cfg.max_cached_workflows = 1);
|
|
1467
|
+
let core = mock_worker(mock);
|
|
1486
1468
|
|
|
1487
|
-
let activation = core.poll_workflow_activation(
|
|
1469
|
+
let activation = core.poll_workflow_activation().await.unwrap();
|
|
1488
1470
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1489
|
-
TEST_Q,
|
|
1490
1471
|
activation.run_id,
|
|
1491
1472
|
ScheduleActivity {
|
|
1492
1473
|
seq: 1,
|
|
@@ -1497,7 +1478,7 @@ async fn tries_cancel_of_completed_activity() {
|
|
|
1497
1478
|
))
|
|
1498
1479
|
.await
|
|
1499
1480
|
.unwrap();
|
|
1500
|
-
let activation = core.poll_workflow_activation(
|
|
1481
|
+
let activation = core.poll_workflow_activation().await.unwrap();
|
|
1501
1482
|
assert_matches!(
|
|
1502
1483
|
activation.jobs.as_slice(),
|
|
1503
1484
|
[
|
|
@@ -1510,7 +1491,6 @@ async fn tries_cancel_of_completed_activity() {
|
|
|
1510
1491
|
]
|
|
1511
1492
|
);
|
|
1512
1493
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
1513
|
-
TEST_Q,
|
|
1514
1494
|
activation.run_id,
|
|
1515
1495
|
vec![
|
|
1516
1496
|
RequestCancelActivity { seq: 1 }.into(),
|
|
@@ -1529,29 +1509,29 @@ async fn failing_wft_doesnt_eat_permit_forever() {
|
|
|
1529
1509
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
1530
1510
|
t.add_workflow_task_scheduled_and_started();
|
|
1531
1511
|
|
|
1532
|
-
let mock =
|
|
1512
|
+
let mock = mock_workflow_client();
|
|
1533
1513
|
let mut mock = single_hist_mock_sg("fake_wf_id", t, [1, 1, 1], mock, true);
|
|
1534
|
-
mock.worker_cfg(
|
|
1514
|
+
mock.worker_cfg(|cfg| {
|
|
1535
1515
|
cfg.max_cached_workflows = 2;
|
|
1536
1516
|
cfg.max_outstanding_workflow_tasks = 2;
|
|
1537
1517
|
});
|
|
1538
1518
|
let outstanding_mock_tasks = mock.outstanding_task_map.clone();
|
|
1539
|
-
let
|
|
1519
|
+
let worker = mock_worker(mock);
|
|
1540
1520
|
|
|
1541
1521
|
let mut run_id = "".to_string();
|
|
1542
1522
|
// Fail twice, verifying a permit is eaten. We cannot fail the same run more than twice in a row
|
|
1543
1523
|
// because we purposefully time out rather than spamming.
|
|
1544
1524
|
for _ in 1..=2 {
|
|
1545
|
-
let activation =
|
|
1525
|
+
let activation = worker.poll_workflow_activation().await.unwrap();
|
|
1546
1526
|
// Issue a nonsense completion that will trigger a WFT failure
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
let activation =
|
|
1527
|
+
worker
|
|
1528
|
+
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1529
|
+
activation.run_id,
|
|
1530
|
+
RequestCancelActivity { seq: 1 }.into(),
|
|
1531
|
+
))
|
|
1532
|
+
.await
|
|
1533
|
+
.unwrap();
|
|
1534
|
+
let activation = worker.poll_workflow_activation().await.unwrap();
|
|
1555
1535
|
assert_matches!(
|
|
1556
1536
|
activation.jobs.as_slice(),
|
|
1557
1537
|
[WorkflowActivationJob {
|
|
@@ -1559,14 +1539,12 @@ async fn failing_wft_doesnt_eat_permit_forever() {
|
|
|
1559
1539
|
},]
|
|
1560
1540
|
);
|
|
1561
1541
|
run_id = activation.run_id.clone();
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
.
|
|
1567
|
-
.
|
|
1568
|
-
assert_eq!(core.outstanding_wfts(TEST_Q), 0);
|
|
1569
|
-
assert_eq!(core.available_wft_permits(TEST_Q), 2);
|
|
1542
|
+
worker
|
|
1543
|
+
.complete_workflow_activation(WorkflowActivationCompletion::empty(activation.run_id))
|
|
1544
|
+
.await
|
|
1545
|
+
.unwrap();
|
|
1546
|
+
assert_eq!(worker.outstanding_workflow_tasks(), 0);
|
|
1547
|
+
assert_eq!(worker.available_wft_permits(), 2);
|
|
1570
1548
|
}
|
|
1571
1549
|
// We should be "out of work" because the mock service thinks we didn't complete the last task,
|
|
1572
1550
|
// which we didn't, because we don't spam failures. The real server would eventually time out
|
|
@@ -1577,91 +1555,86 @@ async fn failing_wft_doesnt_eat_permit_forever() {
|
|
|
1577
1555
|
.unwrap()
|
|
1578
1556
|
.write()
|
|
1579
1557
|
.remove_by_left(&run_id);
|
|
1580
|
-
let activation =
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1558
|
+
let activation = worker.poll_workflow_activation().await.unwrap();
|
|
1559
|
+
worker
|
|
1560
|
+
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1561
|
+
activation.run_id,
|
|
1562
|
+
CompleteWorkflowExecution { result: None }.into(),
|
|
1563
|
+
))
|
|
1564
|
+
.await
|
|
1565
|
+
.unwrap();
|
|
1588
1566
|
|
|
1589
|
-
|
|
1567
|
+
worker.shutdown().await;
|
|
1590
1568
|
}
|
|
1591
1569
|
|
|
1592
1570
|
#[tokio::test]
|
|
1593
|
-
async fn
|
|
1571
|
+
async fn cache_miss_will_fetch_history() {
|
|
1594
1572
|
let mut t = TestHistoryBuilder::default();
|
|
1595
1573
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
1596
1574
|
t.add_full_wf_task();
|
|
1597
1575
|
t.add_we_signaled("sig", vec![]);
|
|
1598
1576
|
t.add_full_wf_task();
|
|
1599
1577
|
t.add_workflow_execution_completed();
|
|
1578
|
+
let get_exec_resp: GetWorkflowExecutionHistoryResponse = t.get_history_info(2).unwrap().into();
|
|
1600
1579
|
|
|
1601
1580
|
let mut mh = MockPollCfg::from_resp_batches(
|
|
1602
1581
|
"fake_wf_id",
|
|
1603
1582
|
t,
|
|
1604
|
-
[
|
|
1605
|
-
|
|
1606
|
-
ResponseType::OneTask(2),
|
|
1607
|
-
ResponseType::ToTaskNum(1),
|
|
1608
|
-
ResponseType::OneTask(2),
|
|
1609
|
-
ResponseType::ToTaskNum(1),
|
|
1610
|
-
ResponseType::OneTask(2),
|
|
1611
|
-
// Last one to complete successfully
|
|
1612
|
-
ResponseType::ToTaskNum(1),
|
|
1613
|
-
],
|
|
1614
|
-
mock_gateway(),
|
|
1583
|
+
[ResponseType::ToTaskNum(1), ResponseType::OneTask(2)],
|
|
1584
|
+
mock_workflow_client(),
|
|
1615
1585
|
);
|
|
1616
|
-
mh.num_expected_fails = Some(
|
|
1617
|
-
mh.
|
|
1618
|
-
|
|
1586
|
+
mh.num_expected_fails = Some(0);
|
|
1587
|
+
mh.mock_client
|
|
1588
|
+
.expect_get_workflow_execution_history()
|
|
1589
|
+
.times(1)
|
|
1590
|
+
.returning(move |_, _, _| Ok(get_exec_resp.clone()));
|
|
1619
1591
|
let mut mock = build_mock_pollers(mh);
|
|
1620
|
-
mock.worker_cfg(
|
|
1621
|
-
cfg.
|
|
1592
|
+
mock.worker_cfg(|cfg| {
|
|
1593
|
+
cfg.max_cached_workflows = 1;
|
|
1622
1594
|
});
|
|
1623
|
-
let
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1595
|
+
let worker = mock_worker(mock);
|
|
1596
|
+
|
|
1597
|
+
let activation = worker.poll_workflow_activation().await.unwrap();
|
|
1598
|
+
assert_matches!(
|
|
1599
|
+
activation.jobs.as_slice(),
|
|
1600
|
+
[WorkflowActivationJob {
|
|
1601
|
+
variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
|
|
1602
|
+
}]
|
|
1603
|
+
);
|
|
1604
|
+
worker
|
|
1605
|
+
.complete_workflow_activation(WorkflowActivationCompletion::empty(&activation.run_id))
|
|
1633
1606
|
.await
|
|
1634
1607
|
.unwrap();
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1608
|
+
// Force an eviction
|
|
1609
|
+
worker.request_wf_eviction(
|
|
1610
|
+
&activation.run_id,
|
|
1611
|
+
"whatever",
|
|
1612
|
+
EvictionReason::LangRequested,
|
|
1613
|
+
);
|
|
1614
|
+
// Handle the eviction, and the restart
|
|
1615
|
+
for _ in 1..=2 {
|
|
1616
|
+
let activation = worker.poll_workflow_activation().await.unwrap();
|
|
1617
|
+
worker
|
|
1618
|
+
.complete_workflow_activation(WorkflowActivationCompletion::empty(activation.run_id))
|
|
1619
|
+
.await
|
|
1620
|
+
.unwrap();
|
|
1621
|
+
}
|
|
1622
|
+
let activation = worker.poll_workflow_activation().await.unwrap();
|
|
1623
|
+
assert_matches!(
|
|
1624
|
+
activation.jobs.as_slice(),
|
|
1625
|
+
[WorkflowActivationJob {
|
|
1626
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
|
1627
|
+
}]
|
|
1628
|
+
);
|
|
1629
|
+
worker
|
|
1630
|
+
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1645
1631
|
activation.run_id,
|
|
1632
|
+
CompleteWorkflowExecution { result: None }.into(),
|
|
1646
1633
|
))
|
|
1647
1634
|
.await
|
|
1648
1635
|
.unwrap();
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
// When we loop back up, the poll will trigger a cache miss, which we should immediately
|
|
1652
|
-
// reply to WFT with failure, and then poll again, which will deliver the from-the-start
|
|
1653
|
-
// history
|
|
1654
|
-
}
|
|
1655
|
-
let activation = core.poll_workflow_activation(TEST_Q).await.unwrap();
|
|
1656
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1657
|
-
TEST_Q,
|
|
1658
|
-
activation.run_id,
|
|
1659
|
-
CompleteWorkflowExecution { result: None }.into(),
|
|
1660
|
-
))
|
|
1661
|
-
.await
|
|
1662
|
-
.unwrap();
|
|
1663
|
-
|
|
1664
|
-
core.shutdown().await;
|
|
1636
|
+
assert_eq!(worker.outstanding_workflow_tasks(), 0);
|
|
1637
|
+
worker.shutdown().await;
|
|
1665
1638
|
}
|
|
1666
1639
|
|
|
1667
1640
|
/// This test verifies that WFTs which come as replies to completing a WFT are properly delivered
|
|
@@ -1682,7 +1655,7 @@ async fn tasks_from_completion_are_delivered() {
|
|
|
1682
1655
|
1.into(),
|
|
1683
1656
|
TEST_Q.to_string(),
|
|
1684
1657
|
)];
|
|
1685
|
-
let mut mock =
|
|
1658
|
+
let mut mock = mock_workflow_client();
|
|
1686
1659
|
mock.expect_complete_workflow_task()
|
|
1687
1660
|
.times(1)
|
|
1688
1661
|
.returning(move |_| {
|
|
@@ -1698,15 +1671,15 @@ async fn tasks_from_completion_are_delivered() {
|
|
|
1698
1671
|
mock.expect_complete_workflow_task()
|
|
1699
1672
|
.times(1)
|
|
1700
1673
|
.returning(|_| Ok(Default::default()));
|
|
1701
|
-
let mut mock = MocksHolder::
|
|
1702
|
-
mock.worker_cfg(
|
|
1703
|
-
let core =
|
|
1674
|
+
let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
|
|
1675
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 2);
|
|
1676
|
+
let core = mock_worker(mock);
|
|
1704
1677
|
|
|
1705
|
-
let wf_task = core.poll_workflow_activation(
|
|
1706
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::empty(
|
|
1678
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
1679
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
|
|
1707
1680
|
.await
|
|
1708
1681
|
.unwrap();
|
|
1709
|
-
let wf_task = core.poll_workflow_activation(
|
|
1682
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
1710
1683
|
assert_matches!(
|
|
1711
1684
|
wf_task.jobs.as_slice(),
|
|
1712
1685
|
[WorkflowActivationJob {
|
|
@@ -1714,7 +1687,6 @@ async fn tasks_from_completion_are_delivered() {
|
|
|
1714
1687
|
},]
|
|
1715
1688
|
);
|
|
1716
1689
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
1717
|
-
TEST_Q,
|
|
1718
1690
|
wf_task.run_id,
|
|
1719
1691
|
vec![CompleteWorkflowExecution { result: None }.into()],
|
|
1720
1692
|
))
|
|
@@ -1722,3 +1694,46 @@ async fn tasks_from_completion_are_delivered() {
|
|
|
1722
1694
|
.unwrap();
|
|
1723
1695
|
core.shutdown().await;
|
|
1724
1696
|
}
|
|
1697
|
+
|
|
1698
|
+
#[tokio::test]
|
|
1699
|
+
async fn evict_missing_wf_during_poll_doesnt_eat_permit() {
|
|
1700
|
+
let wfid = "fake_wf_id";
|
|
1701
|
+
let mut t = TestHistoryBuilder::default();
|
|
1702
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
1703
|
+
t.add_full_wf_task();
|
|
1704
|
+
t.add_we_signaled("sig", vec![]);
|
|
1705
|
+
t.add_full_wf_task();
|
|
1706
|
+
t.add_workflow_execution_completed();
|
|
1707
|
+
|
|
1708
|
+
let tasks = [hist_to_poll_resp(
|
|
1709
|
+
&t,
|
|
1710
|
+
wfid.to_owned(),
|
|
1711
|
+
// Use a partial task so that we'll fetch history
|
|
1712
|
+
ResponseType::OneTask(2),
|
|
1713
|
+
TEST_Q.to_string(),
|
|
1714
|
+
)];
|
|
1715
|
+
let mut mock = mock_workflow_client();
|
|
1716
|
+
mock.expect_get_workflow_execution_history()
|
|
1717
|
+
.times(1)
|
|
1718
|
+
.returning(move |_, _, _| {
|
|
1719
|
+
Ok(GetWorkflowExecutionHistoryResponse {
|
|
1720
|
+
// Empty history so we error applying it (no jobs)
|
|
1721
|
+
history: Some(History { events: vec![] }),
|
|
1722
|
+
raw_history: vec![],
|
|
1723
|
+
next_page_token: vec![],
|
|
1724
|
+
archived: false,
|
|
1725
|
+
})
|
|
1726
|
+
});
|
|
1727
|
+
let mut mock = MocksHolder::from_client_with_responses(mock, tasks, []);
|
|
1728
|
+
mock.worker_cfg(|wc| {
|
|
1729
|
+
wc.max_cached_workflows = 1;
|
|
1730
|
+
wc.max_outstanding_workflow_tasks = 1;
|
|
1731
|
+
});
|
|
1732
|
+
let core = mock_worker(mock);
|
|
1733
|
+
|
|
1734
|
+
// Should error because mock is out of work
|
|
1735
|
+
assert_matches!(core.poll_workflow_activation().await, Err(_));
|
|
1736
|
+
assert_eq!(core.available_wft_permits(), 1);
|
|
1737
|
+
|
|
1738
|
+
core.shutdown().await;
|
|
1739
|
+
}
|