@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
|
@@ -4,7 +4,7 @@ use crate::{
|
|
|
4
4
|
build_fake_worker, build_mock_pollers, canned_histories, gen_assert_and_reply,
|
|
5
5
|
mock_manual_poller, mock_poller, mock_poller_from_resps, mock_worker, poll_and_reply,
|
|
6
6
|
single_hist_mock_sg, test_worker_cfg, MockPollCfg, MockWorkerInputs, MocksHolder,
|
|
7
|
-
ResponseType, WorkflowCachingPolicy, TEST_Q,
|
|
7
|
+
QueueResponse, ResponseType, WorkerExt, WorkflowCachingPolicy, TEST_Q,
|
|
8
8
|
},
|
|
9
9
|
worker::client::mocks::{mock_manual_workflow_client, mock_workflow_client},
|
|
10
10
|
ActivityHeartbeat, Worker, WorkerConfigBuilder,
|
|
@@ -13,7 +13,8 @@ use futures::FutureExt;
|
|
|
13
13
|
use itertools::Itertools;
|
|
14
14
|
use std::{
|
|
15
15
|
cell::RefCell,
|
|
16
|
-
collections::{hash_map::Entry, HashMap, VecDeque},
|
|
16
|
+
collections::{hash_map::Entry, HashMap, HashSet, VecDeque},
|
|
17
|
+
future,
|
|
17
18
|
rc::Rc,
|
|
18
19
|
sync::{
|
|
19
20
|
atomic::{AtomicUsize, Ordering},
|
|
@@ -23,15 +24,17 @@ use std::{
|
|
|
23
24
|
};
|
|
24
25
|
use temporal_client::WorkflowOptions;
|
|
25
26
|
use temporal_sdk::{ActivityOptions, WfContext};
|
|
26
|
-
use temporal_sdk_core_api::{
|
|
27
|
-
|
|
27
|
+
use temporal_sdk_core_api::{
|
|
28
|
+
errors::{CompleteActivityError, PollActivityError},
|
|
29
|
+
Worker as WorkerTrait,
|
|
30
|
+
};
|
|
28
31
|
use temporal_sdk_core_protos::{
|
|
29
32
|
coresdk::{
|
|
30
33
|
activity_result::{
|
|
31
34
|
activity_execution_result, activity_resolution, ActivityExecutionResult,
|
|
32
35
|
ActivityResolution, Success,
|
|
33
36
|
},
|
|
34
|
-
activity_task::{activity_task, ActivityTask},
|
|
37
|
+
activity_task::{activity_task, ActivityCancelReason, ActivityTask, Cancel},
|
|
35
38
|
workflow_activation::{workflow_activation_job, ResolveActivity, WorkflowActivationJob},
|
|
36
39
|
workflow_commands::{
|
|
37
40
|
ActivityCancellationType, CompleteWorkflowExecution, RequestCancelActivity,
|
|
@@ -41,8 +44,11 @@ use temporal_sdk_core_protos::{
|
|
|
41
44
|
ActivityTaskCompletion,
|
|
42
45
|
},
|
|
43
46
|
temporal::api::{
|
|
44
|
-
command::v1::command::Attributes,
|
|
47
|
+
command::v1::{command::Attributes, ScheduleActivityTaskCommandAttributes},
|
|
45
48
|
enums::v1::EventType,
|
|
49
|
+
history::v1::{
|
|
50
|
+
history_event::Attributes as EventAttributes, ActivityTaskScheduledEventAttributes,
|
|
51
|
+
},
|
|
46
52
|
workflowservice::v1::{
|
|
47
53
|
PollActivityTaskQueueResponse, RecordActivityTaskHeartbeatResponse,
|
|
48
54
|
RespondActivityTaskCanceledResponse, RespondActivityTaskCompletedResponse,
|
|
@@ -53,11 +59,10 @@ use temporal_sdk_core_protos::{
|
|
|
53
59
|
};
|
|
54
60
|
use temporal_sdk_core_test_utils::{fanout_tasks, start_timer_cmd, TestWorker};
|
|
55
61
|
use tokio::{sync::Barrier, time::sleep};
|
|
62
|
+
use tokio_util::sync::CancellationToken;
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let _task_q = "q";
|
|
60
|
-
let mut tasks = VecDeque::from(vec![
|
|
64
|
+
fn three_tasks() -> VecDeque<PollActivityTaskQueueResponse> {
|
|
65
|
+
VecDeque::from(vec![
|
|
61
66
|
PollActivityTaskQueueResponse {
|
|
62
67
|
task_token: vec![1],
|
|
63
68
|
activity_id: "act1".to_string(),
|
|
@@ -73,7 +78,13 @@ async fn max_activities_respected() {
|
|
|
73
78
|
activity_id: "act3".to_string(),
|
|
74
79
|
..Default::default()
|
|
75
80
|
},
|
|
76
|
-
])
|
|
81
|
+
])
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#[tokio::test]
|
|
85
|
+
async fn max_activities_respected() {
|
|
86
|
+
let _task_q = "q";
|
|
87
|
+
let mut tasks = three_tasks();
|
|
77
88
|
let mut mock_client = mock_workflow_client();
|
|
78
89
|
mock_client
|
|
79
90
|
.expect_poll_activity_task()
|
|
@@ -122,7 +133,7 @@ async fn activity_not_found_returns_ok() {
|
|
|
122
133
|
})
|
|
123
134
|
.await
|
|
124
135
|
.unwrap();
|
|
125
|
-
core.
|
|
136
|
+
core.drain_activity_poller_and_shutdown().await;
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
#[tokio::test]
|
|
@@ -218,12 +229,14 @@ async fn heartbeats_report_cancels_only_once() {
|
|
|
218
229
|
})
|
|
219
230
|
.await
|
|
220
231
|
.unwrap();
|
|
221
|
-
core.
|
|
232
|
+
core.drain_activity_poller_and_shutdown().await;
|
|
222
233
|
}
|
|
223
234
|
|
|
224
235
|
#[tokio::test]
|
|
225
236
|
async fn activity_cancel_interrupts_poll() {
|
|
226
237
|
let mut mock_poller = mock_manual_poller();
|
|
238
|
+
let shutdown_token = CancellationToken::new();
|
|
239
|
+
let shutdown_token_clone = shutdown_token.clone();
|
|
227
240
|
let mut poll_resps = VecDeque::from(vec![
|
|
228
241
|
async {
|
|
229
242
|
Some(Ok(PollActivityTaskQueueResponse {
|
|
@@ -238,10 +251,15 @@ async fn activity_cancel_interrupts_poll() {
|
|
|
238
251
|
Some(Ok(Default::default()))
|
|
239
252
|
}
|
|
240
253
|
.boxed(),
|
|
254
|
+
async move {
|
|
255
|
+
shutdown_token.cancelled().await;
|
|
256
|
+
None
|
|
257
|
+
}
|
|
258
|
+
.boxed(),
|
|
241
259
|
]);
|
|
242
260
|
mock_poller
|
|
243
261
|
.expect_poll()
|
|
244
|
-
.times(
|
|
262
|
+
.times(3)
|
|
245
263
|
.returning(move || poll_resps.pop_front().unwrap());
|
|
246
264
|
|
|
247
265
|
let mut mock_client = mock_manual_workflow_client();
|
|
@@ -290,11 +308,12 @@ async fn activity_cancel_interrupts_poll() {
|
|
|
290
308
|
}
|
|
291
309
|
).await.unwrap();
|
|
292
310
|
last_finisher.store(2, Ordering::SeqCst);
|
|
311
|
+
shutdown_token_clone.cancel();
|
|
293
312
|
}
|
|
294
313
|
};
|
|
295
314
|
// So that we know we blocked
|
|
296
315
|
assert_eq!(last_finisher.load(Ordering::Acquire), 2);
|
|
297
|
-
core.
|
|
316
|
+
core.drain_activity_poller_and_shutdown().await;
|
|
298
317
|
}
|
|
299
318
|
|
|
300
319
|
#[tokio::test]
|
|
@@ -343,13 +362,10 @@ async fn many_concurrent_heartbeat_cancels() {
|
|
|
343
362
|
})
|
|
344
363
|
.collect::<Vec<_>>(),
|
|
345
364
|
);
|
|
346
|
-
// Because the mock is so fast, it's possible it can return before the cancel channel in
|
|
347
|
-
// the activity task poll selector. So, the final poll when there are no more tasks must
|
|
348
|
-
// take a while.
|
|
349
365
|
poll_resps.push_back(
|
|
350
366
|
async {
|
|
351
|
-
|
|
352
|
-
unreachable!(
|
|
367
|
+
future::pending::<()>().await;
|
|
368
|
+
unreachable!()
|
|
353
369
|
}
|
|
354
370
|
.boxed(),
|
|
355
371
|
);
|
|
@@ -432,7 +448,7 @@ async fn many_concurrent_heartbeat_cancels() {
|
|
|
432
448
|
})
|
|
433
449
|
.await;
|
|
434
450
|
|
|
435
|
-
worker.
|
|
451
|
+
worker.drain_activity_poller_and_shutdown().await;
|
|
436
452
|
}
|
|
437
453
|
|
|
438
454
|
#[tokio::test]
|
|
@@ -484,7 +500,7 @@ async fn activity_timeout_no_double_resolve() {
|
|
|
484
500
|
)
|
|
485
501
|
.await;
|
|
486
502
|
|
|
487
|
-
core.
|
|
503
|
+
core.drain_pollers_and_shutdown().await;
|
|
488
504
|
}
|
|
489
505
|
|
|
490
506
|
#[tokio::test]
|
|
@@ -530,7 +546,7 @@ async fn can_heartbeat_acts_during_shutdown() {
|
|
|
530
546
|
})
|
|
531
547
|
.await
|
|
532
548
|
.unwrap();
|
|
533
|
-
|
|
549
|
+
core.drain_activity_poller_and_shutdown().await;
|
|
534
550
|
}
|
|
535
551
|
|
|
536
552
|
/// Verifies that if a user has tried to record a heartbeat and then immediately after failed the
|
|
@@ -581,7 +597,7 @@ async fn complete_act_with_fail_flushes_heartbeat() {
|
|
|
581
597
|
})
|
|
582
598
|
.await
|
|
583
599
|
.unwrap();
|
|
584
|
-
core.
|
|
600
|
+
core.drain_activity_poller_and_shutdown().await;
|
|
585
601
|
|
|
586
602
|
// Verify the last seen call to record a heartbeat had the last detail payload
|
|
587
603
|
let last_seen_payload = &last_seen_payload.take().unwrap().payloads[0];
|
|
@@ -654,6 +670,7 @@ async fn no_eager_activities_requested_when_worker_options_disable_remote_activi
|
|
|
654
670
|
Ok(RespondWorkflowTaskCompletedResponse {
|
|
655
671
|
workflow_task: None,
|
|
656
672
|
activity_tasks: vec![],
|
|
673
|
+
reset_history_event_id: 0,
|
|
657
674
|
})
|
|
658
675
|
});
|
|
659
676
|
let mut mock = single_hist_mock_sg(wfid, t, [1], mock, true);
|
|
@@ -686,7 +703,7 @@ async fn no_eager_activities_requested_when_worker_options_disable_remote_activi
|
|
|
686
703
|
.await
|
|
687
704
|
.unwrap();
|
|
688
705
|
|
|
689
|
-
core.
|
|
706
|
+
core.drain_pollers_and_shutdown().await;
|
|
690
707
|
|
|
691
708
|
assert_eq!(num_eager_requested.load(Ordering::Relaxed), 0);
|
|
692
709
|
}
|
|
@@ -703,7 +720,7 @@ async fn activity_tasks_from_completion_are_delivered() {
|
|
|
703
720
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
704
721
|
t.add_full_wf_task();
|
|
705
722
|
let act_same_queue_scheduled_ids = (1..4)
|
|
706
|
-
.map(|i| t.add_activity_task_scheduled(format!("act_id_{}_same_queue"
|
|
723
|
+
.map(|i| t.add_activity_task_scheduled(format!("act_id_{i}_same_queue")))
|
|
707
724
|
.collect_vec();
|
|
708
725
|
t.add_activity_task_scheduled("act_id_same_queue_not_eager");
|
|
709
726
|
t.add_activity_task_scheduled("act_id_different_queue");
|
|
@@ -742,21 +759,19 @@ async fn activity_tasks_from_completion_are_delivered() {
|
|
|
742
759
|
activity_tasks: (1..4)
|
|
743
760
|
.map(|i| PollActivityTaskQueueResponse {
|
|
744
761
|
task_token: vec![i],
|
|
745
|
-
activity_id: format!("act_id_{}_same_queue"
|
|
762
|
+
activity_id: format!("act_id_{i}_same_queue"),
|
|
746
763
|
..Default::default()
|
|
747
764
|
})
|
|
748
765
|
.collect_vec(),
|
|
766
|
+
reset_history_event_id: 0,
|
|
749
767
|
})
|
|
750
768
|
});
|
|
751
769
|
mock.expect_complete_activity_task()
|
|
752
770
|
.times(3)
|
|
753
771
|
.returning(|_, _| Ok(RespondActivityTaskCompletedResponse::default()));
|
|
754
772
|
let mut mock = single_hist_mock_sg(wfid, t, [1], mock, true);
|
|
755
|
-
let
|
|
756
|
-
|
|
757
|
-
.expect_poll()
|
|
758
|
-
.returning(|| futures::future::pending().boxed());
|
|
759
|
-
mock.set_act_poller(Box::new(mock_poller));
|
|
773
|
+
let act_tasks: Vec<QueueResponse<PollActivityTaskQueueResponse>> = vec![];
|
|
774
|
+
mock.set_act_poller(mock_poller_from_resps(act_tasks));
|
|
760
775
|
mock.worker_cfg(|wc| wc.max_cached_workflows = 2);
|
|
761
776
|
let core = mock_worker(mock);
|
|
762
777
|
|
|
@@ -766,7 +781,7 @@ async fn activity_tasks_from_completion_are_delivered() {
|
|
|
766
781
|
.map(|seq| {
|
|
767
782
|
ScheduleActivity {
|
|
768
783
|
seq,
|
|
769
|
-
activity_id: format!("act_id_{}_same_queue"
|
|
784
|
+
activity_id: format!("act_id_{seq}_same_queue"),
|
|
770
785
|
task_queue: TEST_Q.to_string(),
|
|
771
786
|
cancellation_type: ActivityCancellationType::TryCancel as i32,
|
|
772
787
|
..Default::default()
|
|
@@ -815,7 +830,7 @@ async fn activity_tasks_from_completion_are_delivered() {
|
|
|
815
830
|
.unwrap();
|
|
816
831
|
}
|
|
817
832
|
|
|
818
|
-
core.
|
|
833
|
+
core.drain_pollers_and_shutdown().await;
|
|
819
834
|
|
|
820
835
|
// Verify only a single eager activity was scheduled (the one on our worker's task queue)
|
|
821
836
|
assert_eq!(num_eager_requested.load(Ordering::Relaxed), 3);
|
|
@@ -827,11 +842,23 @@ async fn activity_tasks_from_completion_reserve_slots() {
|
|
|
827
842
|
let mut t = TestHistoryBuilder::default();
|
|
828
843
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
829
844
|
t.add_full_wf_task();
|
|
830
|
-
let schedid = t.
|
|
845
|
+
let schedid = t.add(EventAttributes::ActivityTaskScheduledEventAttributes(
|
|
846
|
+
ActivityTaskScheduledEventAttributes {
|
|
847
|
+
activity_id: "1".to_string(),
|
|
848
|
+
activity_type: Some("act1".into()),
|
|
849
|
+
..Default::default()
|
|
850
|
+
},
|
|
851
|
+
));
|
|
831
852
|
let startid = t.add_activity_task_started(schedid);
|
|
832
853
|
t.add_activity_task_completed(schedid, startid, b"hi".into());
|
|
833
854
|
t.add_full_wf_task();
|
|
834
|
-
let schedid = t.
|
|
855
|
+
let schedid = t.add(EventAttributes::ActivityTaskScheduledEventAttributes(
|
|
856
|
+
ActivityTaskScheduledEventAttributes {
|
|
857
|
+
activity_id: "2".to_string(),
|
|
858
|
+
activity_type: Some("act2".into()),
|
|
859
|
+
..Default::default()
|
|
860
|
+
},
|
|
861
|
+
));
|
|
835
862
|
let startid = t.add_activity_task_started(schedid);
|
|
836
863
|
t.add_activity_task_completed(schedid, startid, b"hi".into());
|
|
837
864
|
t.add_full_wf_task();
|
|
@@ -901,19 +928,25 @@ async fn activity_tasks_from_completion_reserve_slots() {
|
|
|
901
928
|
// First poll for activities twice, occupying both slots
|
|
902
929
|
let at1 = core.poll_activity_task().await.unwrap();
|
|
903
930
|
let at2 = core.poll_activity_task().await.unwrap();
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
931
|
+
let workflow_complete_token = CancellationToken::new();
|
|
932
|
+
let workflow_complete_token_clone = workflow_complete_token.clone();
|
|
933
|
+
|
|
934
|
+
worker.register_wf(DEFAULT_WORKFLOW_TYPE, move |ctx: WfContext| {
|
|
935
|
+
let complete_token = workflow_complete_token.clone();
|
|
936
|
+
async move {
|
|
937
|
+
ctx.activity(ActivityOptions {
|
|
938
|
+
activity_type: "act1".to_string(),
|
|
939
|
+
..Default::default()
|
|
940
|
+
})
|
|
941
|
+
.await;
|
|
942
|
+
ctx.activity(ActivityOptions {
|
|
943
|
+
activity_type: "act2".to_string(),
|
|
944
|
+
..Default::default()
|
|
945
|
+
})
|
|
946
|
+
.await;
|
|
947
|
+
complete_token.cancel();
|
|
948
|
+
Ok(().into())
|
|
949
|
+
}
|
|
917
950
|
});
|
|
918
951
|
|
|
919
952
|
worker
|
|
@@ -940,6 +973,13 @@ async fn activity_tasks_from_completion_reserve_slots() {
|
|
|
940
973
|
.await
|
|
941
974
|
.unwrap();
|
|
942
975
|
barr.wait().await;
|
|
976
|
+
// Wait for workflow to complete in order for all eager activities to be requested before shutting down.
|
|
977
|
+
// After shutdown, no eager activities slots can be allocated.
|
|
978
|
+
workflow_complete_token_clone.cancelled().await;
|
|
979
|
+
core.initiate_shutdown();
|
|
980
|
+
// Even though this test requests eager activity tasks, none are returned in poll responses.
|
|
981
|
+
let err = core.poll_activity_task().await.unwrap_err();
|
|
982
|
+
assert_matches!(err, PollActivityError::ShutDown);
|
|
943
983
|
};
|
|
944
984
|
// This wf poll should *not* set the flag that it wants tasks back since both slots are
|
|
945
985
|
// occupied
|
|
@@ -973,7 +1013,7 @@ async fn retryable_net_error_exhaustion_is_nonfatal() {
|
|
|
973
1013
|
})
|
|
974
1014
|
.await
|
|
975
1015
|
.unwrap();
|
|
976
|
-
core.
|
|
1016
|
+
core.drain_activity_poller_and_shutdown().await;
|
|
977
1017
|
}
|
|
978
1018
|
|
|
979
1019
|
#[tokio::test]
|
|
@@ -1011,3 +1051,56 @@ async fn cant_complete_activity_with_unset_result_payload() {
|
|
|
1011
1051
|
Err(CompleteActivityError::MalformedActivityCompletion { .. })
|
|
1012
1052
|
)
|
|
1013
1053
|
}
|
|
1054
|
+
|
|
1055
|
+
#[tokio::test]
|
|
1056
|
+
async fn graceful_shutdown() {
|
|
1057
|
+
let _task_q = "q";
|
|
1058
|
+
let mut tasks = three_tasks();
|
|
1059
|
+
let mut mock_client = mock_workflow_client();
|
|
1060
|
+
mock_client
|
|
1061
|
+
.expect_poll_activity_task()
|
|
1062
|
+
.times(3)
|
|
1063
|
+
.returning(move |_, _| Ok(tasks.pop_front().unwrap()));
|
|
1064
|
+
// They shall all be reported as failed
|
|
1065
|
+
mock_client
|
|
1066
|
+
.expect_fail_activity_task()
|
|
1067
|
+
.times(3)
|
|
1068
|
+
.returning(|_, _| Ok(Default::default()));
|
|
1069
|
+
|
|
1070
|
+
let worker = Worker::new_test(
|
|
1071
|
+
test_worker_cfg()
|
|
1072
|
+
.graceful_shutdown_period(Duration::from_millis(500))
|
|
1073
|
+
.build()
|
|
1074
|
+
.unwrap(),
|
|
1075
|
+
mock_client,
|
|
1076
|
+
);
|
|
1077
|
+
|
|
1078
|
+
let _1 = worker.poll_activity_task().await.unwrap();
|
|
1079
|
+
let _2 = worker.poll_activity_task().await.unwrap();
|
|
1080
|
+
let _3 = worker.poll_activity_task().await.unwrap();
|
|
1081
|
+
|
|
1082
|
+
worker.initiate_shutdown();
|
|
1083
|
+
let expected_tts = HashSet::from([vec![1], vec![2], vec![3]]);
|
|
1084
|
+
let mut seen_tts = HashSet::new();
|
|
1085
|
+
for _ in 1..=3 {
|
|
1086
|
+
let cancel = worker.poll_activity_task().await.unwrap();
|
|
1087
|
+
assert_matches!(
|
|
1088
|
+
cancel.variant,
|
|
1089
|
+
Some(activity_task::Variant::Cancel(Cancel {
|
|
1090
|
+
reason: r
|
|
1091
|
+
})) if r == ActivityCancelReason::WorkerShutdown as i32
|
|
1092
|
+
);
|
|
1093
|
+
seen_tts.insert(cancel.task_token);
|
|
1094
|
+
}
|
|
1095
|
+
assert_eq!(expected_tts, seen_tts);
|
|
1096
|
+
for tt in seen_tts {
|
|
1097
|
+
worker
|
|
1098
|
+
.complete_activity_task(ActivityTaskCompletion {
|
|
1099
|
+
task_token: tt,
|
|
1100
|
+
result: Some(ActivityExecutionResult::cancel_from_details(None)),
|
|
1101
|
+
})
|
|
1102
|
+
.await
|
|
1103
|
+
.unwrap();
|
|
1104
|
+
}
|
|
1105
|
+
worker.drain_pollers_and_shutdown().await;
|
|
1106
|
+
}
|
|
@@ -88,11 +88,12 @@ async fn parent_cancels_child_wf(ctx: WfContext) -> WorkflowResult<()> {
|
|
|
88
88
|
.await
|
|
89
89
|
.into_started()
|
|
90
90
|
.expect("Child should get started");
|
|
91
|
-
|
|
92
|
-
let
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
start_res.cancel(&ctx);
|
|
92
|
+
let stat = start_res
|
|
93
|
+
.result()
|
|
94
|
+
.await
|
|
95
|
+
.status
|
|
96
|
+
.expect("child wf result is ok");
|
|
96
97
|
assert_matches!(stat, child_workflow_result::Status::Cancelled(_));
|
|
97
98
|
Ok(().into())
|
|
98
99
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
use crate::{
|
|
2
|
+
internal_flags::CoreInternalFlags,
|
|
2
3
|
replay::DEFAULT_WORKFLOW_TYPE,
|
|
3
4
|
test_help::{canned_histories, mock_sdk, mock_sdk_cfg, MockPollCfg, ResponseType},
|
|
4
5
|
worker::client::mocks::mock_workflow_client,
|
|
@@ -8,8 +9,13 @@ use std::{
|
|
|
8
9
|
time::Duration,
|
|
9
10
|
};
|
|
10
11
|
use temporal_client::WorkflowOptions;
|
|
11
|
-
use temporal_sdk::{
|
|
12
|
-
|
|
12
|
+
use temporal_sdk::{
|
|
13
|
+
ActivityOptions, ChildWorkflowOptions, LocalActivityOptions, WfContext, WorkflowResult,
|
|
14
|
+
};
|
|
15
|
+
use temporal_sdk_core_protos::{
|
|
16
|
+
temporal::api::{enums::v1::WorkflowTaskFailedCause, failure::v1::Failure},
|
|
17
|
+
DEFAULT_ACTIVITY_TYPE,
|
|
18
|
+
};
|
|
13
19
|
|
|
14
20
|
static DID_FAIL: AtomicBool = AtomicBool::new(false);
|
|
15
21
|
pub async fn timer_wf_fails_once(ctx: WfContext) -> WorkflowResult<()> {
|
|
@@ -105,3 +111,160 @@ async fn test_wf_task_rejected_properly_due_to_nondeterminism(#[case] use_cache:
|
|
|
105
111
|
// timer and proceed without restarting
|
|
106
112
|
assert_eq!(2, started_count.load(Ordering::Relaxed));
|
|
107
113
|
}
|
|
114
|
+
|
|
115
|
+
#[rstest::rstest]
|
|
116
|
+
#[tokio::test]
|
|
117
|
+
async fn activity_id_or_type_change_is_nondeterministic(
|
|
118
|
+
#[values(true, false)] use_cache: bool,
|
|
119
|
+
#[values(true, false)] id_change: bool,
|
|
120
|
+
#[values(true, false)] local_act: bool,
|
|
121
|
+
) {
|
|
122
|
+
let wf_id = "fakeid";
|
|
123
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
124
|
+
let mut t = if local_act {
|
|
125
|
+
canned_histories::single_local_activity("1")
|
|
126
|
+
} else {
|
|
127
|
+
canned_histories::single_activity("1")
|
|
128
|
+
};
|
|
129
|
+
t.set_flags_first_wft(&[CoreInternalFlags::IdAndTypeDeterminismChecks as u32], &[]);
|
|
130
|
+
let mock = mock_workflow_client();
|
|
131
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
132
|
+
wf_id,
|
|
133
|
+
t,
|
|
134
|
+
// Two polls are needed, since the first will fail
|
|
135
|
+
[ResponseType::AllHistory, ResponseType::AllHistory],
|
|
136
|
+
mock,
|
|
137
|
+
);
|
|
138
|
+
// We should see one wft failure which has nondeterminism cause
|
|
139
|
+
mh.num_expected_fails = 1;
|
|
140
|
+
mh.expect_fail_wft_matcher = Box::new(move |_, cause, f| {
|
|
141
|
+
let should_contain = if id_change {
|
|
142
|
+
"does not match activity id"
|
|
143
|
+
} else {
|
|
144
|
+
"does not match activity type"
|
|
145
|
+
};
|
|
146
|
+
matches!(cause, WorkflowTaskFailedCause::NonDeterministicError)
|
|
147
|
+
&& matches!(f, Some(Failure {
|
|
148
|
+
message,
|
|
149
|
+
..
|
|
150
|
+
}) if message.contains(should_contain))
|
|
151
|
+
});
|
|
152
|
+
let mut worker = mock_sdk_cfg(mh, |cfg| {
|
|
153
|
+
if use_cache {
|
|
154
|
+
cfg.max_cached_workflows = 2;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
|
|
159
|
+
if local_act {
|
|
160
|
+
ctx.local_activity(if id_change {
|
|
161
|
+
LocalActivityOptions {
|
|
162
|
+
activity_id: Some("I'm bad and wrong!".to_string()),
|
|
163
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
164
|
+
..Default::default()
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
LocalActivityOptions {
|
|
168
|
+
activity_type: "not the default act type".to_string(),
|
|
169
|
+
..Default::default()
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
.await;
|
|
173
|
+
} else {
|
|
174
|
+
ctx.activity(if id_change {
|
|
175
|
+
ActivityOptions {
|
|
176
|
+
activity_id: Some("I'm bad and wrong!".to_string()),
|
|
177
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
178
|
+
..Default::default()
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
ActivityOptions {
|
|
182
|
+
activity_type: "not the default act type".to_string(),
|
|
183
|
+
..Default::default()
|
|
184
|
+
}
|
|
185
|
+
})
|
|
186
|
+
.await;
|
|
187
|
+
}
|
|
188
|
+
Ok(().into())
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
worker
|
|
192
|
+
.submit_wf(
|
|
193
|
+
wf_id.to_owned(),
|
|
194
|
+
wf_type.to_owned(),
|
|
195
|
+
vec![],
|
|
196
|
+
WorkflowOptions::default(),
|
|
197
|
+
)
|
|
198
|
+
.await
|
|
199
|
+
.unwrap();
|
|
200
|
+
worker.run_until_done().await.unwrap();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
#[rstest::rstest]
|
|
204
|
+
#[tokio::test]
|
|
205
|
+
async fn child_wf_id_or_type_change_is_nondeterministic(
|
|
206
|
+
#[values(true, false)] use_cache: bool,
|
|
207
|
+
#[values(true, false)] id_change: bool,
|
|
208
|
+
) {
|
|
209
|
+
let wf_id = "fakeid";
|
|
210
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
211
|
+
let mut t = canned_histories::single_child_workflow("1");
|
|
212
|
+
t.set_flags_first_wft(&[CoreInternalFlags::IdAndTypeDeterminismChecks as u32], &[]);
|
|
213
|
+
let mock = mock_workflow_client();
|
|
214
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
215
|
+
wf_id,
|
|
216
|
+
t,
|
|
217
|
+
// Two polls are needed, since the first will fail
|
|
218
|
+
[ResponseType::AllHistory, ResponseType::AllHistory],
|
|
219
|
+
mock,
|
|
220
|
+
);
|
|
221
|
+
// We should see one wft failure which has nondeterminism cause
|
|
222
|
+
mh.num_expected_fails = 1;
|
|
223
|
+
mh.expect_fail_wft_matcher = Box::new(move |_, cause, f| {
|
|
224
|
+
let should_contain = if id_change {
|
|
225
|
+
"does not match child workflow id"
|
|
226
|
+
} else {
|
|
227
|
+
"does not match child workflow type"
|
|
228
|
+
};
|
|
229
|
+
matches!(cause, WorkflowTaskFailedCause::NonDeterministicError)
|
|
230
|
+
&& matches!(f, Some(Failure {
|
|
231
|
+
message,
|
|
232
|
+
..
|
|
233
|
+
}) if message.contains(should_contain))
|
|
234
|
+
});
|
|
235
|
+
let mut worker = mock_sdk_cfg(mh, |cfg| {
|
|
236
|
+
if use_cache {
|
|
237
|
+
cfg.max_cached_workflows = 2;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
|
|
242
|
+
ctx.child_workflow(if id_change {
|
|
243
|
+
ChildWorkflowOptions {
|
|
244
|
+
workflow_id: "I'm bad and wrong!".to_string(),
|
|
245
|
+
workflow_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
246
|
+
..Default::default()
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
ChildWorkflowOptions {
|
|
250
|
+
workflow_id: "1".to_string(),
|
|
251
|
+
workflow_type: "not the child wf type".to_string(),
|
|
252
|
+
..Default::default()
|
|
253
|
+
}
|
|
254
|
+
})
|
|
255
|
+
.start(&ctx)
|
|
256
|
+
.await;
|
|
257
|
+
Ok(().into())
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
worker
|
|
261
|
+
.submit_wf(
|
|
262
|
+
wf_id.to_owned(),
|
|
263
|
+
wf_type.to_owned(),
|
|
264
|
+
vec![],
|
|
265
|
+
WorkflowOptions::default(),
|
|
266
|
+
)
|
|
267
|
+
.await
|
|
268
|
+
.unwrap();
|
|
269
|
+
worker.run_until_done().await.unwrap();
|
|
270
|
+
}
|