@temporalio/core-bridge 1.14.2-canary-release-testing.0 → 1.16.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 +794 -650
- package/bridge-macros/src/derive_tryintojs.rs +40 -0
- package/lib/native.d.ts +24 -3
- package/package.json +4 -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/.github/workflows/per-pr.yml +6 -6
- package/sdk-core/AGENTS.md +42 -31
- package/sdk-core/Cargo.toml +4 -1
- package/sdk-core/README.md +19 -13
- package/sdk-core/crates/client/Cargo.toml +4 -0
- package/sdk-core/crates/client/README.md +139 -0
- package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
- package/sdk-core/crates/client/src/callback_based.rs +7 -0
- package/sdk-core/crates/client/src/errors.rs +294 -0
- package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +370 -159
- package/sdk-core/crates/client/src/lib.rs +920 -1326
- package/sdk-core/crates/client/src/metrics.rs +24 -33
- package/sdk-core/crates/client/src/options_structs.rs +457 -0
- package/sdk-core/crates/client/src/replaceable.rs +5 -4
- package/sdk-core/crates/client/src/request_extensions.rs +8 -9
- package/sdk-core/crates/client/src/retry.rs +99 -54
- package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +104 -29
- package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
- package/sdk-core/crates/common/Cargo.toml +62 -3
- package/sdk-core/crates/common/build.rs +742 -12
- package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
- package/sdk-core/crates/common/protos/api_upstream/.github/workflows/create-release.yml +0 -5
- package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
- package/sdk-core/crates/common/protos/api_upstream/README.md +8 -0
- package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
- package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +3329 -2647
- package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +2734 -708
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/activity/v1/message.proto +155 -3
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/common/v1/message.proto +8 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +27 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/activity.proto +81 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/event_type.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +15 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +63 -15
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/errordetails/v1/message.proto +8 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +111 -17
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +21 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +20 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/worker/v1/message.proto +4 -7
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflow/v1/message.proto +80 -22
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +347 -23
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +242 -43
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/core_interface.proto +15 -0
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +9 -2
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +8 -0
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +22 -5
- package/sdk-core/crates/common/src/activity_definition.rs +20 -0
- package/sdk-core/crates/common/src/data_converters.rs +770 -0
- package/sdk-core/crates/common/src/envconfig.rs +5 -0
- package/sdk-core/crates/common/src/lib.rs +15 -211
- package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
- package/sdk-core/crates/common/src/priority.rs +110 -0
- package/sdk-core/crates/common/src/protos/canned_histories.rs +19 -0
- package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
- package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
- package/sdk-core/crates/common/src/protos/mod.rs +134 -27
- package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
- package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +11 -16
- package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
- package/sdk-core/crates/common/src/telemetry/metrics.rs +272 -225
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
- package/sdk-core/crates/common/src/telemetry.rs +278 -19
- package/sdk-core/crates/common/src/worker.rs +68 -636
- package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
- package/sdk-core/crates/macros/Cargo.toml +5 -1
- package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
- package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
- package/sdk-core/crates/macros/src/lib.rs +138 -512
- package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
- package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
- package/sdk-core/crates/sdk/Cargo.toml +19 -6
- package/sdk-core/crates/sdk/README.md +415 -0
- package/sdk-core/crates/sdk/src/activities.rs +417 -0
- package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
- package/sdk-core/crates/sdk/src/lib.rs +759 -442
- package/sdk-core/crates/sdk/src/workflow_context/options.rs +64 -35
- package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
- package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
- package/sdk-core/crates/sdk/src/workflows.rs +711 -0
- package/sdk-core/crates/sdk-core/Cargo.toml +59 -65
- package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +45 -54
- package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
- package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
- package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
- package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +22 -21
- package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
- package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
- package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
- package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +647 -27
- package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +46 -41
- package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +13 -16
- package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
- package/sdk-core/crates/sdk-core/src/lib.rs +60 -123
- package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
- package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +411 -32
- package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
- package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
- package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +183 -198
- package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -281
- package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +35 -16
- package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
- package/sdk-core/crates/sdk-core/src/worker/activities/activity_heartbeat_manager.rs +1 -0
- package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
- package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
- package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +11 -5
- package/sdk-core/crates/sdk-core/src/worker/client.rs +104 -86
- package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +10 -14
- package/sdk-core/crates/sdk-core/src/worker/mod.rs +1175 -241
- package/sdk-core/crates/sdk-core/src/worker/nexus.rs +150 -23
- package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
- package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
- package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +25 -27
- package/sdk-core/crates/sdk-core/src/worker/tuner.rs +64 -44
- package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/patch_state_machine.rs +5 -8
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +28 -4
- package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +20 -41
- package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +50 -9
- package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
- package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
- package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
- package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
- package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
- package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
- package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
- package/sdk-core/crates/sdk-core/tests/common/mod.rs +281 -236
- package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
- package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +9 -14
- package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -66
- package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +306 -268
- package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
- package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +37 -38
- package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +49 -40
- package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +447 -300
- package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
- package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +157 -157
- package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
- package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -463
- package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +389 -265
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +250 -185
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -49
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +437 -327
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -58
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -30
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -251
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +110 -46
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -149
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -32
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1040
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -43
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +402 -245
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +343 -207
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +155 -140
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -113
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -44
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -48
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -56
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +365 -242
- package/sdk-core/crates/sdk-core/tests/main.rs +22 -16
- package/sdk-core/crates/sdk-core/tests/manual_tests.rs +233 -187
- package/sdk-core/crates/sdk-core/tests/runner.rs +4 -6
- package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +73 -27
- package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
- package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +8 -1
- package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +37 -26
- package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +180 -87
- package/sdk-core/crates/sdk-core-c-bridge/src/lib.rs +89 -5
- package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +10 -16
- package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +59 -67
- package/sdk-core/crates/sdk-core-c-bridge/src/testing.rs +10 -10
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +57 -22
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +108 -12
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +9 -52
- package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +74 -91
- package/sdk-core/rustfmt.toml +2 -1
- package/src/client.rs +206 -289
- package/src/helpers/try_into_js.rs +88 -2
- package/src/metrics.rs +277 -35
- package/src/runtime.rs +94 -45
- package/src/testing.rs +9 -16
- package/src/worker.rs +86 -68
- package/ts/native.ts +39 -3
- package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
- package/sdk-core/crates/common/src/errors.rs +0 -85
- package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
- package/sdk-core/crates/macros/LICENSE.txt +0 -21
- package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
- package/sdk-core/crates/sdk/src/app_data.rs +0 -37
- package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
|
@@ -2,7 +2,7 @@ use crate::{
|
|
|
2
2
|
common::{CoreWfStarter, WorkflowHandleExt, rand_6_chars},
|
|
3
3
|
integ_tests::mk_nexus_endpoint,
|
|
4
4
|
};
|
|
5
|
-
use anyhow::
|
|
5
|
+
use anyhow::anyhow;
|
|
6
6
|
use assert_matches::assert_matches;
|
|
7
7
|
use std::{
|
|
8
8
|
sync::{
|
|
@@ -11,9 +11,15 @@ use std::{
|
|
|
11
11
|
},
|
|
12
12
|
time::Duration,
|
|
13
13
|
};
|
|
14
|
-
use temporalio_client::{
|
|
14
|
+
use temporalio_client::{
|
|
15
|
+
UntypedSignal, UntypedWorkflow, WorkflowCancelOptions, WorkflowSignalOptions,
|
|
16
|
+
WorkflowStartOptions,
|
|
17
|
+
};
|
|
15
18
|
use temporalio_common::{
|
|
16
|
-
|
|
19
|
+
data_converters::{
|
|
20
|
+
GenericPayloadConverter, PayloadConverter, RawValue, SerializationContext,
|
|
21
|
+
SerializationContextData,
|
|
22
|
+
},
|
|
17
23
|
protos::{
|
|
18
24
|
coresdk::{
|
|
19
25
|
FromJsonPayloadExt,
|
|
@@ -35,15 +41,19 @@ use temporalio_common::{
|
|
|
35
41
|
},
|
|
36
42
|
worker::WorkerTaskTypes,
|
|
37
43
|
};
|
|
38
|
-
use
|
|
44
|
+
use temporalio_macros::{workflow, workflow_methods};
|
|
45
|
+
use temporalio_sdk::{
|
|
46
|
+
CancellableFuture, NexusOperationOptions, SyncWorkflowContext, WorkflowContext,
|
|
47
|
+
WorkflowContextView, WorkflowResult, WorkflowTermination,
|
|
48
|
+
};
|
|
49
|
+
use temporalio_sdk_core::PollError;
|
|
39
50
|
use tokio::{
|
|
40
51
|
join,
|
|
41
52
|
sync::{mpsc, watch},
|
|
42
53
|
};
|
|
43
|
-
use tokio_stream::StreamExt;
|
|
44
54
|
|
|
45
|
-
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
46
|
-
enum Outcome {
|
|
55
|
+
#[derive(Debug, PartialEq, Eq, Clone, Copy, serde::Serialize, serde::Deserialize)]
|
|
56
|
+
pub(crate) enum Outcome {
|
|
47
57
|
Succeed,
|
|
48
58
|
Fail,
|
|
49
59
|
Cancel,
|
|
@@ -51,6 +61,43 @@ enum Outcome {
|
|
|
51
61
|
Timeout,
|
|
52
62
|
}
|
|
53
63
|
|
|
64
|
+
#[workflow]
|
|
65
|
+
#[derive(Default)]
|
|
66
|
+
struct NexusBasicWf {
|
|
67
|
+
endpoint: String,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#[workflow_methods]
|
|
71
|
+
impl NexusBasicWf {
|
|
72
|
+
#[init]
|
|
73
|
+
fn new(_ctx: &WorkflowContextView, endpoint: String) -> Self {
|
|
74
|
+
Self { endpoint }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#[run]
|
|
78
|
+
pub(crate) async fn run(
|
|
79
|
+
ctx: &mut WorkflowContext<Self>,
|
|
80
|
+
) -> WorkflowResult<Result<NexusOperationResult, Failure>> {
|
|
81
|
+
match ctx
|
|
82
|
+
.start_nexus_operation(NexusOperationOptions {
|
|
83
|
+
endpoint: ctx.state(|wf| wf.endpoint.clone()),
|
|
84
|
+
service: "svc".to_string(),
|
|
85
|
+
operation: "op".to_string(),
|
|
86
|
+
schedule_to_close_timeout: Some(Duration::from_secs(3)),
|
|
87
|
+
..Default::default()
|
|
88
|
+
})
|
|
89
|
+
.await
|
|
90
|
+
{
|
|
91
|
+
Ok(started) => {
|
|
92
|
+
assert_eq!(started.operation_token, None);
|
|
93
|
+
let res = started.result().await;
|
|
94
|
+
Ok(Ok(res))
|
|
95
|
+
}
|
|
96
|
+
Err(failure) => Ok(Err(failure)),
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
54
101
|
#[rstest::rstest]
|
|
55
102
|
#[tokio::test]
|
|
56
103
|
async fn nexus_basic(
|
|
@@ -58,42 +105,28 @@ async fn nexus_basic(
|
|
|
58
105
|
) {
|
|
59
106
|
let wf_name = "nexus_basic";
|
|
60
107
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
61
|
-
starter.
|
|
108
|
+
starter.sdk_config.task_types = WorkerTaskTypes {
|
|
62
109
|
enable_workflows: true,
|
|
63
110
|
enable_local_activities: false,
|
|
64
111
|
enable_remote_activities: false,
|
|
65
112
|
enable_nexus: true,
|
|
66
|
-
}
|
|
113
|
+
};
|
|
67
114
|
let mut worker = starter.worker().await;
|
|
68
115
|
let core_worker = starter.get_worker().await;
|
|
69
116
|
|
|
70
117
|
let endpoint = mk_nexus_endpoint(&mut starter).await;
|
|
71
118
|
|
|
72
|
-
worker.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
..Default::default()
|
|
82
|
-
})
|
|
83
|
-
.await
|
|
84
|
-
{
|
|
85
|
-
Ok(started) => {
|
|
86
|
-
assert_eq!(started.operation_token, None);
|
|
87
|
-
let res = started.result().await;
|
|
88
|
-
Ok(Ok(res).into())
|
|
89
|
-
}
|
|
90
|
-
Err(failure) => Ok(Err(failure).into()),
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
let wf_handle = starter.start_with_worker(wf_name, &mut worker).await;
|
|
119
|
+
worker.register_workflow::<NexusBasicWf>();
|
|
120
|
+
let wf_handle = worker
|
|
121
|
+
.submit_workflow(
|
|
122
|
+
NexusBasicWf::run,
|
|
123
|
+
endpoint.clone(),
|
|
124
|
+
starter.workflow_options.clone(),
|
|
125
|
+
)
|
|
126
|
+
.await
|
|
127
|
+
.unwrap();
|
|
95
128
|
|
|
96
|
-
let client = starter.get_client().await
|
|
129
|
+
let client = starter.get_client().await;
|
|
97
130
|
let nexus_task_handle = async {
|
|
98
131
|
let nt = core_worker.poll_nexus_task().await.unwrap().unwrap_task();
|
|
99
132
|
match outcome {
|
|
@@ -132,6 +165,7 @@ async fn nexus_basic(
|
|
|
132
165
|
core_worker
|
|
133
166
|
.complete_nexus_task(NexusTaskCompletion {
|
|
134
167
|
task_token: nt.task_token,
|
|
168
|
+
#[allow(deprecated)]
|
|
135
169
|
status: Some(nexus_task_completion::Status::Error(HandlerError {
|
|
136
170
|
error_type: "BAD_REQUEST".to_string(), // bad req is non-retryable
|
|
137
171
|
failure: Some(nexus::v1::Failure {
|
|
@@ -157,12 +191,13 @@ async fn nexus_basic(
|
|
|
157
191
|
});
|
|
158
192
|
|
|
159
193
|
let res = client
|
|
160
|
-
.
|
|
161
|
-
.
|
|
194
|
+
.get_workflow_handle::<UntypedWorkflow>(starter.get_task_queue().to_owned())
|
|
195
|
+
.get_result(Default::default())
|
|
162
196
|
.await
|
|
163
197
|
.unwrap();
|
|
164
|
-
let res =
|
|
165
|
-
.unwrap()
|
|
198
|
+
let res =
|
|
199
|
+
Result::<NexusOperationResult, Failure>::from_json_payload(res.payloads.first().unwrap())
|
|
200
|
+
.unwrap();
|
|
166
201
|
match outcome {
|
|
167
202
|
Outcome::Succeed => {
|
|
168
203
|
let p = assert_matches!(
|
|
@@ -194,6 +229,80 @@ async fn nexus_basic(
|
|
|
194
229
|
.unwrap();
|
|
195
230
|
}
|
|
196
231
|
|
|
232
|
+
#[workflow]
|
|
233
|
+
struct NexusAsyncWf {
|
|
234
|
+
endpoint: String,
|
|
235
|
+
schedule_to_close_timeout: Option<Duration>,
|
|
236
|
+
outcome: Outcome,
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
#[workflow_methods]
|
|
240
|
+
impl NexusAsyncWf {
|
|
241
|
+
#[init]
|
|
242
|
+
fn new(
|
|
243
|
+
_ctx: &WorkflowContextView,
|
|
244
|
+
(endpoint, schedule_to_close_timeout, outcome): (String, Option<Duration>, Outcome),
|
|
245
|
+
) -> Self {
|
|
246
|
+
Self {
|
|
247
|
+
endpoint,
|
|
248
|
+
schedule_to_close_timeout,
|
|
249
|
+
outcome,
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
#[run]
|
|
254
|
+
pub(crate) async fn run(
|
|
255
|
+
ctx: &mut WorkflowContext<Self>,
|
|
256
|
+
) -> WorkflowResult<NexusOperationResult> {
|
|
257
|
+
let started = ctx.start_nexus_operation(NexusOperationOptions {
|
|
258
|
+
endpoint: ctx.state(|wf| wf.endpoint.clone()),
|
|
259
|
+
service: "svc".to_string(),
|
|
260
|
+
operation: "op".to_string(),
|
|
261
|
+
schedule_to_close_timeout: ctx.state(|wf| wf.schedule_to_close_timeout),
|
|
262
|
+
..Default::default()
|
|
263
|
+
});
|
|
264
|
+
if ctx.state(|wf| wf.outcome) == Outcome::CancelAfterRecordedBeforeStarted {
|
|
265
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
266
|
+
started.cancel();
|
|
267
|
+
}
|
|
268
|
+
let started = started.await.unwrap();
|
|
269
|
+
let result = started.result();
|
|
270
|
+
if matches!(ctx.state(|wf| wf.outcome), Outcome::Cancel) {
|
|
271
|
+
started.cancel();
|
|
272
|
+
started.cancel();
|
|
273
|
+
}
|
|
274
|
+
let res = result.await;
|
|
275
|
+
started.cancel();
|
|
276
|
+
Ok(res)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
#[workflow]
|
|
281
|
+
struct AsyncCompleter {
|
|
282
|
+
outcome: Outcome,
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
#[workflow_methods]
|
|
286
|
+
impl AsyncCompleter {
|
|
287
|
+
#[init]
|
|
288
|
+
fn new(_ctx: &WorkflowContextView, outcome: Outcome) -> Self {
|
|
289
|
+
Self { outcome }
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
#[allow(dead_code)] // Started via untyped submitter handle
|
|
293
|
+
#[run]
|
|
294
|
+
pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> {
|
|
295
|
+
match ctx.state(|wf| wf.outcome) {
|
|
296
|
+
Outcome::Succeed => Ok("completed async".to_string()),
|
|
297
|
+
Outcome::Cancel | Outcome::CancelAfterRecordedBeforeStarted => {
|
|
298
|
+
ctx.cancelled().await;
|
|
299
|
+
Err(WorkflowTermination::Cancelled)
|
|
300
|
+
}
|
|
301
|
+
_ => Err(anyhow!("broken").into()),
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
197
306
|
#[rstest::rstest]
|
|
198
307
|
#[tokio::test]
|
|
199
308
|
async fn nexus_async(
|
|
@@ -208,67 +317,40 @@ async fn nexus_async(
|
|
|
208
317
|
) {
|
|
209
318
|
let wf_name = "nexus_async";
|
|
210
319
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
211
|
-
starter.
|
|
320
|
+
starter.sdk_config.task_types = WorkerTaskTypes {
|
|
212
321
|
enable_workflows: true,
|
|
213
322
|
enable_local_activities: false,
|
|
214
323
|
enable_remote_activities: false,
|
|
215
324
|
enable_nexus: true,
|
|
216
|
-
}
|
|
325
|
+
};
|
|
217
326
|
let mut worker = starter.worker().await;
|
|
218
327
|
let core_worker = starter.get_worker().await;
|
|
219
328
|
|
|
220
329
|
let endpoint = mk_nexus_endpoint(&mut starter).await;
|
|
221
330
|
let schedule_to_close_timeout = if outcome == Outcome::CancelAfterRecordedBeforeStarted {
|
|
222
|
-
// If we set this, it'll time out before we can cancel it.
|
|
223
331
|
None
|
|
224
332
|
} else {
|
|
225
333
|
Some(Duration::from_secs(5))
|
|
226
334
|
};
|
|
227
335
|
|
|
228
|
-
worker.
|
|
229
|
-
|
|
230
|
-
async move {
|
|
231
|
-
let started = ctx.start_nexus_operation(NexusOperationOptions {
|
|
232
|
-
endpoint,
|
|
233
|
-
service: "svc".to_string(),
|
|
234
|
-
operation: "op".to_string(),
|
|
235
|
-
schedule_to_close_timeout,
|
|
236
|
-
..Default::default()
|
|
237
|
-
});
|
|
238
|
-
if outcome == Outcome::CancelAfterRecordedBeforeStarted {
|
|
239
|
-
ctx.timer(Duration::from_millis(1)).await;
|
|
240
|
-
started.cancel(&ctx);
|
|
241
|
-
}
|
|
242
|
-
let started = started.await.unwrap();
|
|
243
|
-
let result = started.result();
|
|
244
|
-
if matches!(outcome, Outcome::Cancel) {
|
|
245
|
-
started.cancel(&ctx);
|
|
246
|
-
// Make sure double-cancel doesn't cause problems
|
|
247
|
-
started.cancel(&ctx);
|
|
248
|
-
}
|
|
249
|
-
let res = result.await;
|
|
250
|
-
// Make sure cancel after completion doesn't cause problems
|
|
251
|
-
started.cancel(&ctx);
|
|
252
|
-
Ok(res.into())
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
worker.register_wf(
|
|
256
|
-
"async_completer".to_owned(),
|
|
257
|
-
move |ctx: WfContext| async move {
|
|
258
|
-
match outcome {
|
|
259
|
-
Outcome::Succeed => Ok("completed async".into()),
|
|
260
|
-
Outcome::Cancel | Outcome::CancelAfterRecordedBeforeStarted => {
|
|
261
|
-
ctx.cancelled().await;
|
|
262
|
-
Ok(WfExitValue::Cancelled)
|
|
263
|
-
}
|
|
264
|
-
_ => bail!("broken"),
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
);
|
|
336
|
+
worker.register_workflow::<NexusAsyncWf>();
|
|
337
|
+
worker.register_workflow::<AsyncCompleter>();
|
|
268
338
|
let submitter = worker.get_submitter_handle();
|
|
269
|
-
let
|
|
339
|
+
let converter = PayloadConverter::default();
|
|
340
|
+
let ser_ctx = SerializationContext {
|
|
341
|
+
data: &SerializationContextData::Workflow,
|
|
342
|
+
converter: &converter,
|
|
343
|
+
};
|
|
344
|
+
let wf_handle = worker
|
|
345
|
+
.submit_workflow(
|
|
346
|
+
NexusAsyncWf::run,
|
|
347
|
+
(endpoint.clone(), schedule_to_close_timeout, outcome),
|
|
348
|
+
starter.workflow_options.clone(),
|
|
349
|
+
)
|
|
350
|
+
.await
|
|
351
|
+
.unwrap();
|
|
270
352
|
|
|
271
|
-
let client = starter.get_client().await
|
|
353
|
+
let client = starter.get_client().await;
|
|
272
354
|
let nexus_task_handle = async {
|
|
273
355
|
let mut nt = core_worker.poll_nexus_task().await.unwrap().unwrap_task();
|
|
274
356
|
// Verify request header key for timeout exists and is lowercase
|
|
@@ -311,23 +393,22 @@ async fn nexus_async(
|
|
|
311
393
|
|
|
312
394
|
// Start the workflow which will act like the nexus handler and complete the async
|
|
313
395
|
// operation
|
|
396
|
+
let payloads = vec![converter.to_payload(&ser_ctx, &outcome).unwrap()];
|
|
397
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
314
398
|
submitter
|
|
315
399
|
.submit_wf(
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
completion_callbacks: vec![Callback {
|
|
400
|
+
AsyncCompleter::name(),
|
|
401
|
+
payloads,
|
|
402
|
+
WorkflowStartOptions::new(task_queue, completer_id.clone())
|
|
403
|
+
.completion_callbacks(vec![Callback {
|
|
321
404
|
variant: Some(callback::Variant::Nexus(callback::Nexus {
|
|
322
405
|
url: start_req.callback,
|
|
323
406
|
header: start_req.callback_header,
|
|
324
407
|
})),
|
|
325
408
|
links: links.clone(),
|
|
326
|
-
}]
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
..Default::default()
|
|
330
|
-
},
|
|
409
|
+
}])
|
|
410
|
+
.links(links)
|
|
411
|
+
.build(),
|
|
331
412
|
)
|
|
332
413
|
.await
|
|
333
414
|
.unwrap();
|
|
@@ -364,8 +445,13 @@ async fn nexus_async(
|
|
|
364
445
|
nt.request.unwrap().variant.unwrap(),
|
|
365
446
|
request::Variant::CancelOperation(_)
|
|
366
447
|
);
|
|
367
|
-
client
|
|
368
|
-
|
|
448
|
+
let handle = client.get_workflow_handle::<UntypedWorkflow>(completer_id);
|
|
449
|
+
handle
|
|
450
|
+
.cancel(
|
|
451
|
+
WorkflowCancelOptions::builder()
|
|
452
|
+
.reason("nexus cancel")
|
|
453
|
+
.build(),
|
|
454
|
+
)
|
|
369
455
|
.await
|
|
370
456
|
.unwrap();
|
|
371
457
|
core_worker
|
|
@@ -393,11 +479,11 @@ async fn nexus_async(
|
|
|
393
479
|
});
|
|
394
480
|
|
|
395
481
|
let res = client
|
|
396
|
-
.
|
|
397
|
-
.
|
|
482
|
+
.get_workflow_handle::<UntypedWorkflow>(starter.get_task_queue().to_owned())
|
|
483
|
+
.get_result(Default::default())
|
|
398
484
|
.await
|
|
399
485
|
.unwrap();
|
|
400
|
-
let res = NexusOperationResult::from_json_payload(
|
|
486
|
+
let res = NexusOperationResult::from_json_payload(res.payloads.first().unwrap()).unwrap();
|
|
401
487
|
match outcome {
|
|
402
488
|
Outcome::Succeed => {
|
|
403
489
|
let p = assert_matches!(
|
|
@@ -412,7 +498,7 @@ async fn nexus_async(
|
|
|
412
498
|
Some(nexus_operation_result::Status::Failed(f)) => f
|
|
413
499
|
);
|
|
414
500
|
assert_eq!(f.message, "nexus operation completed unsuccessfully");
|
|
415
|
-
assert_eq!(f.cause.unwrap().message, "broken");
|
|
501
|
+
assert_eq!(f.cause.unwrap().message, "Workflow execution error: broken");
|
|
416
502
|
}
|
|
417
503
|
Outcome::Cancel | Outcome::CancelAfterRecordedBeforeStarted => {
|
|
418
504
|
let f = assert_matches!(
|
|
@@ -436,43 +522,64 @@ async fn nexus_async(
|
|
|
436
522
|
.await
|
|
437
523
|
.unwrap();
|
|
438
524
|
}
|
|
525
|
+
#[workflow]
|
|
526
|
+
#[derive(Default)]
|
|
527
|
+
struct NexusCancelBeforeStartWf {
|
|
528
|
+
endpoint: String,
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
#[workflow_methods]
|
|
532
|
+
impl NexusCancelBeforeStartWf {
|
|
533
|
+
#[init]
|
|
534
|
+
fn new(_ctx: &WorkflowContextView, endpoint: String) -> Self {
|
|
535
|
+
Self { endpoint }
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
#[run]
|
|
539
|
+
pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
540
|
+
let started = ctx.start_nexus_operation(NexusOperationOptions {
|
|
541
|
+
endpoint: ctx.state(|wf| wf.endpoint.clone()),
|
|
542
|
+
service: "svc".to_string(),
|
|
543
|
+
operation: "op".to_string(),
|
|
544
|
+
..Default::default()
|
|
545
|
+
});
|
|
546
|
+
started.cancel();
|
|
547
|
+
let res = started.await.unwrap_err();
|
|
548
|
+
assert_eq!(res.message, "Nexus Operation cancelled before scheduled");
|
|
549
|
+
if let FailureInfo::NexusOperationExecutionFailureInfo(fi) = res.failure_info.unwrap() {
|
|
550
|
+
assert_eq!(fi.endpoint, ctx.state(|wf| wf.endpoint.clone()));
|
|
551
|
+
assert_eq!(fi.service, "svc");
|
|
552
|
+
assert_eq!(fi.operation, "op");
|
|
553
|
+
} else {
|
|
554
|
+
panic!("unexpected failure info");
|
|
555
|
+
}
|
|
556
|
+
Ok(())
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
439
560
|
#[tokio::test]
|
|
440
561
|
async fn nexus_cancel_before_start() {
|
|
441
562
|
let wf_name = "nexus_cancel_before_start";
|
|
442
563
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
443
|
-
starter.
|
|
564
|
+
starter.sdk_config.task_types = WorkerTaskTypes {
|
|
444
565
|
enable_workflows: true,
|
|
445
566
|
enable_local_activities: false,
|
|
446
567
|
enable_remote_activities: false,
|
|
447
568
|
enable_nexus: true,
|
|
448
|
-
}
|
|
569
|
+
};
|
|
449
570
|
let mut worker = starter.worker().await;
|
|
450
571
|
|
|
451
572
|
let endpoint = mk_nexus_endpoint(&mut starter).await;
|
|
452
573
|
|
|
453
|
-
worker.
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
started.cancel(&ctx);
|
|
463
|
-
let res = started.await.unwrap_err();
|
|
464
|
-
assert_eq!(res.message, "Nexus Operation cancelled before scheduled");
|
|
465
|
-
if let FailureInfo::NexusOperationExecutionFailureInfo(fi) = res.failure_info.unwrap() {
|
|
466
|
-
assert_eq!(fi.endpoint, endpoint);
|
|
467
|
-
assert_eq!(fi.service, "svc");
|
|
468
|
-
assert_eq!(fi.operation, "op");
|
|
469
|
-
} else {
|
|
470
|
-
panic!("unexpected failure info");
|
|
471
|
-
}
|
|
472
|
-
Ok(().into())
|
|
473
|
-
}
|
|
474
|
-
});
|
|
475
|
-
let handle = starter.start_with_worker(wf_name, &mut worker).await;
|
|
574
|
+
worker.register_workflow::<NexusCancelBeforeStartWf>();
|
|
575
|
+
let handle = worker
|
|
576
|
+
.submit_workflow(
|
|
577
|
+
NexusCancelBeforeStartWf::run,
|
|
578
|
+
endpoint,
|
|
579
|
+
starter.workflow_options.clone(),
|
|
580
|
+
)
|
|
581
|
+
.await
|
|
582
|
+
.unwrap();
|
|
476
583
|
|
|
477
584
|
worker.run_until_done().await.unwrap();
|
|
478
585
|
|
|
@@ -482,55 +589,71 @@ async fn nexus_cancel_before_start() {
|
|
|
482
589
|
.unwrap();
|
|
483
590
|
}
|
|
484
591
|
|
|
592
|
+
#[workflow]
|
|
593
|
+
#[derive(Default)]
|
|
594
|
+
struct NexusMustCompleteTaskWf {
|
|
595
|
+
endpoint: String,
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
#[workflow_methods]
|
|
599
|
+
impl NexusMustCompleteTaskWf {
|
|
600
|
+
#[init]
|
|
601
|
+
fn new(_ctx: &WorkflowContextView, endpoint: String) -> Self {
|
|
602
|
+
Self { endpoint }
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
#[run]
|
|
606
|
+
pub(crate) async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
607
|
+
// We just need to create the command, not await it.
|
|
608
|
+
drop(ctx.start_nexus_operation(NexusOperationOptions {
|
|
609
|
+
endpoint: ctx.state(|wf| wf.endpoint.clone()),
|
|
610
|
+
service: "svc".to_string(),
|
|
611
|
+
operation: "op".to_string(),
|
|
612
|
+
..Default::default()
|
|
613
|
+
}));
|
|
614
|
+
// Workflow completes right away, only having scheduled the operation. We need a timer
|
|
615
|
+
// to make sure the nexus task actually gets scheduled.
|
|
616
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
617
|
+
// started.await.unwrap();
|
|
618
|
+
Ok(())
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
485
622
|
#[rstest::rstest]
|
|
486
623
|
#[tokio::test]
|
|
487
624
|
async fn nexus_must_complete_task_to_shutdown(#[values(true, false)] use_grace_period: bool) {
|
|
488
625
|
let wf_name = "nexus_must_complete_task_to_shutdown";
|
|
489
626
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
490
|
-
starter.
|
|
627
|
+
starter.sdk_config.task_types = WorkerTaskTypes {
|
|
491
628
|
enable_workflows: true,
|
|
492
629
|
enable_local_activities: false,
|
|
493
630
|
enable_remote_activities: false,
|
|
494
631
|
enable_nexus: true,
|
|
495
|
-
}
|
|
632
|
+
};
|
|
496
633
|
if use_grace_period {
|
|
497
|
-
starter
|
|
498
|
-
.worker_config
|
|
499
|
-
.graceful_shutdown_period(Duration::from_millis(500));
|
|
634
|
+
starter.sdk_config.graceful_shutdown_period = Some(Duration::from_millis(500));
|
|
500
635
|
}
|
|
501
636
|
let mut worker = starter.worker().await;
|
|
502
637
|
let core_worker = starter.get_worker().await;
|
|
503
638
|
|
|
504
639
|
let endpoint = mk_nexus_endpoint(&mut starter).await;
|
|
505
640
|
|
|
506
|
-
worker.
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
}));
|
|
516
|
-
// Workflow completes right away, only having scheduled the operation. We need a timer
|
|
517
|
-
// to make sure the nexus task actually gets scheduled.
|
|
518
|
-
ctx.timer(Duration::from_millis(1)).await;
|
|
519
|
-
// started.await.unwrap();
|
|
520
|
-
Ok(().into())
|
|
521
|
-
}
|
|
522
|
-
});
|
|
523
|
-
let handle = starter.start_with_worker(wf_name, &mut worker).await;
|
|
641
|
+
worker.register_workflow::<NexusMustCompleteTaskWf>();
|
|
642
|
+
let handle = worker
|
|
643
|
+
.submit_workflow(
|
|
644
|
+
NexusMustCompleteTaskWf::run,
|
|
645
|
+
endpoint,
|
|
646
|
+
starter.workflow_options.clone(),
|
|
647
|
+
)
|
|
648
|
+
.await
|
|
649
|
+
.unwrap();
|
|
524
650
|
let (complete_order_tx, mut complete_order_rx) = mpsc::unbounded_channel();
|
|
525
651
|
|
|
526
652
|
let task_handle = async {
|
|
527
653
|
// Should get the nexus task first
|
|
528
654
|
let nt = core_worker.poll_nexus_task().await.unwrap().unwrap_task();
|
|
529
655
|
// The workflow will complete
|
|
530
|
-
handle
|
|
531
|
-
.get_workflow_result(Default::default())
|
|
532
|
-
.await
|
|
533
|
-
.unwrap();
|
|
656
|
+
handle.get_result(Default::default()).await.unwrap();
|
|
534
657
|
if use_grace_period {
|
|
535
658
|
// Wait for cancel to be sent
|
|
536
659
|
let nt = core_worker.poll_nexus_task().await.unwrap();
|
|
@@ -546,6 +669,7 @@ async fn nexus_must_complete_task_to_shutdown(#[values(true, false)] use_grace_p
|
|
|
546
669
|
core_worker
|
|
547
670
|
.complete_nexus_task(NexusTaskCompletion {
|
|
548
671
|
task_token: nt.task_token,
|
|
672
|
+
#[allow(deprecated)]
|
|
549
673
|
status: Some(nexus_task_completion::Status::Error(HandlerError {
|
|
550
674
|
error_type: "BAD_REQUEST".to_string(), // bad req is non-retryable
|
|
551
675
|
failure: Some(nexus::v1::Failure {
|
|
@@ -579,6 +703,89 @@ async fn nexus_must_complete_task_to_shutdown(#[values(true, false)] use_grace_p
|
|
|
579
703
|
.unwrap();
|
|
580
704
|
}
|
|
581
705
|
|
|
706
|
+
#[workflow]
|
|
707
|
+
struct NexusCancellationCallerWf {
|
|
708
|
+
endpoint: String,
|
|
709
|
+
schedule_to_close_timeout: Option<Duration>,
|
|
710
|
+
cancellation_type: NexusOperationCancellationType,
|
|
711
|
+
caller_op_future_tx: watch::Sender<bool>,
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
#[workflow_methods(factory_only)]
|
|
715
|
+
impl NexusCancellationCallerWf {
|
|
716
|
+
#[run(name = "nexus_cancellation_types")]
|
|
717
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<NexusOperationResult> {
|
|
718
|
+
let options = NexusOperationOptions {
|
|
719
|
+
endpoint: ctx.state(|wf| wf.endpoint.clone()),
|
|
720
|
+
service: "svc".to_string(),
|
|
721
|
+
operation: "op".to_string(),
|
|
722
|
+
schedule_to_close_timeout: ctx.state(|wf| wf.schedule_to_close_timeout),
|
|
723
|
+
cancellation_type: Some(ctx.state(|wf| wf.cancellation_type)),
|
|
724
|
+
..Default::default()
|
|
725
|
+
};
|
|
726
|
+
let started = ctx.start_nexus_operation(options);
|
|
727
|
+
let started = started.await.unwrap();
|
|
728
|
+
let result = started.result();
|
|
729
|
+
started.cancel();
|
|
730
|
+
started.cancel();
|
|
731
|
+
|
|
732
|
+
let res = result.await;
|
|
733
|
+
ctx.state(|wf| wf.caller_op_future_tx.send(true).unwrap());
|
|
734
|
+
|
|
735
|
+
// Make sure cancel after op completion doesn't cause problems
|
|
736
|
+
started.cancel();
|
|
737
|
+
|
|
738
|
+
// We need to wait slightly so that the workflow is not complete at the same time
|
|
739
|
+
// cancellation is invoked. If it does, the caller workflow will close and the server
|
|
740
|
+
// won't attempt to send the cancellation to the handler
|
|
741
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
742
|
+
Ok(res)
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
#[workflow]
|
|
747
|
+
struct AsyncCompleterWf {
|
|
748
|
+
cancellation_type: NexusOperationCancellationType,
|
|
749
|
+
cancellation_wait_happened: Arc<AtomicBool>,
|
|
750
|
+
cancellation_tx: watch::Sender<bool>,
|
|
751
|
+
handler_exited_tx: watch::Sender<bool>,
|
|
752
|
+
proceed_signal_received: bool,
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
#[workflow_methods(factory_only)]
|
|
756
|
+
impl AsyncCompleterWf {
|
|
757
|
+
#[run(name = "async_completer")]
|
|
758
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
759
|
+
// Wait for cancellation
|
|
760
|
+
ctx.cancelled().await;
|
|
761
|
+
ctx.state(|wf| wf.cancellation_tx.send(true).unwrap());
|
|
762
|
+
|
|
763
|
+
if ctx.state(|wf| wf.cancellation_type)
|
|
764
|
+
== NexusOperationCancellationType::WaitCancellationCompleted
|
|
765
|
+
{
|
|
766
|
+
ctx.wait_condition(|wf| wf.cancellation_wait_happened.load(Ordering::Relaxed))
|
|
767
|
+
.await;
|
|
768
|
+
} else if ctx.state(|wf| wf.cancellation_type)
|
|
769
|
+
== NexusOperationCancellationType::WaitCancellationRequested
|
|
770
|
+
{
|
|
771
|
+
// For WAIT_REQUESTED, wait until the caller nexus op future has been resolved. This
|
|
772
|
+
// allows the test to verify that it resolved due to
|
|
773
|
+
// NexusOperationCancelRequestCompleted (written after cancel handler responds)
|
|
774
|
+
// rather than NexusOperationCanceled (written after handler workflow completes as
|
|
775
|
+
// cancelled).
|
|
776
|
+
ctx.wait_condition(|wf| wf.proceed_signal_received).await;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
ctx.state(|wf| wf.handler_exited_tx.send(true).unwrap());
|
|
780
|
+
Err(WorkflowTermination::Cancelled)
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
#[signal(name = "proceed-to-exit")]
|
|
784
|
+
fn handle_proceed_signal(&mut self, _ctx: &mut SyncWorkflowContext<Self>) {
|
|
785
|
+
self.proceed_signal_received = true;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
582
789
|
#[rstest::rstest]
|
|
583
790
|
#[tokio::test]
|
|
584
791
|
async fn nexus_cancellation_types(
|
|
@@ -592,12 +799,12 @@ async fn nexus_cancellation_types(
|
|
|
592
799
|
) {
|
|
593
800
|
let wf_name = "nexus_cancellation_types";
|
|
594
801
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
595
|
-
starter.
|
|
802
|
+
starter.sdk_config.task_types = WorkerTaskTypes {
|
|
596
803
|
enable_workflows: true,
|
|
597
804
|
enable_local_activities: false,
|
|
598
805
|
enable_remote_activities: false,
|
|
599
806
|
enable_nexus: true,
|
|
600
|
-
}
|
|
807
|
+
};
|
|
601
808
|
let mut worker = starter.worker().await;
|
|
602
809
|
let core_worker = starter.get_worker().await;
|
|
603
810
|
|
|
@@ -605,72 +812,35 @@ async fn nexus_cancellation_types(
|
|
|
605
812
|
let schedule_to_close_timeout = Some(Duration::from_secs(5));
|
|
606
813
|
|
|
607
814
|
let (caller_op_future_tx, caller_op_future_rx) = watch::channel(false);
|
|
608
|
-
worker.
|
|
815
|
+
worker.register_workflow_with_factory({
|
|
609
816
|
let endpoint = endpoint.clone();
|
|
610
817
|
let caller_op_future_tx = caller_op_future_tx.clone();
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
schedule_to_close_timeout,
|
|
617
|
-
cancellation_type: Some(cancellation_type),
|
|
618
|
-
..Default::default()
|
|
619
|
-
};
|
|
620
|
-
let started = ctx.start_nexus_operation(options);
|
|
621
|
-
let started = started.await.unwrap();
|
|
622
|
-
let result = started.result();
|
|
623
|
-
started.cancel(&ctx);
|
|
624
|
-
started.cancel(&ctx);
|
|
625
|
-
|
|
626
|
-
let res = result.await;
|
|
627
|
-
caller_op_future_tx.send(true).unwrap();
|
|
628
|
-
|
|
629
|
-
// Make sure cancel after op completion doesn't cause problems
|
|
630
|
-
started.cancel(&ctx);
|
|
631
|
-
|
|
632
|
-
// We need to wait slightly so that the workflow is not complete at the same time
|
|
633
|
-
// cancellation is invoked. If it does, the caller workflow will close and the server
|
|
634
|
-
// won't attempt to send the cancellation to the handler
|
|
635
|
-
ctx.timer(Duration::from_millis(1)).await;
|
|
636
|
-
Ok(res.into())
|
|
818
|
+
move || NexusCancellationCallerWf {
|
|
819
|
+
endpoint: endpoint.clone(),
|
|
820
|
+
schedule_to_close_timeout,
|
|
821
|
+
cancellation_type,
|
|
822
|
+
caller_op_future_tx: caller_op_future_tx.clone(),
|
|
637
823
|
}
|
|
638
824
|
});
|
|
639
825
|
|
|
640
826
|
let cancellation_wait_happened = Arc::new(AtomicBool::new(false));
|
|
641
|
-
let cancellation_wait_happened_clone = cancellation_wait_happened.clone();
|
|
642
827
|
let (cancellation_tx, mut cancellation_rx) = watch::channel(false);
|
|
643
828
|
let (handler_exited_tx, mut handler_exited_rx) = watch::channel(false);
|
|
644
|
-
worker.
|
|
829
|
+
worker.register_workflow_with_factory({
|
|
830
|
+
let cancellation_wait_happened = cancellation_wait_happened.clone();
|
|
645
831
|
let cancellation_tx = cancellation_tx.clone();
|
|
646
|
-
let cancellation_wait_happened = cancellation_wait_happened_clone.clone();
|
|
647
832
|
let handler_exited_tx = handler_exited_tx.clone();
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
cancellation_tx.
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
ctx.wait_condition(|| cancellation_wait_happened.load(Ordering::Relaxed))
|
|
655
|
-
.await;
|
|
656
|
-
} else if cancellation_type == NexusOperationCancellationType::WaitCancellationRequested
|
|
657
|
-
{
|
|
658
|
-
// For WAIT_REQUESTED, wait until the caller nexus op future has been resolved. This
|
|
659
|
-
// allows the test to verify that it resolved due to
|
|
660
|
-
// NexusOperationCancelRequestCompleted (written after cancel handler responds)
|
|
661
|
-
// rather than NexusOperationCanceled (written after handler workflow completes as
|
|
662
|
-
// cancelled).
|
|
663
|
-
let mut signal_chan = ctx.make_signal_channel("proceed-to-exit");
|
|
664
|
-
signal_chan.next().await;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
handler_exited_tx.send(true).unwrap();
|
|
668
|
-
Ok(WfExitValue::<()>::Cancelled)
|
|
833
|
+
move || AsyncCompleterWf {
|
|
834
|
+
cancellation_type,
|
|
835
|
+
cancellation_wait_happened: cancellation_wait_happened.clone(),
|
|
836
|
+
cancellation_tx: cancellation_tx.clone(),
|
|
837
|
+
handler_exited_tx: handler_exited_tx.clone(),
|
|
838
|
+
proceed_signal_received: false,
|
|
669
839
|
}
|
|
670
840
|
});
|
|
671
841
|
let submitter = worker.get_submitter_handle();
|
|
672
842
|
let wf_handle = starter.start_with_worker(wf_name, &mut worker).await;
|
|
673
|
-
let client = starter.get_client().await
|
|
843
|
+
let client = starter.get_client().await;
|
|
674
844
|
let (handler_wf_id_tx, mut handler_wf_id_rx) = tokio::sync::oneshot::channel();
|
|
675
845
|
let completer_id = &format!("completer-{}", rand_6_chars());
|
|
676
846
|
let nexus_task_handle = async {
|
|
@@ -689,23 +859,21 @@ async fn nexus_cancellation_types(
|
|
|
689
859
|
|
|
690
860
|
// Start the workflow which will act like the nexus handler and complete the async
|
|
691
861
|
// operation
|
|
862
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
692
863
|
submitter
|
|
693
864
|
.submit_wf(
|
|
694
|
-
completer_id.clone(),
|
|
695
865
|
"async_completer",
|
|
696
866
|
vec![],
|
|
697
|
-
|
|
698
|
-
completion_callbacks
|
|
867
|
+
WorkflowStartOptions::new(task_queue, completer_id.clone())
|
|
868
|
+
.completion_callbacks(vec![Callback {
|
|
699
869
|
variant: Some(callback::Variant::Nexus(callback::Nexus {
|
|
700
870
|
url: start_req.callback,
|
|
701
871
|
header: start_req.callback_header,
|
|
702
872
|
})),
|
|
703
873
|
links: links.clone(),
|
|
704
|
-
}]
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
..Default::default()
|
|
708
|
-
},
|
|
874
|
+
}])
|
|
875
|
+
.links(links)
|
|
876
|
+
.build(),
|
|
709
877
|
)
|
|
710
878
|
.await
|
|
711
879
|
.unwrap();
|
|
@@ -739,10 +907,7 @@ async fn nexus_cancellation_types(
|
|
|
739
907
|
assert!(!*caller_op_future_rx.borrow());
|
|
740
908
|
}
|
|
741
909
|
NexusOperationCancellationType::Abandon | NexusOperationCancellationType::TryCancel => {
|
|
742
|
-
wf_handle
|
|
743
|
-
.get_workflow_result(Default::default())
|
|
744
|
-
.await
|
|
745
|
-
.unwrap();
|
|
910
|
+
wf_handle.get_result(Default::default()).await.unwrap();
|
|
746
911
|
// The nexus op future should have been resolved
|
|
747
912
|
assert!(*caller_op_future_rx.borrow())
|
|
748
913
|
}
|
|
@@ -755,12 +920,12 @@ async fn nexus_cancellation_types(
|
|
|
755
920
|
nt.request.unwrap().variant.unwrap(),
|
|
756
921
|
request::Variant::CancelOperation(_)
|
|
757
922
|
);
|
|
758
|
-
client
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
923
|
+
let handle = client.get_workflow_handle::<UntypedWorkflow>(completer_id.to_string());
|
|
924
|
+
handle
|
|
925
|
+
.cancel(
|
|
926
|
+
WorkflowCancelOptions::builder()
|
|
927
|
+
.reason("nexus cancel")
|
|
928
|
+
.build(),
|
|
764
929
|
)
|
|
765
930
|
.await
|
|
766
931
|
.unwrap();
|
|
@@ -789,18 +954,14 @@ async fn nexus_cancellation_types(
|
|
|
789
954
|
// Send a signal just to wake up the workflow so it'll check the condition
|
|
790
955
|
// (it may already have completed, so ignore the result)
|
|
791
956
|
let _ = client
|
|
792
|
-
.
|
|
793
|
-
|
|
794
|
-
""
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
None,
|
|
957
|
+
.get_workflow_handle::<UntypedWorkflow>(completer_id.to_string())
|
|
958
|
+
.signal(
|
|
959
|
+
UntypedSignal::new("wakeupdude"),
|
|
960
|
+
RawValue::empty(),
|
|
961
|
+
WorkflowSignalOptions::default(),
|
|
798
962
|
)
|
|
799
963
|
.await;
|
|
800
|
-
wf_handle
|
|
801
|
-
.get_workflow_result(Default::default())
|
|
802
|
-
.await
|
|
803
|
-
.unwrap();
|
|
964
|
+
wf_handle.get_result(Default::default()).await.unwrap();
|
|
804
965
|
assert!(*caller_op_future_rx.borrow());
|
|
805
966
|
}
|
|
806
967
|
|
|
@@ -829,12 +990,11 @@ async fn nexus_cancellation_types(
|
|
|
829
990
|
.try_recv()
|
|
830
991
|
.expect("Should have received handler workflow ID");
|
|
831
992
|
client
|
|
832
|
-
.
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
None,
|
|
993
|
+
.get_workflow_handle::<async_completer_wf::Run>(handler_wf_id)
|
|
994
|
+
.signal(
|
|
995
|
+
AsyncCompleterWf::handle_proceed_signal,
|
|
996
|
+
(),
|
|
997
|
+
WorkflowSignalOptions::default(),
|
|
838
998
|
)
|
|
839
999
|
.await
|
|
840
1000
|
.unwrap();
|
|
@@ -847,10 +1007,7 @@ async fn nexus_cancellation_types(
|
|
|
847
1007
|
nexus_task_handle,
|
|
848
1008
|
async { worker.inner_mut().run().await.unwrap() },
|
|
849
1009
|
async {
|
|
850
|
-
wf_handle
|
|
851
|
-
.get_workflow_result(Default::default())
|
|
852
|
-
.await
|
|
853
|
-
.unwrap();
|
|
1010
|
+
wf_handle.get_result(Default::default()).await.unwrap();
|
|
854
1011
|
if cancellation_type == NexusOperationCancellationType::TryCancel {
|
|
855
1012
|
cancellation_rx.changed().await.unwrap();
|
|
856
1013
|
}
|
|
@@ -873,11 +1030,11 @@ async fn nexus_cancellation_types(
|
|
|
873
1030
|
}
|
|
874
1031
|
|
|
875
1032
|
let res = client
|
|
876
|
-
.
|
|
877
|
-
.
|
|
1033
|
+
.get_workflow_handle::<UntypedWorkflow>(starter.get_task_queue().to_owned())
|
|
1034
|
+
.get_result(Default::default())
|
|
878
1035
|
.await
|
|
879
1036
|
.unwrap();
|
|
880
|
-
let res = NexusOperationResult::from_json_payload(
|
|
1037
|
+
let res = NexusOperationResult::from_json_payload(res.payloads.first().unwrap()).unwrap();
|
|
881
1038
|
|
|
882
1039
|
match cancellation_type {
|
|
883
1040
|
NexusOperationCancellationType::Abandon | NexusOperationCancellationType::TryCancel => {
|