@temporalio/core-bridge 1.1.0 → 1.4.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 +765 -128
- package/Cargo.toml +2 -2
- package/common.js +7 -3
- package/index.d.ts +118 -5
- package/index.js +2 -6
- package/package.json +2 -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/scripts/build.js +4 -3
- package/sdk-core/.buildkite/docker/Dockerfile +2 -1
- package/sdk-core/.buildkite/pipeline.yml +2 -0
- package/sdk-core/.cargo/config.toml +1 -1
- package/sdk-core/ARCHITECTURE.md +2 -2
- package/sdk-core/README.md +12 -0
- package/sdk-core/bridge-ffi/Cargo.toml +2 -2
- package/sdk-core/bridge-ffi/src/lib.rs +2 -2
- package/sdk-core/client/Cargo.toml +7 -5
- package/sdk-core/client/src/lib.rs +354 -226
- package/sdk-core/client/src/metrics.rs +13 -11
- package/sdk-core/client/src/raw.rs +352 -107
- package/sdk-core/client/src/retry.rs +188 -147
- package/sdk-core/client/src/workflow_handle/mod.rs +1 -1
- package/sdk-core/core/Cargo.toml +28 -15
- package/sdk-core/core/src/core_tests/activity_tasks.rs +98 -33
- package/sdk-core/core/src/core_tests/child_workflows.rs +125 -3
- package/sdk-core/core/src/core_tests/local_activities.rs +6 -6
- package/sdk-core/core/src/core_tests/workers.rs +3 -2
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +70 -2
- package/sdk-core/core/src/ephemeral_server/mod.rs +515 -0
- package/sdk-core/core/src/lib.rs +62 -28
- package/sdk-core/core/src/pollers/mod.rs +2 -0
- package/sdk-core/core/src/pollers/poll_buffer.rs +4 -4
- package/sdk-core/core/src/replay/mod.rs +3 -3
- package/sdk-core/core/src/retry_logic.rs +10 -9
- package/sdk-core/core/src/telemetry/metrics.rs +48 -39
- package/sdk-core/core/src/telemetry/mod.rs +46 -12
- package/sdk-core/core/src/telemetry/prometheus_server.rs +17 -13
- package/sdk-core/core/src/test_help/mod.rs +18 -8
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +10 -10
- package/sdk-core/core/src/worker/activities/local_activities.rs +13 -13
- package/sdk-core/core/src/worker/activities.rs +6 -12
- package/sdk-core/core/src/worker/client/mocks.rs +1 -0
- package/sdk-core/core/src/worker/client.rs +193 -64
- package/sdk-core/core/src/worker/mod.rs +14 -19
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -0
- package/sdk-core/core/src/worker/workflow/history_update.rs +5 -5
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +133 -85
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +3 -2
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +160 -105
- package/sdk-core/core/src/worker/workflow/managed_run.rs +2 -1
- package/sdk-core/core/src/worker/workflow/mod.rs +62 -58
- package/sdk-core/core/src/worker/workflow/run_cache.rs +5 -3
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +7 -5
- package/sdk-core/core-api/Cargo.toml +3 -3
- package/sdk-core/core-api/src/errors.rs +3 -11
- package/sdk-core/core-api/src/worker.rs +7 -0
- package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +1 -1
- package/sdk-core/protos/api_upstream/.github/CODEOWNERS +1 -1
- package/sdk-core/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +2 -6
- package/sdk-core/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +29 -0
- package/sdk-core/protos/api_upstream/Makefile +2 -2
- package/sdk-core/protos/api_upstream/buf.yaml +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +86 -0
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +46 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +7 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +14 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +51 -0
- package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +18 -0
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +57 -1
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +1 -3
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -2
- package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +11 -0
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +23 -0
- package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +46 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +172 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -0
- package/sdk-core/protos/grpc/health/v1/health.proto +63 -0
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +18 -15
- package/sdk-core/protos/testsrv_upstream/Makefile +80 -0
- package/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
- package/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
- package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
- package/sdk-core/sdk/Cargo.toml +2 -2
- package/sdk-core/sdk/src/lib.rs +2 -2
- package/sdk-core/sdk/src/workflow_context/options.rs +36 -8
- package/sdk-core/sdk/src/workflow_context.rs +30 -6
- package/sdk-core/sdk/src/workflow_future.rs +4 -4
- package/sdk-core/sdk-core-protos/Cargo.toml +5 -5
- package/sdk-core/sdk-core-protos/build.rs +9 -1
- package/sdk-core/sdk-core-protos/src/history_builder.rs +6 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +93 -32
- package/sdk-core/test-utils/Cargo.toml +3 -3
- package/sdk-core/test-utils/src/canned_histories.rs +58 -0
- package/sdk-core/test-utils/src/lib.rs +35 -12
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +128 -0
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +55 -5
- package/sdk-core/tests/integ_tests/polling_tests.rs +2 -1
- package/sdk-core/tests/integ_tests/queries_tests.rs +5 -5
- package/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -10
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +14 -14
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +2 -6
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +12 -12
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +12 -1
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +3 -3
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +8 -2
- package/sdk-core/tests/integ_tests/workflow_tests.rs +19 -4
- package/sdk-core/tests/load_tests.rs +2 -1
- package/sdk-core/tests/main.rs +17 -0
- package/sdk-core/tests/runner.rs +93 -0
- package/src/conversions.rs +157 -94
- package/src/helpers.rs +190 -0
- package/src/lib.rs +10 -912
- package/src/runtime.rs +436 -0
- package/src/testing.rs +67 -0
- package/src/worker.rs +465 -0
|
@@ -20,6 +20,7 @@ use temporal_client::{
|
|
|
20
20
|
};
|
|
21
21
|
use temporal_sdk::{interceptors::WorkerInterceptor, IntoActivityFunc, Worker, WorkflowFunction};
|
|
22
22
|
use temporal_sdk_core::{
|
|
23
|
+
ephemeral_server::{EphemeralExe, EphemeralExeVersion},
|
|
23
24
|
init_replay_worker, init_worker, telemetry_init, ClientOptions, ClientOptionsBuilder, Logger,
|
|
24
25
|
MetricsExporter, OtelCollectorOptions, TelemetryOptions, TelemetryOptionsBuilder,
|
|
25
26
|
TraceExporter, WorkerConfig, WorkerConfigBuilder,
|
|
@@ -40,11 +41,17 @@ use url::Url;
|
|
|
40
41
|
|
|
41
42
|
pub const NAMESPACE: &str = "default";
|
|
42
43
|
pub const TEST_Q: &str = "q";
|
|
44
|
+
/// The env var used to specify where the integ tests should point
|
|
45
|
+
pub const INTEG_SERVER_TARGET_ENV_VAR: &str = "TEMPORAL_SERVICE_ADDRESS";
|
|
46
|
+
/// This env var is set (to any value) if temporalite is in use
|
|
47
|
+
pub const INTEG_TEMPORALITE_USED_ENV_VAR: &str = "INTEG_TEMPORALITE_ON";
|
|
48
|
+
/// This env var is set (to any value) if the test server is in use
|
|
49
|
+
pub const INTEG_TEST_SERVER_USED_ENV_VAR: &str = "INTEG_TEST_SERVER_ON";
|
|
50
|
+
|
|
43
51
|
/// If set, turn export traces and metrics to the OTel collector at the given URL
|
|
44
52
|
const OTEL_URL_ENV_VAR: &str = "TEMPORAL_INTEG_OTEL_URL";
|
|
45
53
|
/// If set, enable direct scraping of prom metrics on the specified port
|
|
46
54
|
const PROM_ENABLE_ENV_VAR: &str = "TEMPORAL_INTEG_PROM_PORT";
|
|
47
|
-
|
|
48
55
|
/// Create a worker instance which will use the provided test name to base the task queue and wf id
|
|
49
56
|
/// upon. Returns the instance and the task queue name (which is also the workflow id).
|
|
50
57
|
pub async fn init_core_and_create_wf(test_name: &str) -> CoreWfStarter {
|
|
@@ -160,6 +167,7 @@ impl CoreWfStarter {
|
|
|
160
167
|
self.worker_config.task_queue.clone(),
|
|
161
168
|
workflow_id,
|
|
162
169
|
self.task_queue_name.clone(),
|
|
170
|
+
None,
|
|
163
171
|
opts,
|
|
164
172
|
)
|
|
165
173
|
.await
|
|
@@ -319,6 +327,7 @@ impl TestWorker {
|
|
|
319
327
|
self.inner.task_queue().to_string(),
|
|
320
328
|
wfid.clone(),
|
|
321
329
|
workflow_type.into(),
|
|
330
|
+
None,
|
|
322
331
|
options,
|
|
323
332
|
)
|
|
324
333
|
.await?;
|
|
@@ -362,6 +371,8 @@ impl TestWorker {
|
|
|
362
371
|
}
|
|
363
372
|
}
|
|
364
373
|
|
|
374
|
+
pub type BoxDynActivationHook = Box<dyn Fn(&WorkflowActivationCompletion)>;
|
|
375
|
+
|
|
365
376
|
pub enum TestWorkerShutdownCond {
|
|
366
377
|
GetResults(Vec<WorkflowExecutionInfo>, Arc<RetryClient<Client>>),
|
|
367
378
|
NoAutoShutdown,
|
|
@@ -370,7 +381,7 @@ pub enum TestWorkerShutdownCond {
|
|
|
370
381
|
pub struct TestWorkerCompletionIceptor {
|
|
371
382
|
condition: TestWorkerShutdownCond,
|
|
372
383
|
shutdown_handle: Arc<dyn Fn()>,
|
|
373
|
-
every_activation: Option<
|
|
384
|
+
every_activation: Option<BoxDynActivationHook>,
|
|
374
385
|
next: Option<Box<dyn WorkerInterceptor>>,
|
|
375
386
|
}
|
|
376
387
|
impl TestWorkerCompletionIceptor {
|
|
@@ -429,8 +440,10 @@ impl WorkerInterceptor for TestWorkerCompletionIceptor {
|
|
|
429
440
|
}
|
|
430
441
|
}
|
|
431
442
|
|
|
443
|
+
/// Returns the client options used to connect to the server used for integration tests.
|
|
432
444
|
pub fn get_integ_server_options() -> ClientOptions {
|
|
433
|
-
|
|
445
|
+
telemetry_init(&get_integ_telem_options()).expect("Telemetry inits cleanly");
|
|
446
|
+
let temporal_server_address = match env::var(INTEG_SERVER_TARGET_ENV_VAR) {
|
|
434
447
|
Ok(addr) => addr,
|
|
435
448
|
Err(_) => "http://localhost:7233".to_owned(),
|
|
436
449
|
};
|
|
@@ -469,6 +482,16 @@ pub fn get_integ_telem_options() -> TelemetryOptions {
|
|
|
469
482
|
.unwrap()
|
|
470
483
|
}
|
|
471
484
|
|
|
485
|
+
pub fn default_cached_download() -> EphemeralExe {
|
|
486
|
+
EphemeralExe::CachedDownload {
|
|
487
|
+
version: EphemeralExeVersion::Default {
|
|
488
|
+
sdk_name: "sdk-rust".to_string(),
|
|
489
|
+
sdk_version: "0.1.0".to_string(),
|
|
490
|
+
},
|
|
491
|
+
dest_dir: None,
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
472
495
|
pub fn schedule_activity_cmd(
|
|
473
496
|
seq: u32,
|
|
474
497
|
task_q: &str,
|
|
@@ -483,10 +506,10 @@ pub fn schedule_activity_cmd(
|
|
|
483
506
|
activity_type: "test_activity".to_string(),
|
|
484
507
|
namespace: NAMESPACE.to_owned(),
|
|
485
508
|
task_queue: task_q.to_owned(),
|
|
486
|
-
schedule_to_start_timeout: Some(activity_timeout.
|
|
487
|
-
start_to_close_timeout: Some(activity_timeout.
|
|
488
|
-
schedule_to_close_timeout: Some(activity_timeout.
|
|
489
|
-
heartbeat_timeout: Some(heartbeat_timeout.
|
|
509
|
+
schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
510
|
+
start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
511
|
+
schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
512
|
+
heartbeat_timeout: Some(heartbeat_timeout.try_into().expect("duration fits")),
|
|
490
513
|
cancellation_type: cancellation_type as i32,
|
|
491
514
|
..Default::default()
|
|
492
515
|
}
|
|
@@ -503,9 +526,9 @@ pub fn schedule_local_activity_cmd(
|
|
|
503
526
|
seq,
|
|
504
527
|
activity_id: activity_id.to_string(),
|
|
505
528
|
activity_type: "test_activity".to_string(),
|
|
506
|
-
schedule_to_start_timeout: Some(activity_timeout.
|
|
507
|
-
start_to_close_timeout: Some(activity_timeout.
|
|
508
|
-
schedule_to_close_timeout: Some(activity_timeout.
|
|
529
|
+
schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
530
|
+
start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
531
|
+
schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
509
532
|
cancellation_type: cancellation_type as i32,
|
|
510
533
|
..Default::default()
|
|
511
534
|
}
|
|
@@ -515,7 +538,7 @@ pub fn schedule_local_activity_cmd(
|
|
|
515
538
|
pub fn start_timer_cmd(seq: u32, duration: Duration) -> workflow_command::Variant {
|
|
516
539
|
StartTimer {
|
|
517
540
|
seq,
|
|
518
|
-
start_to_fire_timeout: Some(duration.
|
|
541
|
+
start_to_fire_timeout: Some(duration.try_into().expect("duration fits")),
|
|
519
542
|
}
|
|
520
543
|
.into()
|
|
521
544
|
}
|
|
@@ -565,7 +588,7 @@ where
|
|
|
565
588
|
run_id.to_string(),
|
|
566
589
|
vec![StartTimer {
|
|
567
590
|
seq,
|
|
568
|
-
start_to_fire_timeout: Some(duration.
|
|
591
|
+
start_to_fire_timeout: Some(duration.try_into().expect("duration fits")),
|
|
569
592
|
}
|
|
570
593
|
.into()],
|
|
571
594
|
))
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
use std::time::{SystemTime, UNIX_EPOCH};
|
|
2
|
+
use temporal_client::{ClientOptionsBuilder, TestService, WorkflowService};
|
|
3
|
+
use temporal_sdk_core::ephemeral_server::{
|
|
4
|
+
EphemeralExe, EphemeralExeVersion, EphemeralServer, TemporaliteConfigBuilder,
|
|
5
|
+
TestServerConfigBuilder,
|
|
6
|
+
};
|
|
7
|
+
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::DescribeNamespaceRequest;
|
|
8
|
+
use temporal_sdk_core_test_utils::{default_cached_download, NAMESPACE};
|
|
9
|
+
use url::Url;
|
|
10
|
+
|
|
11
|
+
#[tokio::test]
|
|
12
|
+
async fn temporalite_default() {
|
|
13
|
+
let config = TemporaliteConfigBuilder::default()
|
|
14
|
+
.exe(default_cached_download())
|
|
15
|
+
.build()
|
|
16
|
+
.unwrap();
|
|
17
|
+
let mut server = config.start_server().await.unwrap();
|
|
18
|
+
assert_ephemeral_server(&server).await;
|
|
19
|
+
server.shutdown().await.unwrap();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#[tokio::test]
|
|
23
|
+
async fn temporalite_fixed() {
|
|
24
|
+
let config = TemporaliteConfigBuilder::default()
|
|
25
|
+
.exe(fixed_cached_download("v0.1.1"))
|
|
26
|
+
.build()
|
|
27
|
+
.unwrap();
|
|
28
|
+
let mut server = config.start_server().await.unwrap();
|
|
29
|
+
assert_ephemeral_server(&server).await;
|
|
30
|
+
server.shutdown().await.unwrap();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
#[tokio::test]
|
|
34
|
+
async fn temporalite_shutdown_port_reuse() {
|
|
35
|
+
// Start, test shutdown, do again immediately on same port to ensure we can
|
|
36
|
+
// reuse after shutdown
|
|
37
|
+
let config = TemporaliteConfigBuilder::default()
|
|
38
|
+
.exe(default_cached_download())
|
|
39
|
+
.port(Some(10123))
|
|
40
|
+
.build()
|
|
41
|
+
.unwrap();
|
|
42
|
+
let mut server = config.start_server().await.unwrap();
|
|
43
|
+
assert_ephemeral_server(&server).await;
|
|
44
|
+
server.shutdown().await.unwrap();
|
|
45
|
+
let mut server = config.start_server().await.unwrap();
|
|
46
|
+
assert_ephemeral_server(&server).await;
|
|
47
|
+
server.shutdown().await.unwrap();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#[tokio::test]
|
|
51
|
+
async fn test_server_default() {
|
|
52
|
+
let config = TestServerConfigBuilder::default()
|
|
53
|
+
.exe(default_cached_download())
|
|
54
|
+
.build()
|
|
55
|
+
.unwrap();
|
|
56
|
+
let mut server = config.start_server().await.unwrap();
|
|
57
|
+
assert_ephemeral_server(&server).await;
|
|
58
|
+
server.shutdown().await.unwrap();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#[tokio::test]
|
|
62
|
+
async fn test_server_fixed() {
|
|
63
|
+
let config = TestServerConfigBuilder::default()
|
|
64
|
+
.exe(fixed_cached_download("v1.16.0"))
|
|
65
|
+
.build()
|
|
66
|
+
.unwrap();
|
|
67
|
+
let mut server = config.start_server().await.unwrap();
|
|
68
|
+
assert_ephemeral_server(&server).await;
|
|
69
|
+
server.shutdown().await.unwrap();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#[tokio::test]
|
|
73
|
+
async fn test_server_shutdown_port_reuse() {
|
|
74
|
+
// Start, test shutdown, do again immediately on same port to ensure we can
|
|
75
|
+
// reuse after shutdown
|
|
76
|
+
let config = TestServerConfigBuilder::default()
|
|
77
|
+
.exe(default_cached_download())
|
|
78
|
+
.port(Some(10124))
|
|
79
|
+
.build()
|
|
80
|
+
.unwrap();
|
|
81
|
+
let mut server = config.start_server().await.unwrap();
|
|
82
|
+
assert_ephemeral_server(&server).await;
|
|
83
|
+
server.shutdown().await.unwrap();
|
|
84
|
+
let mut server = config.start_server().await.unwrap();
|
|
85
|
+
assert_ephemeral_server(&server).await;
|
|
86
|
+
server.shutdown().await.unwrap();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
fn fixed_cached_download(version: &str) -> EphemeralExe {
|
|
90
|
+
EphemeralExe::CachedDownload {
|
|
91
|
+
version: EphemeralExeVersion::Fixed(version.to_string()),
|
|
92
|
+
dest_dir: None,
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async fn assert_ephemeral_server(server: &EphemeralServer) {
|
|
97
|
+
// Connect and describe namespace
|
|
98
|
+
let mut client = ClientOptionsBuilder::default()
|
|
99
|
+
.identity("integ_tester".to_string())
|
|
100
|
+
.target_url(Url::try_from(&*format!("http://{}", server.target)).unwrap())
|
|
101
|
+
.client_name("temporal-core".to_string())
|
|
102
|
+
.client_version("0.1.0".to_string())
|
|
103
|
+
.build()
|
|
104
|
+
.unwrap()
|
|
105
|
+
.connect_no_namespace(None, None)
|
|
106
|
+
.await
|
|
107
|
+
.unwrap();
|
|
108
|
+
let resp = client
|
|
109
|
+
.describe_namespace(DescribeNamespaceRequest {
|
|
110
|
+
namespace: NAMESPACE.to_string(),
|
|
111
|
+
..Default::default()
|
|
112
|
+
})
|
|
113
|
+
.await
|
|
114
|
+
.unwrap();
|
|
115
|
+
assert!(resp.into_inner().namespace_info.unwrap().name == "default");
|
|
116
|
+
|
|
117
|
+
// If it has test service, make sure we can use it too
|
|
118
|
+
if server.has_test_service {
|
|
119
|
+
let resp = client.get_current_time(()).await.unwrap();
|
|
120
|
+
// Make sure it's within 5 mins of now
|
|
121
|
+
let resp_seconds = resp.get_ref().time.as_ref().unwrap().seconds as u64;
|
|
122
|
+
let curr_seconds = SystemTime::now()
|
|
123
|
+
.duration_since(UNIX_EPOCH)
|
|
124
|
+
.unwrap()
|
|
125
|
+
.as_secs();
|
|
126
|
+
assert!(curr_seconds - 300 < resp_seconds && curr_seconds + 300 > resp_seconds);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
use assert_matches::assert_matches;
|
|
2
2
|
use std::time::Duration;
|
|
3
|
+
use temporal_client::{WfClientExt, WorkflowOptions};
|
|
4
|
+
use temporal_sdk::{ActContext, ActivityOptions, WfContext};
|
|
3
5
|
use temporal_sdk_core_protos::{
|
|
4
6
|
coresdk::{
|
|
5
7
|
activity_result::{
|
|
@@ -9,12 +11,12 @@ use temporal_sdk_core_protos::{
|
|
|
9
11
|
workflow_activation::{workflow_activation_job, ResolveActivity, WorkflowActivationJob},
|
|
10
12
|
workflow_commands::{ActivityCancellationType, ScheduleActivity},
|
|
11
13
|
workflow_completion::WorkflowActivationCompletion,
|
|
12
|
-
ActivityHeartbeat, ActivityTaskCompletion, IntoCompletion,
|
|
14
|
+
ActivityHeartbeat, ActivityTaskCompletion, AsJsonPayloadExt, IntoCompletion,
|
|
13
15
|
},
|
|
14
16
|
temporal::api::common::v1::{Payload, RetryPolicy},
|
|
15
17
|
};
|
|
16
18
|
use temporal_sdk_core_test_utils::{
|
|
17
|
-
init_core_and_create_wf, schedule_activity_cmd, WorkerTestHelpers,
|
|
19
|
+
init_core_and_create_wf, schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
|
|
18
20
|
};
|
|
19
21
|
use tokio::time::sleep;
|
|
20
22
|
|
|
@@ -103,14 +105,14 @@ async fn many_act_fails_with_heartbeats() {
|
|
|
103
105
|
activity_id: activity_id.to_string(),
|
|
104
106
|
activity_type: "test_act".to_string(),
|
|
105
107
|
task_queue: starter.get_task_queue().to_string(),
|
|
106
|
-
start_to_close_timeout: Some(
|
|
108
|
+
start_to_close_timeout: Some(prost_dur!(from_secs(30))),
|
|
107
109
|
retry_policy: Some(RetryPolicy {
|
|
108
|
-
initial_interval: Some(
|
|
110
|
+
initial_interval: Some(prost_dur!(from_millis(10))),
|
|
109
111
|
backoff_coefficient: 1.0,
|
|
110
112
|
maximum_attempts: 4,
|
|
111
113
|
..Default::default()
|
|
112
114
|
}),
|
|
113
|
-
heartbeat_timeout: Some(
|
|
115
|
+
heartbeat_timeout: Some(prost_dur!(from_secs(1))),
|
|
114
116
|
..Default::default()
|
|
115
117
|
}
|
|
116
118
|
.into(),
|
|
@@ -166,3 +168,51 @@ async fn many_act_fails_with_heartbeats() {
|
|
|
166
168
|
core.complete_execution(&task.run_id).await;
|
|
167
169
|
core.shutdown().await;
|
|
168
170
|
}
|
|
171
|
+
|
|
172
|
+
#[tokio::test]
|
|
173
|
+
async fn activity_doesnt_heartbeat_hits_timeout_then_completes() {
|
|
174
|
+
let wf_name = "activity_doesnt_heartbeat_hits_timeout_then_completes";
|
|
175
|
+
let mut starter = CoreWfStarter::new(wf_name);
|
|
176
|
+
let mut worker = starter.worker().await;
|
|
177
|
+
let client = starter.get_client().await;
|
|
178
|
+
worker.register_activity(
|
|
179
|
+
"echo_activity",
|
|
180
|
+
|_ctx: ActContext, echo_me: String| async move {
|
|
181
|
+
sleep(Duration::from_secs(4)).await;
|
|
182
|
+
Ok(echo_me)
|
|
183
|
+
},
|
|
184
|
+
);
|
|
185
|
+
worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
|
|
186
|
+
let res = ctx
|
|
187
|
+
.activity(ActivityOptions {
|
|
188
|
+
activity_type: "echo_activity".to_string(),
|
|
189
|
+
input: "hi!".as_json_payload().expect("serializes fine"),
|
|
190
|
+
start_to_close_timeout: Some(Duration::from_secs(10)),
|
|
191
|
+
heartbeat_timeout: Some(Duration::from_secs(2)),
|
|
192
|
+
retry_policy: Some(RetryPolicy {
|
|
193
|
+
maximum_attempts: 1,
|
|
194
|
+
..Default::default()
|
|
195
|
+
}),
|
|
196
|
+
..Default::default()
|
|
197
|
+
})
|
|
198
|
+
.await;
|
|
199
|
+
assert!(res.timed_out());
|
|
200
|
+
Ok(().into())
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
let run_id = worker
|
|
204
|
+
.submit_wf(
|
|
205
|
+
wf_name.to_owned(),
|
|
206
|
+
wf_name.to_owned(),
|
|
207
|
+
vec![],
|
|
208
|
+
WorkflowOptions::default(),
|
|
209
|
+
)
|
|
210
|
+
.await
|
|
211
|
+
.unwrap();
|
|
212
|
+
worker.run_until_done().await.unwrap();
|
|
213
|
+
let handle = client.get_untyped_workflow_handle(wf_name, run_id);
|
|
214
|
+
handle
|
|
215
|
+
.get_workflow_result(Default::default())
|
|
216
|
+
.await
|
|
217
|
+
.unwrap();
|
|
218
|
+
}
|
|
@@ -36,7 +36,7 @@ async fn out_of_order_completion_doesnt_hang() {
|
|
|
36
36
|
),
|
|
37
37
|
StartTimer {
|
|
38
38
|
seq: 1,
|
|
39
|
-
start_to_fire_timeout: Some(
|
|
39
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
|
|
40
40
|
}
|
|
41
41
|
.into(),
|
|
42
42
|
]
|
|
@@ -133,6 +133,7 @@ async fn can_paginate_long_history() {
|
|
|
133
133
|
worker.run_until_done().await.unwrap();
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
+
// TODO: Takes ages now, fix somehow
|
|
136
137
|
#[tokio::test]
|
|
137
138
|
async fn poll_of_nonexistent_namespace_is_fatal() {
|
|
138
139
|
let mut starter = CoreWfStarter::new("whatever_yo");
|
|
@@ -24,12 +24,12 @@ async fn simple_query_legacy() {
|
|
|
24
24
|
vec![
|
|
25
25
|
StartTimer {
|
|
26
26
|
seq: 0,
|
|
27
|
-
start_to_fire_timeout: Some(
|
|
27
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(500))),
|
|
28
28
|
}
|
|
29
29
|
.into(),
|
|
30
30
|
StartTimer {
|
|
31
31
|
seq: 1,
|
|
32
|
-
start_to_fire_timeout: Some(
|
|
32
|
+
start_to_fire_timeout: Some(prost_dur!(from_secs(3))),
|
|
33
33
|
}
|
|
34
34
|
.into(),
|
|
35
35
|
],
|
|
@@ -105,7 +105,7 @@ async fn simple_query_legacy() {
|
|
|
105
105
|
assert_eq!(&q_resp.unwrap()[0].data, query_resp);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
#[rstest
|
|
108
|
+
#[rstest]
|
|
109
109
|
#[case::no_eviction(false)]
|
|
110
110
|
#[case::with_eviction(true)]
|
|
111
111
|
#[tokio::test]
|
|
@@ -343,12 +343,12 @@ async fn fail_legacy_query() {
|
|
|
343
343
|
let t1_resp = vec![
|
|
344
344
|
StartTimer {
|
|
345
345
|
seq: 1,
|
|
346
|
-
start_to_fire_timeout: Some(
|
|
346
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(500))),
|
|
347
347
|
}
|
|
348
348
|
.into(),
|
|
349
349
|
StartTimer {
|
|
350
350
|
seq: 2,
|
|
351
|
-
start_to_fire_timeout: Some(
|
|
351
|
+
start_to_fire_timeout: Some(prost_dur!(from_secs(3))),
|
|
352
352
|
}
|
|
353
353
|
.into(),
|
|
354
354
|
];
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
use assert_matches::assert_matches;
|
|
2
|
+
use std::{sync::Arc, time::Duration};
|
|
3
|
+
use temporal_client::{
|
|
4
|
+
ListClosedFilters, ListOpenFilters, Namespace, StartTimeFilter, WorkflowClientTrait,
|
|
5
|
+
WorkflowExecutionFilter, WorkflowOptions,
|
|
6
|
+
};
|
|
7
|
+
use temporal_sdk_core_protos::coresdk::workflow_activation::{
|
|
8
|
+
workflow_activation_job, WorkflowActivationJob,
|
|
9
|
+
};
|
|
10
|
+
use temporal_sdk_core_test_utils::{
|
|
11
|
+
get_integ_server_options, CoreWfStarter, WorkerTestHelpers, NAMESPACE,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
#[tokio::test]
|
|
15
|
+
async fn client_list_open_closed_workflow_executions() {
|
|
16
|
+
let wf_name = "client_list_open_closed_workflow_executions".to_owned();
|
|
17
|
+
let mut starter = CoreWfStarter::new(&wf_name);
|
|
18
|
+
let core = starter.get_worker().await;
|
|
19
|
+
let client = starter.get_client().await;
|
|
20
|
+
|
|
21
|
+
let earliest = std::time::SystemTime::now();
|
|
22
|
+
let latest = earliest + Duration::from_secs(60);
|
|
23
|
+
|
|
24
|
+
// start workflow
|
|
25
|
+
let run_id = starter
|
|
26
|
+
.start_wf_with_id(wf_name.to_owned(), WorkflowOptions::default())
|
|
27
|
+
.await;
|
|
28
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
29
|
+
assert_matches!(
|
|
30
|
+
task.jobs.as_slice(),
|
|
31
|
+
[WorkflowActivationJob {
|
|
32
|
+
variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
|
|
33
|
+
}]
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// List above OPEN workflow
|
|
37
|
+
let start_time_filter = StartTimeFilter {
|
|
38
|
+
earliest_time: Some(earliest).and_then(|t| t.try_into().ok()),
|
|
39
|
+
latest_time: Some(latest).and_then(|t| t.try_into().ok()),
|
|
40
|
+
};
|
|
41
|
+
let filter = ListOpenFilters::ExecutionFilter(WorkflowExecutionFilter {
|
|
42
|
+
workflow_id: wf_name.clone(),
|
|
43
|
+
run_id: "".to_owned(),
|
|
44
|
+
});
|
|
45
|
+
let open_workflows = client
|
|
46
|
+
.list_open_workflow_executions(1, Default::default(), Some(start_time_filter), Some(filter))
|
|
47
|
+
.await
|
|
48
|
+
.unwrap();
|
|
49
|
+
assert_eq!(open_workflows.executions.len(), 1);
|
|
50
|
+
let workflow = open_workflows.executions[0].clone();
|
|
51
|
+
assert_eq!(workflow.execution.as_ref().unwrap().workflow_id, wf_name);
|
|
52
|
+
|
|
53
|
+
// Complete workflow
|
|
54
|
+
core.complete_execution(&task.run_id).await;
|
|
55
|
+
|
|
56
|
+
// List above CLOSED workflow
|
|
57
|
+
let start_time_filter = StartTimeFilter {
|
|
58
|
+
earliest_time: Some(earliest).and_then(|t| t.try_into().ok()),
|
|
59
|
+
latest_time: Some(latest).and_then(|t| t.try_into().ok()),
|
|
60
|
+
};
|
|
61
|
+
let filter = ListClosedFilters::ExecutionFilter(WorkflowExecutionFilter {
|
|
62
|
+
workflow_id: wf_name.clone(),
|
|
63
|
+
run_id,
|
|
64
|
+
});
|
|
65
|
+
let closed_workflows = client
|
|
66
|
+
.list_closed_workflow_executions(
|
|
67
|
+
1,
|
|
68
|
+
Default::default(),
|
|
69
|
+
Some(start_time_filter),
|
|
70
|
+
Some(filter),
|
|
71
|
+
)
|
|
72
|
+
.await
|
|
73
|
+
.unwrap();
|
|
74
|
+
assert_eq!(closed_workflows.executions.len(), 1);
|
|
75
|
+
let workflow = closed_workflows.executions[0].clone();
|
|
76
|
+
assert_eq!(workflow.execution.as_ref().unwrap().workflow_id, wf_name);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#[tokio::test]
|
|
80
|
+
async fn client_describe_namespace() {
|
|
81
|
+
let client = Arc::new(
|
|
82
|
+
get_integ_server_options()
|
|
83
|
+
.connect(NAMESPACE.to_owned(), None, None)
|
|
84
|
+
.await
|
|
85
|
+
.expect("Must connect"),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
let namespace_result = client
|
|
89
|
+
.describe_namespace(Namespace::Name(NAMESPACE.to_owned()))
|
|
90
|
+
.await
|
|
91
|
+
.unwrap();
|
|
92
|
+
assert_eq!(namespace_result.namespace_info.unwrap().name, NAMESPACE);
|
|
93
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
use assert_matches::assert_matches;
|
|
2
2
|
use std::time::Duration;
|
|
3
3
|
use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowExecutionResult, WorkflowOptions};
|
|
4
|
-
use temporal_sdk::{
|
|
4
|
+
use temporal_sdk::{
|
|
5
|
+
ActContext, ActExitValue, ActivityOptions, CancellableFuture, WfContext, WorkflowResult,
|
|
6
|
+
};
|
|
5
7
|
use temporal_sdk_core_protos::{
|
|
6
8
|
coresdk::{
|
|
7
9
|
activity_result::{
|
|
8
|
-
self, activity_resolution
|
|
9
|
-
ActivityResolution,
|
|
10
|
+
self, activity_resolution as act_res, ActivityExecutionResult, ActivityResolution,
|
|
10
11
|
},
|
|
11
12
|
activity_task::activity_task as act_task,
|
|
12
13
|
workflow_activation::{
|
|
@@ -14,13 +15,15 @@ use temporal_sdk_core_protos::{
|
|
|
14
15
|
},
|
|
15
16
|
workflow_commands::{ActivityCancellationType, RequestCancelActivity, StartTimer},
|
|
16
17
|
workflow_completion::WorkflowActivationCompletion,
|
|
17
|
-
ActivityHeartbeat, ActivityTaskCompletion, AsJsonPayloadExt,
|
|
18
|
+
ActivityHeartbeat, ActivityTaskCompletion, AsJsonPayloadExt, FromJsonPayloadExt,
|
|
19
|
+
IntoCompletion,
|
|
18
20
|
},
|
|
19
21
|
temporal::api::{
|
|
20
22
|
common::v1::{ActivityType, Payload, Payloads},
|
|
21
23
|
enums::v1::RetryState,
|
|
22
24
|
failure::v1::{failure::FailureInfo, ActivityFailureInfo, Failure},
|
|
23
25
|
},
|
|
26
|
+
TaskToken,
|
|
24
27
|
};
|
|
25
28
|
use temporal_sdk_core_test_utils::{
|
|
26
29
|
init_core_and_create_wf, schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
|
|
@@ -297,7 +300,7 @@ async fn activity_cancellation_try_cancel() {
|
|
|
297
300
|
),
|
|
298
301
|
StartTimer {
|
|
299
302
|
seq: 1,
|
|
300
|
-
start_to_fire_timeout: Some(
|
|
303
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
|
|
301
304
|
}
|
|
302
305
|
.into(),
|
|
303
306
|
]
|
|
@@ -359,7 +362,7 @@ async fn activity_cancellation_plus_complete_doesnt_double_resolve() {
|
|
|
359
362
|
),
|
|
360
363
|
StartTimer {
|
|
361
364
|
seq: 1,
|
|
362
|
-
start_to_fire_timeout: Some(
|
|
365
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
|
|
363
366
|
}
|
|
364
367
|
.into(),
|
|
365
368
|
]
|
|
@@ -390,7 +393,7 @@ async fn activity_cancellation_plus_complete_doesnt_double_resolve() {
|
|
|
390
393
|
variant: Some(workflow_activation_job::Variant::ResolveActivity(
|
|
391
394
|
ResolveActivity {
|
|
392
395
|
result: Some(ActivityResolution {
|
|
393
|
-
status: Some(
|
|
396
|
+
status: Some(act_res::Status::Cancelled(_))
|
|
394
397
|
}),
|
|
395
398
|
..
|
|
396
399
|
}
|
|
@@ -403,7 +406,7 @@ async fn activity_cancellation_plus_complete_doesnt_double_resolve() {
|
|
|
403
406
|
task.run_id,
|
|
404
407
|
vec![StartTimer {
|
|
405
408
|
seq: 2,
|
|
406
|
-
start_to_fire_timeout: Some(
|
|
409
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(100))),
|
|
407
410
|
}
|
|
408
411
|
.into()],
|
|
409
412
|
))
|
|
@@ -506,7 +509,7 @@ async fn activity_cancellation_wait_cancellation_completed() {
|
|
|
506
509
|
),
|
|
507
510
|
StartTimer {
|
|
508
511
|
seq: 1,
|
|
509
|
-
start_to_fire_timeout: Some(
|
|
512
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
|
|
510
513
|
}
|
|
511
514
|
.into(),
|
|
512
515
|
]
|
|
@@ -573,7 +576,7 @@ async fn activity_cancellation_abandon() {
|
|
|
573
576
|
),
|
|
574
577
|
StartTimer {
|
|
575
578
|
seq: 1,
|
|
576
|
-
start_to_fire_timeout: Some(
|
|
579
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(50))),
|
|
577
580
|
}
|
|
578
581
|
.into(),
|
|
579
582
|
]
|
|
@@ -793,3 +796,83 @@ async fn one_activity_abandon_cancelled_after_complete() {
|
|
|
793
796
|
.unwrap();
|
|
794
797
|
assert_matches!(res, WorkflowExecutionResult::Succeeded(_));
|
|
795
798
|
}
|
|
799
|
+
|
|
800
|
+
#[tokio::test]
|
|
801
|
+
async fn it_can_complete_async() {
|
|
802
|
+
use std::sync::Arc;
|
|
803
|
+
use tokio::sync::Mutex;
|
|
804
|
+
|
|
805
|
+
let wf_name = "it_can_complete_async".to_owned();
|
|
806
|
+
let mut starter = CoreWfStarter::new(&wf_name);
|
|
807
|
+
let mut worker = starter.worker().await;
|
|
808
|
+
let client = starter.get_client().await;
|
|
809
|
+
let async_response = "agence";
|
|
810
|
+
let shared_token: Arc<Mutex<Option<Vec<u8>>>> = Arc::new(Mutex::new(None));
|
|
811
|
+
worker.register_wf(wf_name.clone(), move |ctx: WfContext| async move {
|
|
812
|
+
let activity_resolution = ctx
|
|
813
|
+
.activity(ActivityOptions {
|
|
814
|
+
activity_type: "complete_async_activity".to_string(),
|
|
815
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
816
|
+
start_to_close_timeout: Some(Duration::from_secs(30)),
|
|
817
|
+
..Default::default()
|
|
818
|
+
})
|
|
819
|
+
.await;
|
|
820
|
+
|
|
821
|
+
let res = match activity_resolution.status {
|
|
822
|
+
Some(act_res::Status::Completed(activity_result::Success { result })) => result
|
|
823
|
+
.map(|p| String::from_json_payload(&p).unwrap())
|
|
824
|
+
.unwrap(),
|
|
825
|
+
_ => panic!("activity task failed {:?}", activity_resolution),
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
assert_eq!(&res, async_response);
|
|
829
|
+
Ok(().into())
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
let shared_token_ref = shared_token.clone();
|
|
833
|
+
worker.register_activity(
|
|
834
|
+
"complete_async_activity",
|
|
835
|
+
move |ctx: ActContext, _: String| {
|
|
836
|
+
let shared_token_ref = shared_token_ref.clone();
|
|
837
|
+
async move {
|
|
838
|
+
// set the `activity_task_token`
|
|
839
|
+
let activity_info = ctx.get_info();
|
|
840
|
+
let task_token = &activity_info.task_token;
|
|
841
|
+
let mut shared = shared_token_ref.lock().await;
|
|
842
|
+
*shared = Some(task_token.clone());
|
|
843
|
+
Ok::<ActExitValue<()>, _>(ActExitValue::WillCompleteAsync)
|
|
844
|
+
}
|
|
845
|
+
},
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
let shared_token_ref2 = shared_token.clone();
|
|
849
|
+
tokio::spawn(async move {
|
|
850
|
+
loop {
|
|
851
|
+
let mut shared = shared_token_ref2.lock().await;
|
|
852
|
+
let maybe_token = shared.take();
|
|
853
|
+
|
|
854
|
+
if let Some(task_token) = maybe_token {
|
|
855
|
+
client
|
|
856
|
+
.complete_activity_task(
|
|
857
|
+
TaskToken(task_token),
|
|
858
|
+
Some(async_response.as_json_payload().unwrap().into()),
|
|
859
|
+
)
|
|
860
|
+
.await
|
|
861
|
+
.unwrap();
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
let _run_id = worker
|
|
868
|
+
.submit_wf(
|
|
869
|
+
wf_name.to_owned(),
|
|
870
|
+
wf_name.to_owned(),
|
|
871
|
+
vec![],
|
|
872
|
+
WorkflowOptions::default(),
|
|
873
|
+
)
|
|
874
|
+
.await
|
|
875
|
+
.unwrap();
|
|
876
|
+
|
|
877
|
+
worker.run_until_done().await.unwrap();
|
|
878
|
+
}
|
|
@@ -39,7 +39,7 @@ async fn cancel_during_timer() {
|
|
|
39
39
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
|
40
40
|
// Cancel the workflow externally
|
|
41
41
|
client
|
|
42
|
-
.cancel_workflow_execution(wf_name.to_string(), None, "Dieee".to_string())
|
|
42
|
+
.cancel_workflow_execution(wf_name.to_string(), None, "Dieee".to_string(), None)
|
|
43
43
|
.await
|
|
44
44
|
.unwrap();
|
|
45
45
|
};
|