@temporalio/core-bridge 1.13.0 → 1.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +239 -382
- package/Cargo.toml +11 -11
- package/lib/native.d.ts +10 -3
- package/package.json +3 -3
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.cargo/config.toml +71 -11
- package/sdk-core/.clippy.toml +1 -0
- package/sdk-core/.github/workflows/heavy.yml +2 -0
- package/sdk-core/.github/workflows/per-pr.yml +50 -18
- package/sdk-core/ARCHITECTURE.md +44 -48
- package/sdk-core/Cargo.toml +26 -7
- package/sdk-core/README.md +4 -0
- package/sdk-core/arch_docs/diagrams/TimerMachine_Coverage.puml +14 -0
- package/sdk-core/arch_docs/diagrams/initial_event_history.png +0 -0
- package/sdk-core/arch_docs/sdks_intro.md +299 -0
- package/sdk-core/client/Cargo.toml +8 -7
- package/sdk-core/client/src/callback_based.rs +1 -2
- package/sdk-core/client/src/lib.rs +485 -299
- package/sdk-core/client/src/metrics.rs +32 -8
- package/sdk-core/client/src/proxy.rs +124 -5
- package/sdk-core/client/src/raw.rs +598 -307
- package/sdk-core/client/src/replaceable.rs +253 -0
- package/sdk-core/client/src/retry.rs +9 -6
- package/sdk-core/client/src/worker_registry/mod.rs +19 -3
- package/sdk-core/client/src/workflow_handle/mod.rs +20 -17
- package/sdk-core/core/Cargo.toml +100 -31
- package/sdk-core/core/src/core_tests/activity_tasks.rs +55 -225
- package/sdk-core/core/src/core_tests/mod.rs +2 -8
- package/sdk-core/core/src/core_tests/queries.rs +3 -5
- package/sdk-core/core/src/core_tests/replay_flag.rs +3 -62
- package/sdk-core/core/src/core_tests/updates.rs +4 -5
- package/sdk-core/core/src/core_tests/workers.rs +4 -3
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +10 -7
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +28 -291
- package/sdk-core/core/src/ephemeral_server/mod.rs +15 -3
- package/sdk-core/core/src/internal_flags.rs +11 -1
- package/sdk-core/core/src/lib.rs +50 -36
- package/sdk-core/core/src/pollers/mod.rs +5 -5
- package/sdk-core/core/src/pollers/poll_buffer.rs +2 -2
- package/sdk-core/core/src/protosext/mod.rs +13 -5
- package/sdk-core/core/src/protosext/protocol_messages.rs +4 -11
- package/sdk-core/core/src/retry_logic.rs +256 -108
- package/sdk-core/core/src/telemetry/metrics.rs +1 -0
- package/sdk-core/core/src/telemetry/mod.rs +8 -2
- package/sdk-core/core/src/telemetry/prometheus_meter.rs +2 -2
- package/sdk-core/core/src/test_help/integ_helpers.rs +971 -0
- package/sdk-core/core/src/test_help/mod.rs +10 -1100
- package/sdk-core/core/src/test_help/unit_helpers.rs +218 -0
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +42 -6
- package/sdk-core/core/src/worker/activities/local_activities.rs +19 -19
- package/sdk-core/core/src/worker/activities.rs +10 -3
- package/sdk-core/core/src/worker/client/mocks.rs +3 -3
- package/sdk-core/core/src/worker/client.rs +130 -93
- package/sdk-core/core/src/worker/heartbeat.rs +12 -13
- package/sdk-core/core/src/worker/mod.rs +31 -21
- package/sdk-core/core/src/worker/nexus.rs +14 -3
- package/sdk-core/core/src/worker/slot_provider.rs +9 -0
- package/sdk-core/core/src/worker/tuner.rs +159 -0
- package/sdk-core/core/src/worker/workflow/history_update.rs +3 -265
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -54
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +0 -82
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +0 -67
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -192
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +0 -43
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +6 -554
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -71
- package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +102 -3
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +10 -539
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +0 -139
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -119
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +6 -63
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +9 -4
- package/sdk-core/core/src/worker/workflow/mod.rs +5 -1
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +8 -3
- package/sdk-core/core-api/Cargo.toml +4 -4
- package/sdk-core/core-api/src/envconfig.rs +153 -54
- package/sdk-core/core-api/src/lib.rs +68 -0
- package/sdk-core/core-api/src/telemetry/metrics.rs +2 -1
- package/sdk-core/core-api/src/telemetry.rs +13 -0
- package/sdk-core/core-c-bridge/Cargo.toml +13 -8
- package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +184 -22
- package/sdk-core/core-c-bridge/src/client.rs +462 -184
- package/sdk-core/core-c-bridge/src/envconfig.rs +314 -0
- package/sdk-core/core-c-bridge/src/lib.rs +1 -0
- package/sdk-core/core-c-bridge/src/random.rs +4 -4
- package/sdk-core/core-c-bridge/src/runtime.rs +22 -23
- package/sdk-core/core-c-bridge/src/testing.rs +1 -4
- package/sdk-core/core-c-bridge/src/tests/context.rs +31 -31
- package/sdk-core/core-c-bridge/src/tests/mod.rs +32 -28
- package/sdk-core/core-c-bridge/src/tests/utils.rs +7 -7
- package/sdk-core/core-c-bridge/src/worker.rs +319 -66
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -1
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +5 -5
- package/sdk-core/sdk/Cargo.toml +8 -2
- package/sdk-core/sdk/src/activity_context.rs +1 -1
- package/sdk-core/sdk/src/app_data.rs +1 -1
- package/sdk-core/sdk/src/interceptors.rs +1 -4
- package/sdk-core/sdk/src/lib.rs +1 -5
- package/sdk-core/sdk/src/workflow_context/options.rs +10 -1
- package/sdk-core/sdk/src/workflow_future.rs +1 -1
- package/sdk-core/sdk-core-protos/Cargo.toml +6 -6
- package/sdk-core/sdk-core-protos/build.rs +10 -23
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +9 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +254 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +234 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +6 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -6
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
- package/sdk-core/{test-utils → sdk-core-protos}/src/canned_histories.rs +5 -5
- package/sdk-core/sdk-core-protos/src/history_builder.rs +2 -2
- package/sdk-core/sdk-core-protos/src/lib.rs +25 -9
- package/sdk-core/sdk-core-protos/src/test_utils.rs +89 -0
- package/sdk-core/sdk-core-protos/src/utilities.rs +14 -5
- package/sdk-core/tests/c_bridge_smoke_test.c +10 -0
- package/sdk-core/tests/cloud_tests.rs +10 -8
- package/sdk-core/tests/common/http_proxy.rs +134 -0
- package/sdk-core/{test-utils/src/lib.rs → tests/common/mod.rs} +214 -281
- package/sdk-core/{test-utils/src → tests/common}/workflows.rs +4 -3
- package/sdk-core/tests/fuzzy_workflow.rs +1 -1
- package/sdk-core/tests/global_metric_tests.rs +8 -7
- package/sdk-core/tests/heavy_tests.rs +7 -3
- package/sdk-core/tests/integ_tests/client_tests.rs +111 -24
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +14 -9
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +4 -4
- package/sdk-core/tests/integ_tests/metrics_tests.rs +114 -14
- package/sdk-core/tests/integ_tests/pagination_tests.rs +273 -0
- package/sdk-core/tests/integ_tests/polling_tests.rs +311 -93
- package/sdk-core/tests/integ_tests/queries_tests.rs +4 -4
- package/sdk-core/tests/integ_tests/update_tests.rs +13 -7
- package/sdk-core/tests/integ_tests/visibility_tests.rs +26 -9
- package/sdk-core/tests/integ_tests/worker_tests.rs +668 -13
- package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +40 -24
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +244 -11
- package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +78 -2
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +61 -2
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +465 -7
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +41 -2
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +315 -3
- package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1990 -14
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +65 -2
- package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +123 -23
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +525 -3
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +65 -16
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +32 -23
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +126 -5
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +1 -2
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +124 -8
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +62 -2
- package/sdk-core/tests/integ_tests/workflow_tests.rs +67 -8
- package/sdk-core/tests/main.rs +26 -17
- package/sdk-core/tests/manual_tests.rs +5 -1
- package/sdk-core/tests/runner.rs +22 -40
- package/sdk-core/tests/shared_tests/mod.rs +1 -1
- package/sdk-core/tests/shared_tests/priority.rs +1 -1
- package/sdk-core/{core/benches/workflow_replay.rs → tests/workflow_replay_bench.rs} +10 -5
- package/src/client.rs +97 -20
- package/src/helpers/callbacks.rs +4 -4
- package/src/helpers/errors.rs +7 -1
- package/src/helpers/handles.rs +1 -0
- package/src/helpers/try_from_js.rs +4 -3
- package/src/lib.rs +3 -2
- package/src/metrics.rs +3 -0
- package/src/runtime.rs +5 -2
- package/src/worker.rs +9 -12
- package/ts/native.ts +13 -3
- package/sdk-core/arch_docs/diagrams/workflow_internals.svg +0 -1
- package/sdk-core/core/src/core_tests/child_workflows.rs +0 -281
- package/sdk-core/core/src/core_tests/determinism.rs +0 -318
- package/sdk-core/core/src/core_tests/local_activities.rs +0 -1442
- package/sdk-core/test-utils/Cargo.toml +0 -38
- package/sdk-core/test-utils/src/histfetch.rs +0 -28
- package/sdk-core/test-utils/src/interceptors.rs +0 -46
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
use crate::common::{CoreWfStarter, build_fake_sdk};
|
|
1
2
|
use temporal_client::WorkflowClientTrait;
|
|
2
3
|
use temporal_sdk::{WfContext, WorkflowResult};
|
|
3
|
-
use
|
|
4
|
-
use
|
|
4
|
+
use temporal_sdk_core::test_help::MockPollCfg;
|
|
5
|
+
use temporal_sdk_core_protos::{
|
|
6
|
+
DEFAULT_WORKFLOW_TYPE, TestHistoryBuilder,
|
|
7
|
+
coresdk::{AsJsonPayloadExt, FromJsonPayloadExt},
|
|
8
|
+
temporal::api::{
|
|
9
|
+
command::v1::{Command, command},
|
|
10
|
+
common::v1::Payload,
|
|
11
|
+
enums::v1::EventType,
|
|
12
|
+
},
|
|
13
|
+
};
|
|
5
14
|
use uuid::Uuid;
|
|
6
15
|
|
|
7
16
|
static FIELD_A: &str = "cat_name";
|
|
@@ -49,3 +58,57 @@ async fn sends_modify_wf_props() {
|
|
|
49
58
|
assert_eq!("enchi", String::from_json_payload(catname).unwrap());
|
|
50
59
|
assert_eq!(9001, usize::from_json_payload(cuteness).unwrap());
|
|
51
60
|
}
|
|
61
|
+
|
|
62
|
+
#[tokio::test]
|
|
63
|
+
async fn workflow_modify_props() {
|
|
64
|
+
let mut t = TestHistoryBuilder::default();
|
|
65
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
66
|
+
t.add_full_wf_task();
|
|
67
|
+
t.add_workflow_execution_completed();
|
|
68
|
+
|
|
69
|
+
let (k1, k2) = ("foo", "bar");
|
|
70
|
+
|
|
71
|
+
let mut mock_cfg = MockPollCfg::from_hist_builder(t);
|
|
72
|
+
mock_cfg.completion_asserts_from_expectations(|mut asserts| {
|
|
73
|
+
asserts.then(|wft| {
|
|
74
|
+
assert_matches!(
|
|
75
|
+
wft.commands.as_slice(),
|
|
76
|
+
[Command {
|
|
77
|
+
attributes: Some(
|
|
78
|
+
command::Attributes::ModifyWorkflowPropertiesCommandAttributes(msg)
|
|
79
|
+
),
|
|
80
|
+
..
|
|
81
|
+
}, ..] => {
|
|
82
|
+
let fields = &msg.upserted_memo.as_ref().unwrap().fields;
|
|
83
|
+
let payload1 = fields.get(k1).unwrap();
|
|
84
|
+
let payload2 = fields.get(k2).unwrap();
|
|
85
|
+
assert_eq!(payload1.data[0], 0x01);
|
|
86
|
+
assert_eq!(payload2.data[0], 0x02);
|
|
87
|
+
assert_eq!(fields.len(), 2);
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
let mut worker = build_fake_sdk(mock_cfg);
|
|
94
|
+
worker.register_wf(DEFAULT_WORKFLOW_TYPE, move |ctx: WfContext| async move {
|
|
95
|
+
ctx.upsert_memo([
|
|
96
|
+
(
|
|
97
|
+
String::from(k1),
|
|
98
|
+
Payload {
|
|
99
|
+
data: vec![0x01],
|
|
100
|
+
..Default::default()
|
|
101
|
+
},
|
|
102
|
+
),
|
|
103
|
+
(
|
|
104
|
+
String::from(k2),
|
|
105
|
+
Payload {
|
|
106
|
+
data: vec![0x02],
|
|
107
|
+
..Default::default()
|
|
108
|
+
},
|
|
109
|
+
),
|
|
110
|
+
]);
|
|
111
|
+
Ok(().into())
|
|
112
|
+
});
|
|
113
|
+
worker.run().await.unwrap();
|
|
114
|
+
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
use crate::
|
|
1
|
+
use crate::{
|
|
2
|
+
common::{CoreWfStarter, WorkflowHandleExt, rand_6_chars},
|
|
3
|
+
integ_tests::mk_nexus_endpoint,
|
|
4
|
+
};
|
|
2
5
|
use anyhow::bail;
|
|
3
6
|
use assert_matches::assert_matches;
|
|
4
|
-
use std::
|
|
7
|
+
use std::{
|
|
8
|
+
sync::{
|
|
9
|
+
Arc,
|
|
10
|
+
atomic::{AtomicBool, Ordering},
|
|
11
|
+
},
|
|
12
|
+
time::Duration,
|
|
13
|
+
};
|
|
5
14
|
use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowOptions};
|
|
6
15
|
use temporal_sdk::{CancellableFuture, NexusOperationOptions, WfContext, WfExitValue};
|
|
7
16
|
use temporal_sdk_core_api::errors::PollError;
|
|
@@ -24,11 +33,11 @@ use temporal_sdk_core_protos::{
|
|
|
24
33
|
},
|
|
25
34
|
},
|
|
26
35
|
};
|
|
27
|
-
use temporal_sdk_core_test_utils::{CoreWfStarter, WorkflowHandleExt, rand_6_chars};
|
|
28
36
|
use tokio::{
|
|
29
37
|
join,
|
|
30
38
|
sync::{mpsc, watch},
|
|
31
39
|
};
|
|
40
|
+
use tokio_stream::StreamExt;
|
|
32
41
|
|
|
33
42
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
34
43
|
enum Outcome {
|
|
@@ -249,6 +258,16 @@ async fn nexus_async(
|
|
|
249
258
|
let client = starter.get_client().await.get_client().clone();
|
|
250
259
|
let nexus_task_handle = async {
|
|
251
260
|
let mut nt = core_worker.poll_nexus_task().await.unwrap().unwrap_task();
|
|
261
|
+
// Verify request header key for timeout exists and is lowercase
|
|
262
|
+
if outcome == Outcome::Timeout {
|
|
263
|
+
assert!(
|
|
264
|
+
nt.request
|
|
265
|
+
.as_ref()
|
|
266
|
+
.unwrap()
|
|
267
|
+
.header
|
|
268
|
+
.contains_key("request-timeout")
|
|
269
|
+
);
|
|
270
|
+
}
|
|
252
271
|
let start_req = assert_matches!(
|
|
253
272
|
nt.request.unwrap().variant.unwrap(),
|
|
254
273
|
request::Variant::StartOperation(sr) => sr
|
|
@@ -557,10 +576,10 @@ async fn nexus_cancellation_types(
|
|
|
557
576
|
let endpoint = mk_nexus_endpoint(&mut starter).await;
|
|
558
577
|
let schedule_to_close_timeout = Some(Duration::from_secs(5));
|
|
559
578
|
|
|
560
|
-
let (
|
|
579
|
+
let (caller_op_future_tx, caller_op_future_rx) = watch::channel(false);
|
|
561
580
|
worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| {
|
|
562
581
|
let endpoint = endpoint.clone();
|
|
563
|
-
let
|
|
582
|
+
let caller_op_future_tx = caller_op_future_tx.clone();
|
|
564
583
|
async move {
|
|
565
584
|
let options = NexusOperationOptions {
|
|
566
585
|
endpoint,
|
|
@@ -577,42 +596,62 @@ async fn nexus_cancellation_types(
|
|
|
577
596
|
started.cancel(&ctx);
|
|
578
597
|
|
|
579
598
|
let res = result.await;
|
|
580
|
-
|
|
599
|
+
caller_op_future_tx.send(true).unwrap();
|
|
581
600
|
|
|
582
|
-
// Make sure cancel after completion doesn't cause problems
|
|
601
|
+
// Make sure cancel after op completion doesn't cause problems
|
|
583
602
|
started.cancel(&ctx);
|
|
584
603
|
|
|
585
604
|
// We need to wait slightly so that the workflow is not complete at the same time
|
|
586
|
-
// cancellation is invoked. If it does, the caller workflow will close and the server
|
|
605
|
+
// cancellation is invoked. If it does, the caller workflow will close and the server
|
|
606
|
+
// won't attempt to send the cancellation to the handler
|
|
587
607
|
ctx.timer(Duration::from_millis(1)).await;
|
|
588
608
|
Ok(res.into())
|
|
589
609
|
}
|
|
590
610
|
});
|
|
591
611
|
|
|
592
|
-
let
|
|
612
|
+
let cancellation_wait_happened = Arc::new(AtomicBool::new(false));
|
|
613
|
+
let cancellation_wait_happened_clone = cancellation_wait_happened.clone();
|
|
593
614
|
let (cancellation_tx, mut cancellation_rx) = watch::channel(false);
|
|
615
|
+
let (handler_exited_tx, mut handler_exited_rx) = watch::channel(false);
|
|
594
616
|
worker.register_wf("async_completer".to_owned(), move |ctx: WfContext| {
|
|
595
617
|
let cancellation_tx = cancellation_tx.clone();
|
|
596
|
-
let
|
|
618
|
+
let cancellation_wait_happened = cancellation_wait_happened_clone.clone();
|
|
619
|
+
let handler_exited_tx = handler_exited_tx.clone();
|
|
597
620
|
async move {
|
|
621
|
+
// Wait for cancellation
|
|
598
622
|
ctx.cancelled().await;
|
|
599
623
|
cancellation_tx.send(true).unwrap();
|
|
624
|
+
|
|
600
625
|
if cancellation_type == NexusOperationCancellationType::WaitCancellationCompleted {
|
|
601
|
-
|
|
626
|
+
ctx.wait_condition(|| cancellation_wait_happened.load(Ordering::Relaxed))
|
|
627
|
+
.await;
|
|
628
|
+
} else if cancellation_type == NexusOperationCancellationType::WaitCancellationRequested
|
|
629
|
+
{
|
|
630
|
+
// For WAIT_REQUESTED, wait until the caller nexus op future has been resolved. This
|
|
631
|
+
// allows the test to verify that it resolved due to
|
|
632
|
+
// NexusOperationCancelRequestCompleted (written after cancel handler responds)
|
|
633
|
+
// rather than NexusOperationCanceled (written after handler workflow completes as
|
|
634
|
+
// cancelled).
|
|
635
|
+
let mut signal_chan = ctx.make_signal_channel("proceed-to-exit");
|
|
636
|
+
signal_chan.next().await;
|
|
602
637
|
}
|
|
638
|
+
|
|
639
|
+
handler_exited_tx.send(true).unwrap();
|
|
603
640
|
Ok(WfExitValue::<()>::Cancelled)
|
|
604
641
|
}
|
|
605
642
|
});
|
|
606
643
|
let submitter = worker.get_submitter_handle();
|
|
607
644
|
let wf_handle = starter.start_with_worker(wf_name, &mut worker).await;
|
|
608
645
|
let client = starter.get_client().await.get_client().clone();
|
|
646
|
+
let (handler_wf_id_tx, mut handler_wf_id_rx) = tokio::sync::oneshot::channel();
|
|
647
|
+
let completer_id = &format!("completer-{}", rand_6_chars());
|
|
609
648
|
let nexus_task_handle = async {
|
|
610
649
|
let nt = core_worker.poll_nexus_task().await.unwrap().unwrap_task();
|
|
611
650
|
let start_req = assert_matches!(
|
|
612
651
|
nt.request.unwrap().variant.unwrap(),
|
|
613
652
|
request::Variant::StartOperation(sr) => sr
|
|
614
653
|
);
|
|
615
|
-
let
|
|
654
|
+
let _ = handler_wf_id_tx.send(completer_id.clone());
|
|
616
655
|
let links = start_req
|
|
617
656
|
.links
|
|
618
657
|
.iter()
|
|
@@ -668,16 +707,19 @@ async fn nexus_cancellation_types(
|
|
|
668
707
|
match cancellation_type {
|
|
669
708
|
NexusOperationCancellationType::WaitCancellationCompleted
|
|
670
709
|
| NexusOperationCancellationType::WaitCancellationRequested => {
|
|
671
|
-
|
|
710
|
+
// The nexus op future should not have been resolved
|
|
711
|
+
assert!(!*caller_op_future_rx.borrow());
|
|
672
712
|
}
|
|
673
713
|
NexusOperationCancellationType::Abandon | NexusOperationCancellationType::TryCancel => {
|
|
674
714
|
wf_handle
|
|
675
715
|
.get_workflow_result(Default::default())
|
|
676
716
|
.await
|
|
677
717
|
.unwrap();
|
|
678
|
-
|
|
718
|
+
// The nexus op future should have been resolved
|
|
719
|
+
assert!(*caller_op_future_rx.borrow())
|
|
679
720
|
}
|
|
680
721
|
}
|
|
722
|
+
let (cancel_handler_responded_tx, _cancel_handler_responded_rx) = watch::channel(false);
|
|
681
723
|
if cancellation_type != NexusOperationCancellationType::Abandon {
|
|
682
724
|
let nt = core_worker.poll_nexus_task().await.unwrap();
|
|
683
725
|
let nt = nt.unwrap_task();
|
|
@@ -686,7 +728,12 @@ async fn nexus_cancellation_types(
|
|
|
686
728
|
request::Variant::CancelOperation(_)
|
|
687
729
|
);
|
|
688
730
|
client
|
|
689
|
-
.cancel_workflow_execution(
|
|
731
|
+
.cancel_workflow_execution(
|
|
732
|
+
completer_id.to_string(),
|
|
733
|
+
None,
|
|
734
|
+
"nexus cancel".to_string(),
|
|
735
|
+
None,
|
|
736
|
+
)
|
|
690
737
|
.await
|
|
691
738
|
.unwrap();
|
|
692
739
|
core_worker
|
|
@@ -702,19 +749,31 @@ async fn nexus_cancellation_types(
|
|
|
702
749
|
})
|
|
703
750
|
.await
|
|
704
751
|
.unwrap();
|
|
752
|
+
// Mark that the cancel handler has responded
|
|
753
|
+
cancel_handler_responded_tx.send(true).unwrap();
|
|
705
754
|
}
|
|
706
755
|
|
|
707
|
-
//
|
|
756
|
+
// Check that the nexus op future resolves only _after_ the handler WF completes
|
|
708
757
|
if cancellation_type == NexusOperationCancellationType::WaitCancellationCompleted {
|
|
709
|
-
assert!(!*
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
758
|
+
assert!(!*caller_op_future_rx.borrow());
|
|
759
|
+
|
|
760
|
+
cancellation_wait_happened.store(true, Ordering::Relaxed);
|
|
761
|
+
// Send a signal just to wake up the workflow so it'll check the condition
|
|
762
|
+
// (it may already have completed, so ignore the result)
|
|
763
|
+
let _ = client
|
|
764
|
+
.signal_workflow_execution(
|
|
765
|
+
completer_id.to_string(),
|
|
766
|
+
"".to_string(),
|
|
767
|
+
"wakeupdude".to_string(),
|
|
768
|
+
None,
|
|
769
|
+
None,
|
|
770
|
+
)
|
|
771
|
+
.await;
|
|
713
772
|
wf_handle
|
|
714
773
|
.get_workflow_result(Default::default())
|
|
715
774
|
.await
|
|
716
775
|
.unwrap();
|
|
717
|
-
assert!(*
|
|
776
|
+
assert!(*caller_op_future_rx.borrow());
|
|
718
777
|
}
|
|
719
778
|
|
|
720
779
|
assert_matches!(
|
|
@@ -724,6 +783,38 @@ async fn nexus_cancellation_types(
|
|
|
724
783
|
};
|
|
725
784
|
|
|
726
785
|
let shutdown_handle = worker.inner_mut().shutdown_handle();
|
|
786
|
+
|
|
787
|
+
let check_caller_op_future_resolved_then_allow_handler_to_complete = async {
|
|
788
|
+
// The caller nexus op future has been resolved
|
|
789
|
+
assert!(*caller_op_future_rx.borrow());
|
|
790
|
+
|
|
791
|
+
// Verify the handler workflow has not exited yet. This proves that the caller op future
|
|
792
|
+
// was resolved as a result of NexusOperationCancelRequestCompleted (written after cancel
|
|
793
|
+
// handler responds), as opposed to NexusOperationCanceled (written after handler workflow
|
|
794
|
+
// exits).
|
|
795
|
+
assert!(
|
|
796
|
+
!*handler_exited_rx.borrow(),
|
|
797
|
+
"Handler should not have exited yet"
|
|
798
|
+
);
|
|
799
|
+
|
|
800
|
+
let handler_wf_id = handler_wf_id_rx
|
|
801
|
+
.try_recv()
|
|
802
|
+
.expect("Should have received handler workflow ID");
|
|
803
|
+
client
|
|
804
|
+
.signal_workflow_execution(
|
|
805
|
+
handler_wf_id,
|
|
806
|
+
"".to_string(),
|
|
807
|
+
"proceed-to-exit".to_string(),
|
|
808
|
+
None,
|
|
809
|
+
None,
|
|
810
|
+
)
|
|
811
|
+
.await
|
|
812
|
+
.unwrap();
|
|
813
|
+
|
|
814
|
+
handler_exited_rx.changed().await.unwrap();
|
|
815
|
+
assert!(*handler_exited_rx.borrow());
|
|
816
|
+
};
|
|
817
|
+
|
|
727
818
|
join!(
|
|
728
819
|
nexus_task_handle,
|
|
729
820
|
async { worker.inner_mut().run().await.unwrap() },
|
|
@@ -735,6 +826,9 @@ async fn nexus_cancellation_types(
|
|
|
735
826
|
if cancellation_type == NexusOperationCancellationType::TryCancel {
|
|
736
827
|
cancellation_rx.changed().await.unwrap();
|
|
737
828
|
}
|
|
829
|
+
if cancellation_type == NexusOperationCancellationType::WaitCancellationRequested {
|
|
830
|
+
check_caller_op_future_resolved_then_allow_handler_to_complete.await;
|
|
831
|
+
}
|
|
738
832
|
shutdown_handle();
|
|
739
833
|
}
|
|
740
834
|
);
|
|
@@ -765,8 +859,14 @@ async fn nexus_cancellation_types(
|
|
|
765
859
|
);
|
|
766
860
|
assert_eq!(f.message, "Nexus operation cancelled after starting");
|
|
767
861
|
}
|
|
768
|
-
NexusOperationCancellationType::WaitCancellationRequested
|
|
769
|
-
|
|
862
|
+
NexusOperationCancellationType::WaitCancellationRequested => {
|
|
863
|
+
let f = assert_matches!(
|
|
864
|
+
res.status,
|
|
865
|
+
Some(nexus_operation_result::Status::Cancelled(f)) => f
|
|
866
|
+
);
|
|
867
|
+
assert_eq!(f.message, "Nexus operation cancellation request completed");
|
|
868
|
+
}
|
|
869
|
+
NexusOperationCancellationType::WaitCancellationCompleted => {
|
|
770
870
|
let f = assert_matches!(
|
|
771
871
|
res.status,
|
|
772
872
|
Some(nexus_operation_result::Status::Cancelled(f)) => f
|