@temporalio/core-bridge 1.5.2 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +304 -112
- package/lib/index.d.ts +8 -6
- package/lib/index.js.map +1 -1
- package/package.json +9 -4
- 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 +2 -2
- package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
- package/sdk-core/.buildkite/pipeline.yml +2 -4
- package/sdk-core/.cargo/config.toml +5 -2
- package/sdk-core/.github/workflows/heavy.yml +29 -0
- package/sdk-core/Cargo.toml +1 -1
- package/sdk-core/README.md +20 -10
- package/sdk-core/client/src/lib.rs +215 -39
- package/sdk-core/client/src/metrics.rs +17 -8
- package/sdk-core/client/src/raw.rs +4 -4
- package/sdk-core/client/src/retry.rs +32 -20
- package/sdk-core/core/Cargo.toml +25 -12
- package/sdk-core/core/src/abstractions/take_cell.rs +28 -0
- package/sdk-core/core/src/abstractions.rs +204 -14
- package/sdk-core/core/src/core_tests/activity_tasks.rs +143 -50
- package/sdk-core/core/src/core_tests/child_workflows.rs +6 -5
- package/sdk-core/core/src/core_tests/determinism.rs +165 -2
- package/sdk-core/core/src/core_tests/local_activities.rs +431 -43
- package/sdk-core/core/src/core_tests/queries.rs +34 -16
- package/sdk-core/core/src/core_tests/workers.rs +8 -5
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +588 -55
- package/sdk-core/core/src/ephemeral_server/mod.rs +113 -12
- package/sdk-core/core/src/internal_flags.rs +155 -0
- package/sdk-core/core/src/lib.rs +16 -9
- package/sdk-core/core/src/protosext/mod.rs +1 -1
- package/sdk-core/core/src/replay/mod.rs +16 -27
- package/sdk-core/core/src/telemetry/log_export.rs +1 -1
- package/sdk-core/core/src/telemetry/metrics.rs +69 -35
- package/sdk-core/core/src/telemetry/mod.rs +60 -21
- package/sdk-core/core/src/telemetry/prometheus_server.rs +19 -13
- package/sdk-core/core/src/test_help/mod.rs +73 -14
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +119 -160
- package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
- package/sdk-core/core/src/worker/activities/local_activities.rs +379 -129
- package/sdk-core/core/src/worker/activities.rs +350 -175
- package/sdk-core/core/src/worker/client/mocks.rs +22 -2
- package/sdk-core/core/src/worker/client.rs +18 -2
- package/sdk-core/core/src/worker/mod.rs +183 -64
- package/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
- package/sdk-core/core/src/worker/workflow/history_update.rs +916 -277
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +216 -183
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +9 -12
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +7 -9
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +160 -87
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +13 -14
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -9
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +14 -17
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +242 -110
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +27 -19
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +9 -11
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +321 -206
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +13 -18
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +20 -29
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +257 -51
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +310 -150
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +17 -20
- package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +31 -15
- package/sdk-core/core/src/worker/workflow/managed_run.rs +1052 -380
- package/sdk-core/core/src/worker/workflow/mod.rs +598 -390
- package/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
- package/sdk-core/core/src/worker/workflow/wft_extraction.rs +137 -0
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
- package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
- package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +469 -718
- package/sdk-core/core-api/Cargo.toml +2 -1
- package/sdk-core/core-api/src/errors.rs +1 -34
- package/sdk-core/core-api/src/lib.rs +19 -9
- package/sdk-core/core-api/src/telemetry.rs +4 -6
- package/sdk-core/core-api/src/worker.rs +19 -1
- package/sdk-core/etc/deps.svg +115 -140
- package/sdk-core/etc/regen-depgraph.sh +5 -0
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +86 -61
- package/sdk-core/fsm/rustfsm_trait/src/lib.rs +29 -71
- package/sdk-core/histories/ends_empty_wft_complete.bin +0 -0
- package/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
- package/sdk-core/histories/old_change_marker_format.bin +0 -0
- package/sdk-core/protos/api_upstream/.github/CODEOWNERS +2 -1
- package/sdk-core/protos/api_upstream/Makefile +6 -6
- package/sdk-core/protos/api_upstream/build/go.mod +7 -0
- package/sdk-core/protos/api_upstream/build/go.sum +5 -0
- package/sdk-core/protos/api_upstream/build/tools.go +29 -0
- package/sdk-core/protos/api_upstream/go.mod +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +9 -2
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +7 -26
- package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +3 -7
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +8 -8
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +25 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +49 -26
- package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +5 -2
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
- package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
- package/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -28
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -4
- package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +7 -8
- package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +10 -7
- package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +19 -30
- package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
- package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
- package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +8 -0
- package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +67 -60
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +85 -84
- package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +9 -3
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
- package/sdk-core/sdk/Cargo.toml +5 -4
- package/sdk-core/sdk/src/lib.rs +108 -26
- package/sdk-core/sdk/src/workflow_context/options.rs +7 -1
- package/sdk-core/sdk/src/workflow_context.rs +24 -17
- package/sdk-core/sdk/src/workflow_future.rs +16 -15
- package/sdk-core/sdk-core-protos/Cargo.toml +5 -2
- package/sdk-core/sdk-core-protos/build.rs +36 -2
- package/sdk-core/sdk-core-protos/src/history_builder.rs +138 -106
- package/sdk-core/sdk-core-protos/src/history_info.rs +10 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +272 -87
- package/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
- package/sdk-core/test-utils/Cargo.toml +3 -1
- package/sdk-core/test-utils/src/canned_histories.rs +106 -296
- package/sdk-core/test-utils/src/histfetch.rs +1 -1
- package/sdk-core/test-utils/src/lib.rs +82 -23
- package/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
- package/sdk-core/test-utils/src/workflows.rs +29 -0
- package/sdk-core/tests/fuzzy_workflow.rs +130 -0
- package/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
- package/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
- package/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
- package/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
- package/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +161 -72
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +80 -3
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +94 -200
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +2 -4
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +34 -28
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +76 -7
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +7 -8
- package/sdk-core/tests/integ_tests/workflow_tests.rs +13 -14
- package/sdk-core/tests/main.rs +3 -13
- package/sdk-core/tests/runner.rs +75 -36
- package/sdk-core/tests/wf_input_replay.rs +32 -0
- package/src/conversions.rs +14 -8
- package/src/runtime.rs +9 -8
- package/ts/index.ts +8 -6
- package/sdk-core/bridge-ffi/Cargo.toml +0 -24
- package/sdk-core/bridge-ffi/LICENSE.txt +0 -23
- package/sdk-core/bridge-ffi/build.rs +0 -25
- package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -224
- package/sdk-core/bridge-ffi/src/lib.rs +0 -746
- package/sdk-core/bridge-ffi/src/wrappers.rs +0 -221
- package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
- package/sdk-core/sdk/src/conversions.rs +0 -8
|
@@ -8,35 +8,47 @@ use crate::{
|
|
|
8
8
|
worker::{client::mocks::mock_workflow_client, LEGACY_QUERY_ID},
|
|
9
9
|
};
|
|
10
10
|
use anyhow::anyhow;
|
|
11
|
+
use crossbeam::queue::SegQueue;
|
|
11
12
|
use futures::{future::join_all, FutureExt};
|
|
12
13
|
use std::{
|
|
13
14
|
collections::HashMap,
|
|
15
|
+
ops::Sub,
|
|
14
16
|
sync::{
|
|
15
17
|
atomic::{AtomicUsize, Ordering},
|
|
16
18
|
Arc,
|
|
17
19
|
},
|
|
18
|
-
time::Duration,
|
|
20
|
+
time::{Duration, SystemTime},
|
|
19
21
|
};
|
|
20
22
|
use temporal_client::WorkflowOptions;
|
|
21
|
-
use temporal_sdk::{
|
|
22
|
-
|
|
23
|
+
use temporal_sdk::{
|
|
24
|
+
ActContext, ActivityCancelledError, LocalActivityOptions, WfContext, WorkflowResult,
|
|
25
|
+
};
|
|
26
|
+
use temporal_sdk_core_api::{
|
|
27
|
+
errors::{PollActivityError, PollWfError},
|
|
28
|
+
Worker,
|
|
29
|
+
};
|
|
23
30
|
use temporal_sdk_core_protos::{
|
|
24
31
|
coresdk::{
|
|
25
32
|
activity_result::ActivityExecutionResult,
|
|
26
33
|
workflow_activation::{workflow_activation_job, WorkflowActivationJob},
|
|
27
|
-
workflow_commands::{
|
|
34
|
+
workflow_commands::{
|
|
35
|
+
ActivityCancellationType, QueryResult, QuerySuccess, ScheduleLocalActivity,
|
|
36
|
+
},
|
|
28
37
|
workflow_completion::WorkflowActivationCompletion,
|
|
29
38
|
ActivityTaskCompletion, AsJsonPayloadExt,
|
|
30
39
|
},
|
|
31
40
|
temporal::api::{
|
|
32
|
-
common::v1::RetryPolicy,
|
|
41
|
+
common::v1::RetryPolicy,
|
|
42
|
+
enums::v1::{EventType, TimeoutType, WorkflowTaskFailedCause},
|
|
43
|
+
failure::v1::{failure::FailureInfo, Failure},
|
|
33
44
|
query::v1::WorkflowQuery,
|
|
34
45
|
},
|
|
46
|
+
DEFAULT_ACTIVITY_TYPE,
|
|
35
47
|
};
|
|
36
48
|
use temporal_sdk_core_test_utils::{
|
|
37
49
|
schedule_local_activity_cmd, start_timer_cmd, WorkerTestHelpers,
|
|
38
50
|
};
|
|
39
|
-
use tokio::sync::Barrier;
|
|
51
|
+
use tokio::{join, sync::Barrier};
|
|
40
52
|
|
|
41
53
|
async fn echo(_ctx: ActContext, e: String) -> anyhow::Result<String> {
|
|
42
54
|
Ok(e)
|
|
@@ -54,7 +66,7 @@ async fn local_act_two_wfts_before_marker(#[case] replay: bool, #[case] cached:
|
|
|
54
66
|
let mut t = TestHistoryBuilder::default();
|
|
55
67
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
56
68
|
t.add_full_wf_task();
|
|
57
|
-
let timer_started_event_id = t.
|
|
69
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
58
70
|
t.add_full_wf_task();
|
|
59
71
|
t.add_local_activity_result_marker(1, "1", b"echo".into());
|
|
60
72
|
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
@@ -79,7 +91,7 @@ async fn local_act_two_wfts_before_marker(#[case] replay: bool, #[case] cached:
|
|
|
79
91
|
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
80
92
|
|ctx: WfContext| async move {
|
|
81
93
|
let la = ctx.local_activity(LocalActivityOptions {
|
|
82
|
-
activity_type:
|
|
94
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
83
95
|
input: "hi".as_json_payload().expect("serializes fine"),
|
|
84
96
|
..Default::default()
|
|
85
97
|
});
|
|
@@ -88,7 +100,7 @@ async fn local_act_two_wfts_before_marker(#[case] replay: bool, #[case] cached:
|
|
|
88
100
|
Ok(().into())
|
|
89
101
|
},
|
|
90
102
|
);
|
|
91
|
-
worker.register_activity(
|
|
103
|
+
worker.register_activity(DEFAULT_ACTIVITY_TYPE, echo);
|
|
92
104
|
worker
|
|
93
105
|
.submit_wf(
|
|
94
106
|
wf_id.to_owned(),
|
|
@@ -106,7 +118,7 @@ pub async fn local_act_fanout_wf(ctx: WfContext) -> WorkflowResult<()> {
|
|
|
106
118
|
.map(|i| {
|
|
107
119
|
ctx.local_activity(LocalActivityOptions {
|
|
108
120
|
activity_type: "echo".to_string(),
|
|
109
|
-
input: format!("Hi {}"
|
|
121
|
+
input: format!("Hi {i}")
|
|
110
122
|
.as_json_payload()
|
|
111
123
|
.expect("serializes fine"),
|
|
112
124
|
..Default::default()
|
|
@@ -123,7 +135,7 @@ async fn local_act_many_concurrent() {
|
|
|
123
135
|
let mut t = TestHistoryBuilder::default();
|
|
124
136
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
125
137
|
t.add_full_wf_task();
|
|
126
|
-
let timer_started_event_id = t.
|
|
138
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
127
139
|
t.add_full_wf_task();
|
|
128
140
|
for i in 1..=50 {
|
|
129
141
|
t.add_local_activity_result_marker(i, &i.to_string(), b"echo".into());
|
|
@@ -164,12 +176,7 @@ async fn local_act_many_concurrent() {
|
|
|
164
176
|
async fn local_act_heartbeat(#[case] shutdown_middle: bool) {
|
|
165
177
|
let mut t = TestHistoryBuilder::default();
|
|
166
178
|
let wft_timeout = Duration::from_millis(200);
|
|
167
|
-
|
|
168
|
-
wes_short_wft_timeout.workflow_task_timeout = Some(wft_timeout.try_into().unwrap());
|
|
169
|
-
t.add(
|
|
170
|
-
EventType::WorkflowExecutionStarted,
|
|
171
|
-
wes_short_wft_timeout.into(),
|
|
172
|
-
);
|
|
179
|
+
t.add_wfe_started_with_wft_timeout(wft_timeout);
|
|
173
180
|
t.add_full_wf_task();
|
|
174
181
|
// Task created by WFT heartbeat
|
|
175
182
|
t.add_full_wf_task();
|
|
@@ -300,7 +307,7 @@ async fn local_act_retry_long_backoff_uses_timer() {
|
|
|
300
307
|
"1",
|
|
301
308
|
Failure::application_failure("la failed".to_string(), false),
|
|
302
309
|
);
|
|
303
|
-
let timer_started_event_id = t.
|
|
310
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
304
311
|
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
305
312
|
t.add_full_wf_task();
|
|
306
313
|
t.add_local_activity_fail_marker(
|
|
@@ -308,7 +315,7 @@ async fn local_act_retry_long_backoff_uses_timer() {
|
|
|
308
315
|
"2",
|
|
309
316
|
Failure::application_failure("la failed".to_string(), false),
|
|
310
317
|
);
|
|
311
|
-
let timer_started_event_id = t.
|
|
318
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
312
319
|
t.add_timer_fired(timer_started_event_id, "2".to_string());
|
|
313
320
|
t.add_full_wf_task();
|
|
314
321
|
t.add_workflow_execution_completed();
|
|
@@ -328,7 +335,7 @@ async fn local_act_retry_long_backoff_uses_timer() {
|
|
|
328
335
|
|ctx: WfContext| async move {
|
|
329
336
|
let la_res = ctx
|
|
330
337
|
.local_activity(LocalActivityOptions {
|
|
331
|
-
activity_type:
|
|
338
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
332
339
|
input: "hi".as_json_payload().expect("serializes fine"),
|
|
333
340
|
retry_policy: RetryPolicy {
|
|
334
341
|
initial_interval: Some(prost_dur!(from_millis(65))),
|
|
@@ -347,9 +354,12 @@ async fn local_act_retry_long_backoff_uses_timer() {
|
|
|
347
354
|
Ok(().into())
|
|
348
355
|
},
|
|
349
356
|
);
|
|
350
|
-
worker.register_activity(
|
|
351
|
-
|
|
352
|
-
|
|
357
|
+
worker.register_activity(
|
|
358
|
+
DEFAULT_ACTIVITY_TYPE,
|
|
359
|
+
move |_ctx: ActContext, _: String| async move {
|
|
360
|
+
Result::<(), _>::Err(anyhow!("Oh no I failed!"))
|
|
361
|
+
},
|
|
362
|
+
);
|
|
353
363
|
worker
|
|
354
364
|
.submit_wf(
|
|
355
365
|
wf_id.to_owned(),
|
|
@@ -367,7 +377,7 @@ async fn local_act_null_result() {
|
|
|
367
377
|
let mut t = TestHistoryBuilder::default();
|
|
368
378
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
369
379
|
t.add_full_wf_task();
|
|
370
|
-
t.add_local_activity_marker(1, "1", None, None,
|
|
380
|
+
t.add_local_activity_marker(1, "1", None, None, |_| {});
|
|
371
381
|
t.add_workflow_execution_completed();
|
|
372
382
|
|
|
373
383
|
let wf_id = "fakeid";
|
|
@@ -408,8 +418,8 @@ async fn local_act_command_immediately_follows_la_marker() {
|
|
|
408
418
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
409
419
|
t.add_full_wf_task();
|
|
410
420
|
t.add_full_wf_task();
|
|
411
|
-
t.
|
|
412
|
-
t.
|
|
421
|
+
t.add_local_activity_result_marker(1, "1", "done".into());
|
|
422
|
+
t.add_by_type(EventType::TimerStarted);
|
|
413
423
|
t.add_full_wf_task();
|
|
414
424
|
|
|
415
425
|
let wf_id = "fakeid";
|
|
@@ -448,16 +458,11 @@ async fn local_act_command_immediately_follows_la_marker() {
|
|
|
448
458
|
async fn query_during_wft_heartbeat_doesnt_accidentally_fail_to_continue_heartbeat() {
|
|
449
459
|
let wfid = "fake_wf_id";
|
|
450
460
|
let mut t = TestHistoryBuilder::default();
|
|
451
|
-
|
|
452
|
-
wes_short_wft_timeout.workflow_task_timeout = Some(prost_dur!(from_millis(200)));
|
|
453
|
-
t.add(
|
|
454
|
-
EventType::WorkflowExecutionStarted,
|
|
455
|
-
wes_short_wft_timeout.into(),
|
|
456
|
-
);
|
|
461
|
+
t.add_wfe_started_with_wft_timeout(Duration::from_millis(200));
|
|
457
462
|
t.add_full_wf_task();
|
|
458
463
|
// get query here
|
|
459
464
|
t.add_full_wf_task();
|
|
460
|
-
t.
|
|
465
|
+
t.add_local_activity_result_marker(1, "1", "done".into());
|
|
461
466
|
t.add_workflow_execution_completed();
|
|
462
467
|
|
|
463
468
|
let query_with_hist_task = {
|
|
@@ -502,7 +507,7 @@ async fn query_during_wft_heartbeat_doesnt_accidentally_fail_to_continue_heartbe
|
|
|
502
507
|
task.run_id,
|
|
503
508
|
schedule_local_activity_cmd(
|
|
504
509
|
1,
|
|
505
|
-
"
|
|
510
|
+
"1",
|
|
506
511
|
ActivityCancellationType::TryCancel,
|
|
507
512
|
Duration::from_secs(60),
|
|
508
513
|
),
|
|
@@ -568,21 +573,17 @@ async fn la_resolve_during_legacy_query_does_not_combine(#[case] impossible_quer
|
|
|
568
573
|
// never happen, but there was an issue where an LA resolving could trigger that.
|
|
569
574
|
let wfid = "fake_wf_id";
|
|
570
575
|
let mut t = TestHistoryBuilder::default();
|
|
571
|
-
|
|
572
|
-
t.add(
|
|
573
|
-
EventType::WorkflowExecutionStarted,
|
|
574
|
-
wes_short_wft_timeout.into(),
|
|
575
|
-
);
|
|
576
|
+
t.add(default_wes_attribs());
|
|
576
577
|
// Since we don't send queries with start workflow, need one workflow task of something else
|
|
577
578
|
// b/c we want to get an activation with a job and a nonlegacy query
|
|
578
579
|
t.add_full_wf_task();
|
|
579
|
-
let timer_started_event_id = t.
|
|
580
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
580
581
|
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
581
582
|
|
|
582
583
|
// nonlegacy query got here & LA started here
|
|
583
584
|
t.add_full_wf_task();
|
|
584
585
|
// legacy query got here, at the same time that the LA is resolved
|
|
585
|
-
t.
|
|
586
|
+
t.add_local_activity_result_marker(1, "1", "whatever".into());
|
|
586
587
|
t.add_workflow_execution_completed();
|
|
587
588
|
|
|
588
589
|
let barr = Arc::new(Barrier::new(2));
|
|
@@ -618,8 +619,12 @@ async fn la_resolve_during_legacy_query_does_not_combine(#[case] impossible_quer
|
|
|
618
619
|
2,
|
|
619
620
|
),
|
|
620
621
|
);
|
|
621
|
-
// Strip history
|
|
622
|
-
|
|
622
|
+
// Strip beginning of history so the only events are WFT sched/started, we need to look
|
|
623
|
+
// like we hit the cache
|
|
624
|
+
{
|
|
625
|
+
let h = pr.history.as_mut().unwrap();
|
|
626
|
+
h.events = h.events.split_off(6);
|
|
627
|
+
}
|
|
623
628
|
// In the nonsense server response case, we attach a legacy query, otherwise this
|
|
624
629
|
// response looks like a normal response to a forced WFT heartbeat.
|
|
625
630
|
if impossible_query_in_task {
|
|
@@ -735,3 +740,386 @@ async fn la_resolve_during_legacy_query_does_not_combine(#[case] impossible_quer
|
|
|
735
740
|
tokio::join!(wf_fut, act_fut);
|
|
736
741
|
core.shutdown().await;
|
|
737
742
|
}
|
|
743
|
+
|
|
744
|
+
#[tokio::test]
|
|
745
|
+
async fn test_schedule_to_start_timeout() {
|
|
746
|
+
let mut t = TestHistoryBuilder::default();
|
|
747
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
748
|
+
t.add_full_wf_task();
|
|
749
|
+
|
|
750
|
+
let wf_id = "fakeid";
|
|
751
|
+
let mock = mock_workflow_client();
|
|
752
|
+
let mh = MockPollCfg::from_resp_batches(wf_id, t, [ResponseType::ToTaskNum(1)], mock);
|
|
753
|
+
let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 1);
|
|
754
|
+
|
|
755
|
+
worker.register_wf(
|
|
756
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
757
|
+
|ctx: WfContext| async move {
|
|
758
|
+
let la_res = ctx
|
|
759
|
+
.local_activity(LocalActivityOptions {
|
|
760
|
+
activity_type: "echo".to_string(),
|
|
761
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
762
|
+
// Impossibly small timeout so we timeout in the queue
|
|
763
|
+
schedule_to_start_timeout: prost_dur!(from_nanos(1)),
|
|
764
|
+
..Default::default()
|
|
765
|
+
})
|
|
766
|
+
.await;
|
|
767
|
+
assert_eq!(la_res.timed_out(), Some(TimeoutType::ScheduleToStart));
|
|
768
|
+
let rfail = la_res.unwrap_failure();
|
|
769
|
+
assert_matches!(
|
|
770
|
+
rfail.failure_info,
|
|
771
|
+
Some(FailureInfo::ActivityFailureInfo(_))
|
|
772
|
+
);
|
|
773
|
+
assert_matches!(
|
|
774
|
+
rfail.cause.unwrap().failure_info,
|
|
775
|
+
Some(FailureInfo::TimeoutFailureInfo(_))
|
|
776
|
+
);
|
|
777
|
+
Ok(().into())
|
|
778
|
+
},
|
|
779
|
+
);
|
|
780
|
+
worker.register_activity(
|
|
781
|
+
"echo",
|
|
782
|
+
move |_ctx: ActContext, _: String| async move { Ok(()) },
|
|
783
|
+
);
|
|
784
|
+
worker
|
|
785
|
+
.submit_wf(
|
|
786
|
+
wf_id.to_owned(),
|
|
787
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
788
|
+
vec![],
|
|
789
|
+
WorkflowOptions::default(),
|
|
790
|
+
)
|
|
791
|
+
.await
|
|
792
|
+
.unwrap();
|
|
793
|
+
worker.run_until_done().await.unwrap();
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
#[rstest::rstest]
|
|
797
|
+
#[case::sched_to_start(true)]
|
|
798
|
+
#[case::sched_to_close(false)]
|
|
799
|
+
#[tokio::test]
|
|
800
|
+
async fn test_schedule_to_start_timeout_not_based_on_original_time(
|
|
801
|
+
#[case] is_sched_to_start: bool,
|
|
802
|
+
) {
|
|
803
|
+
// We used to carry over the schedule time of LAs from the "original" schedule time if these LAs
|
|
804
|
+
// created newly after backing off across a timer. That was a mistake, since schedule-to-start
|
|
805
|
+
// timeouts should apply to when the new attempt was scheduled. This test verifies:
|
|
806
|
+
// * we don't time out on s-t-s timeouts because of that, when the param is true.
|
|
807
|
+
// * we do properly time out on s-t-c timeouts when the param is false
|
|
808
|
+
|
|
809
|
+
let mut t = TestHistoryBuilder::default();
|
|
810
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
811
|
+
t.add_full_wf_task();
|
|
812
|
+
let orig_sched = SystemTime::now().sub(Duration::from_secs(60 * 20));
|
|
813
|
+
t.add_local_activity_marker(
|
|
814
|
+
1,
|
|
815
|
+
"1",
|
|
816
|
+
None,
|
|
817
|
+
Some(Failure::application_failure("la failed".to_string(), false)),
|
|
818
|
+
|deets| {
|
|
819
|
+
// Really old schedule time, which should _not_ count against schedule_to_start
|
|
820
|
+
deets.original_schedule_time = Some(orig_sched.into());
|
|
821
|
+
// Backoff value must be present since we're simulating timer backoff
|
|
822
|
+
deets.backoff = Some(prost_dur!(from_secs(100)));
|
|
823
|
+
},
|
|
824
|
+
);
|
|
825
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
826
|
+
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
827
|
+
t.add_workflow_task_scheduled_and_started();
|
|
828
|
+
|
|
829
|
+
let wf_id = "fakeid";
|
|
830
|
+
let mock = mock_workflow_client();
|
|
831
|
+
let mh = MockPollCfg::from_resp_batches(wf_id, t, [ResponseType::AllHistory], mock);
|
|
832
|
+
let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 1);
|
|
833
|
+
|
|
834
|
+
let schedule_to_close_timeout = Some(if is_sched_to_start {
|
|
835
|
+
// This 60 minute timeout will not have elapsed according to the original
|
|
836
|
+
// schedule time in the history.
|
|
837
|
+
Duration::from_secs(60 * 60)
|
|
838
|
+
} else {
|
|
839
|
+
// This 10 minute timeout will have already elapsed
|
|
840
|
+
Duration::from_secs(10 * 60)
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
worker.register_wf(
|
|
844
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
845
|
+
move |ctx: WfContext| async move {
|
|
846
|
+
let la_res = ctx
|
|
847
|
+
.local_activity(LocalActivityOptions {
|
|
848
|
+
activity_type: "echo".to_string(),
|
|
849
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
850
|
+
retry_policy: RetryPolicy {
|
|
851
|
+
initial_interval: Some(prost_dur!(from_millis(50))),
|
|
852
|
+
backoff_coefficient: 1.2,
|
|
853
|
+
maximum_interval: None,
|
|
854
|
+
maximum_attempts: 5,
|
|
855
|
+
non_retryable_error_types: vec![],
|
|
856
|
+
},
|
|
857
|
+
schedule_to_start_timeout: Some(Duration::from_secs(60)),
|
|
858
|
+
schedule_to_close_timeout,
|
|
859
|
+
..Default::default()
|
|
860
|
+
})
|
|
861
|
+
.await;
|
|
862
|
+
if is_sched_to_start {
|
|
863
|
+
assert!(la_res.completed_ok());
|
|
864
|
+
} else {
|
|
865
|
+
assert_eq!(la_res.timed_out(), Some(TimeoutType::ScheduleToClose));
|
|
866
|
+
}
|
|
867
|
+
Ok(().into())
|
|
868
|
+
},
|
|
869
|
+
);
|
|
870
|
+
worker.register_activity(
|
|
871
|
+
"echo",
|
|
872
|
+
move |_ctx: ActContext, _: String| async move { Ok(()) },
|
|
873
|
+
);
|
|
874
|
+
worker
|
|
875
|
+
.submit_wf(
|
|
876
|
+
wf_id.to_owned(),
|
|
877
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
878
|
+
vec![],
|
|
879
|
+
WorkflowOptions::default(),
|
|
880
|
+
)
|
|
881
|
+
.await
|
|
882
|
+
.unwrap();
|
|
883
|
+
worker.run_until_done().await.unwrap();
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
#[tokio::test]
|
|
887
|
+
async fn wft_failure_cancels_running_las() {
|
|
888
|
+
let mut t = TestHistoryBuilder::default();
|
|
889
|
+
t.add_wfe_started_with_wft_timeout(Duration::from_millis(200));
|
|
890
|
+
t.add_full_wf_task();
|
|
891
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
892
|
+
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
893
|
+
t.add_workflow_task_scheduled_and_started();
|
|
894
|
+
|
|
895
|
+
let wf_id = "fakeid";
|
|
896
|
+
let mock = mock_workflow_client();
|
|
897
|
+
let mut mh = MockPollCfg::from_resp_batches(wf_id, t, [1, 2], mock);
|
|
898
|
+
mh.num_expected_fails = 1;
|
|
899
|
+
let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 1);
|
|
900
|
+
|
|
901
|
+
worker.register_wf(
|
|
902
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
903
|
+
|ctx: WfContext| async move {
|
|
904
|
+
let la_handle = ctx.local_activity(LocalActivityOptions {
|
|
905
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
906
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
907
|
+
..Default::default()
|
|
908
|
+
});
|
|
909
|
+
tokio::join!(
|
|
910
|
+
async {
|
|
911
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
912
|
+
panic!("ahhh I'm failing wft")
|
|
913
|
+
},
|
|
914
|
+
la_handle
|
|
915
|
+
);
|
|
916
|
+
Ok(().into())
|
|
917
|
+
},
|
|
918
|
+
);
|
|
919
|
+
worker.register_activity(
|
|
920
|
+
DEFAULT_ACTIVITY_TYPE,
|
|
921
|
+
move |ctx: ActContext, _: String| async move {
|
|
922
|
+
let res = tokio::time::timeout(Duration::from_millis(500), ctx.cancelled()).await;
|
|
923
|
+
if res.is_err() {
|
|
924
|
+
panic!("Activity must be cancelled!!!!");
|
|
925
|
+
}
|
|
926
|
+
Result::<(), _>::Err(ActivityCancelledError::default().into())
|
|
927
|
+
},
|
|
928
|
+
);
|
|
929
|
+
worker
|
|
930
|
+
.submit_wf(
|
|
931
|
+
wf_id.to_owned(),
|
|
932
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
933
|
+
vec![],
|
|
934
|
+
WorkflowOptions::default(),
|
|
935
|
+
)
|
|
936
|
+
.await
|
|
937
|
+
.unwrap();
|
|
938
|
+
worker.run_until_done().await.unwrap();
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
#[tokio::test]
|
|
942
|
+
async fn resolved_las_not_recorded_if_wft_fails_many_times() {
|
|
943
|
+
// We shouldn't record any LA results if the workflow activation is repeatedly failing. There
|
|
944
|
+
// was an issue that, because we stop reporting WFT failures after 2 tries, this meant the WFT
|
|
945
|
+
// was not marked as "completed" and the WFT could accidentally be replied to with LA results.
|
|
946
|
+
let mut t = TestHistoryBuilder::default();
|
|
947
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
948
|
+
t.add_workflow_task_scheduled_and_started();
|
|
949
|
+
t.add_workflow_task_failed_with_failure(
|
|
950
|
+
WorkflowTaskFailedCause::Unspecified,
|
|
951
|
+
Default::default(),
|
|
952
|
+
);
|
|
953
|
+
t.add_workflow_task_scheduled_and_started();
|
|
954
|
+
|
|
955
|
+
let wf_id = "fakeid";
|
|
956
|
+
let mock = mock_workflow_client();
|
|
957
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
958
|
+
wf_id,
|
|
959
|
+
t,
|
|
960
|
+
[1.into(), ResponseType::AllHistory, ResponseType::AllHistory],
|
|
961
|
+
mock,
|
|
962
|
+
);
|
|
963
|
+
mh.num_expected_fails = 2;
|
|
964
|
+
mh.num_expected_completions = Some(0.into());
|
|
965
|
+
let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 1);
|
|
966
|
+
|
|
967
|
+
worker.register_wf(
|
|
968
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
969
|
+
|ctx: WfContext| async move {
|
|
970
|
+
ctx.local_activity(LocalActivityOptions {
|
|
971
|
+
activity_type: "echo".to_string(),
|
|
972
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
973
|
+
..Default::default()
|
|
974
|
+
})
|
|
975
|
+
.await;
|
|
976
|
+
panic!("Oh nooooo")
|
|
977
|
+
},
|
|
978
|
+
);
|
|
979
|
+
worker.register_activity(
|
|
980
|
+
"echo",
|
|
981
|
+
move |_: ActContext, _: String| async move { Ok(()) },
|
|
982
|
+
);
|
|
983
|
+
worker
|
|
984
|
+
.submit_wf(
|
|
985
|
+
wf_id.to_owned(),
|
|
986
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
987
|
+
vec![],
|
|
988
|
+
WorkflowOptions::default(),
|
|
989
|
+
)
|
|
990
|
+
.await
|
|
991
|
+
.unwrap();
|
|
992
|
+
worker.run_until_done().await.unwrap();
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
#[tokio::test]
|
|
996
|
+
async fn local_act_records_nonfirst_attempts_ok() {
|
|
997
|
+
let mut t = TestHistoryBuilder::default();
|
|
998
|
+
let wft_timeout = Duration::from_millis(200);
|
|
999
|
+
t.add_wfe_started_with_wft_timeout(wft_timeout);
|
|
1000
|
+
t.add_full_wf_task();
|
|
1001
|
+
t.add_full_wf_task();
|
|
1002
|
+
t.add_full_wf_task();
|
|
1003
|
+
t.add_workflow_task_scheduled_and_started();
|
|
1004
|
+
|
|
1005
|
+
let wf_id = "fakeid";
|
|
1006
|
+
let mock = mock_workflow_client();
|
|
1007
|
+
let mut mh = MockPollCfg::from_resp_batches(wf_id, t, [1, 2, 3], mock);
|
|
1008
|
+
let nonfirst_counts = Arc::new(SegQueue::new());
|
|
1009
|
+
let nfc_c = nonfirst_counts.clone();
|
|
1010
|
+
mh.completion_asserts = Some(Box::new(move |c| {
|
|
1011
|
+
nfc_c.push(
|
|
1012
|
+
c.metering_metadata
|
|
1013
|
+
.nonfirst_local_activity_execution_attempts,
|
|
1014
|
+
);
|
|
1015
|
+
}));
|
|
1016
|
+
let mut worker = mock_sdk_cfg(mh, |wc| {
|
|
1017
|
+
wc.max_cached_workflows = 1;
|
|
1018
|
+
wc.max_outstanding_workflow_tasks = 1;
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
worker.register_wf(
|
|
1022
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
1023
|
+
|ctx: WfContext| async move {
|
|
1024
|
+
ctx.local_activity(LocalActivityOptions {
|
|
1025
|
+
activity_type: "echo".to_string(),
|
|
1026
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
1027
|
+
retry_policy: RetryPolicy {
|
|
1028
|
+
initial_interval: Some(prost_dur!(from_millis(10))),
|
|
1029
|
+
backoff_coefficient: 1.0,
|
|
1030
|
+
maximum_interval: None,
|
|
1031
|
+
maximum_attempts: 0,
|
|
1032
|
+
non_retryable_error_types: vec![],
|
|
1033
|
+
},
|
|
1034
|
+
..Default::default()
|
|
1035
|
+
})
|
|
1036
|
+
.await;
|
|
1037
|
+
Ok(().into())
|
|
1038
|
+
},
|
|
1039
|
+
);
|
|
1040
|
+
worker.register_activity("echo", move |_ctx: ActContext, _: String| async move {
|
|
1041
|
+
Result::<(), _>::Err(anyhow!("I fail"))
|
|
1042
|
+
});
|
|
1043
|
+
worker
|
|
1044
|
+
.submit_wf(
|
|
1045
|
+
wf_id.to_owned(),
|
|
1046
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
1047
|
+
vec![],
|
|
1048
|
+
WorkflowOptions::default(),
|
|
1049
|
+
)
|
|
1050
|
+
.await
|
|
1051
|
+
.unwrap();
|
|
1052
|
+
worker.run_until_done().await.unwrap();
|
|
1053
|
+
// 3 workflow tasks
|
|
1054
|
+
assert_eq!(nonfirst_counts.len(), 3);
|
|
1055
|
+
// First task's non-first count should, of course, be 0
|
|
1056
|
+
assert_eq!(nonfirst_counts.pop().unwrap(), 0);
|
|
1057
|
+
// Next two, some nonzero amount which could vary based on test load
|
|
1058
|
+
assert!(nonfirst_counts.pop().unwrap() > 0);
|
|
1059
|
+
assert!(nonfirst_counts.pop().unwrap() > 0);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
#[tokio::test]
|
|
1063
|
+
async fn local_activities_can_be_delivered_during_shutdown() {
|
|
1064
|
+
let wfid = "fake_wf_id";
|
|
1065
|
+
let mut t = TestHistoryBuilder::default();
|
|
1066
|
+
t.add_wfe_started_with_wft_timeout(Duration::from_millis(200));
|
|
1067
|
+
t.add_full_wf_task();
|
|
1068
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
1069
|
+
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
1070
|
+
t.add_workflow_task_scheduled_and_started();
|
|
1071
|
+
|
|
1072
|
+
let mock = mock_workflow_client();
|
|
1073
|
+
let mut mock = single_hist_mock_sg(
|
|
1074
|
+
wfid,
|
|
1075
|
+
t,
|
|
1076
|
+
[ResponseType::ToTaskNum(1), ResponseType::AllHistory],
|
|
1077
|
+
mock,
|
|
1078
|
+
true,
|
|
1079
|
+
);
|
|
1080
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
|
|
1081
|
+
let core = mock_worker(mock);
|
|
1082
|
+
|
|
1083
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
1084
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1085
|
+
task.run_id,
|
|
1086
|
+
start_timer_cmd(1, Duration::from_secs(1)),
|
|
1087
|
+
))
|
|
1088
|
+
.await
|
|
1089
|
+
.unwrap();
|
|
1090
|
+
|
|
1091
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
1092
|
+
// Initiate shutdown once we have the WF activation, but before replying that we want to do an
|
|
1093
|
+
// LA
|
|
1094
|
+
core.initiate_shutdown();
|
|
1095
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
1096
|
+
task.run_id,
|
|
1097
|
+
ScheduleLocalActivity {
|
|
1098
|
+
seq: 1,
|
|
1099
|
+
activity_id: "1".to_string(),
|
|
1100
|
+
activity_type: "test_act".to_string(),
|
|
1101
|
+
start_to_close_timeout: Some(prost_dur!(from_secs(30))),
|
|
1102
|
+
..Default::default()
|
|
1103
|
+
}
|
|
1104
|
+
.into(),
|
|
1105
|
+
))
|
|
1106
|
+
.await
|
|
1107
|
+
.unwrap();
|
|
1108
|
+
|
|
1109
|
+
let wf_poller = async { core.poll_workflow_activation().await };
|
|
1110
|
+
|
|
1111
|
+
let at_poller = async {
|
|
1112
|
+
let act_task = core.poll_activity_task().await.unwrap();
|
|
1113
|
+
core.complete_activity_task(ActivityTaskCompletion {
|
|
1114
|
+
task_token: act_task.task_token,
|
|
1115
|
+
result: Some(ActivityExecutionResult::ok(vec![1].into())),
|
|
1116
|
+
})
|
|
1117
|
+
.await
|
|
1118
|
+
.unwrap();
|
|
1119
|
+
core.poll_activity_task().await
|
|
1120
|
+
};
|
|
1121
|
+
|
|
1122
|
+
let (wf_r, act_r) = join!(wf_poller, at_poller);
|
|
1123
|
+
assert_matches!(wf_r.unwrap_err(), PollWfError::ShutDown);
|
|
1124
|
+
assert_matches!(act_r.unwrap_err(), PollActivityError::ShutDown);
|
|
1125
|
+
}
|