@temporalio/core-bridge 1.11.6 → 1.11.8
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 +902 -468
- 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 +5 -0
- package/sdk-core/.github/workflows/per-pr.yml +59 -5
- package/sdk-core/Cargo.toml +3 -2
- package/sdk-core/client/Cargo.toml +3 -3
- package/sdk-core/client/src/lib.rs +154 -161
- package/sdk-core/client/src/metrics.rs +15 -8
- package/sdk-core/client/src/proxy.rs +1 -1
- package/sdk-core/client/src/raw.rs +176 -33
- package/sdk-core/client/src/retry.rs +102 -465
- package/sdk-core/client/src/worker_registry/mod.rs +2 -2
- package/sdk-core/client/src/workflow_handle/mod.rs +19 -1
- package/sdk-core/core/Cargo.toml +12 -14
- package/sdk-core/core/benches/workflow_replay.rs +1 -1
- package/sdk-core/core/src/abstractions.rs +2 -2
- package/sdk-core/core/src/core_tests/activity_tasks.rs +99 -46
- package/sdk-core/core/src/core_tests/child_workflows.rs +68 -9
- package/sdk-core/core/src/core_tests/determinism.rs +2 -2
- package/sdk-core/core/src/core_tests/local_activities.rs +20 -33
- package/sdk-core/core/src/core_tests/mod.rs +7 -8
- package/sdk-core/core/src/core_tests/queries.rs +79 -79
- package/sdk-core/core/src/core_tests/replay_flag.rs +5 -5
- package/sdk-core/core/src/core_tests/updates.rs +6 -6
- package/sdk-core/core/src/core_tests/workers.rs +19 -22
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +3 -3
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +154 -106
- package/sdk-core/core/src/ephemeral_server/mod.rs +66 -10
- package/sdk-core/core/src/internal_flags.rs +103 -12
- package/sdk-core/core/src/lib.rs +21 -13
- package/sdk-core/core/src/pollers/mod.rs +200 -6
- package/sdk-core/core/src/pollers/poll_buffer.rs +32 -8
- package/sdk-core/core/src/protosext/mod.rs +7 -7
- package/sdk-core/core/src/protosext/protocol_messages.rs +2 -2
- package/sdk-core/core/src/replay/mod.rs +8 -9
- package/sdk-core/core/src/retry_logic.rs +8 -6
- package/sdk-core/core/src/telemetry/log_export.rs +4 -4
- package/sdk-core/core/src/telemetry/metrics.rs +111 -25
- package/sdk-core/core/src/telemetry/mod.rs +11 -4
- package/sdk-core/core/src/telemetry/otel.rs +108 -144
- package/sdk-core/core/src/telemetry/prometheus_server.rs +1 -4
- package/sdk-core/core/src/test_help/mod.rs +27 -21
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +7 -5
- package/sdk-core/core/src/worker/activities/local_activities.rs +9 -9
- package/sdk-core/core/src/worker/activities.rs +34 -46
- package/sdk-core/core/src/worker/client/mocks.rs +24 -2
- package/sdk-core/core/src/worker/client.rs +169 -33
- package/sdk-core/core/src/worker/mod.rs +132 -56
- package/sdk-core/core/src/worker/nexus.rs +410 -0
- package/sdk-core/core/src/worker/tuner/resource_based.rs +27 -5
- package/sdk-core/core/src/worker/tuner.rs +29 -2
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +8 -3
- package/sdk-core/core/src/worker/workflow/history_update.rs +5 -8
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +83 -87
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +38 -38
- package/sdk-core/core/src/worker/workflow/machines/cancel_nexus_op_state_machine.rs +117 -0
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +8 -18
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +114 -108
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +16 -31
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -14
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +8 -15
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +34 -75
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +26 -48
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +10 -17
- package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +543 -0
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +22 -31
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +53 -51
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +40 -45
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
- package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +8 -10
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +24 -30
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +182 -116
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +4 -8
- package/sdk-core/core/src/worker/workflow/managed_run.rs +75 -45
- package/sdk-core/core/src/worker/workflow/mod.rs +104 -55
- package/sdk-core/core/src/worker/workflow/run_cache.rs +23 -4
- package/sdk-core/core/src/worker/workflow/wft_extraction.rs +4 -4
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +3 -3
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +32 -13
- package/sdk-core/core-api/Cargo.toml +2 -3
- package/sdk-core/core-api/src/errors.rs +22 -20
- package/sdk-core/core-api/src/lib.rs +24 -5
- package/sdk-core/core-api/src/telemetry/metrics.rs +27 -1
- package/sdk-core/core-api/src/telemetry.rs +37 -3
- package/sdk-core/core-api/src/worker.rs +36 -3
- package/sdk-core/docker/docker-compose-ci.yaml +25 -0
- package/sdk-core/etc/otel-collector-ci.yaml +36 -0
- package/sdk-core/etc/otel-collector-config.yaml +3 -3
- package/sdk-core/etc/prometheus.yaml +1 -1
- package/sdk-core/fsm/Cargo.toml +1 -1
- package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +3 -4
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
- package/sdk-core/fsm/rustfsm_trait/Cargo.toml +1 -1
- package/sdk-core/sdk/Cargo.toml +1 -2
- package/sdk-core/sdk/src/activity_context.rs +1 -1
- package/sdk-core/sdk/src/interceptors.rs +1 -1
- package/sdk-core/sdk/src/lib.rs +126 -54
- package/sdk-core/sdk/src/workflow_context/options.rs +184 -74
- package/sdk-core/sdk/src/workflow_context.rs +193 -79
- package/sdk-core/sdk/src/workflow_future.rs +151 -131
- package/sdk-core/sdk-core-protos/Cargo.toml +3 -4
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -1
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/account/v1/message.proto +46 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +254 -5
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +108 -2
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +94 -15
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +102 -4
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/nexus/v1/message.proto +84 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +25 -10
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +14 -1
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/resource/v1/message.proto +25 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/sink/v1/message.proto +41 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/usage/v1/message.proto +59 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +135 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/push-to-buf.yml +20 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-delete-release.yml +13 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-publish-release.yml +13 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +13 -21
- package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +2 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +1 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +3386 -1047
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +3529 -1144
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +39 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +6 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +39 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +252 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +1 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/common.proto +6 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/deployment.proto +96 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/nexus.proto +42 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/workflow.proto +43 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/errordetails/v1/message.proto +13 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +14 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +70 -12
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +12 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/query/v1/message.proto +9 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +46 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +206 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +482 -97
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +230 -43
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/core_interface.proto +6 -0
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/nexus/nexus.proto +71 -0
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +46 -2
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +55 -9
- package/sdk-core/sdk-core-protos/src/history_builder.rs +5 -5
- package/sdk-core/sdk-core-protos/src/history_info.rs +5 -6
- package/sdk-core/sdk-core-protos/src/lib.rs +414 -34
- package/sdk-core/sdk-core-protos/src/task_token.rs +1 -1
- package/sdk-core/test-utils/Cargo.toml +3 -11
- package/sdk-core/test-utils/src/canned_histories.rs +1 -1
- package/sdk-core/test-utils/src/lib.rs +159 -85
- package/sdk-core/tests/fuzzy_workflow.rs +3 -3
- package/sdk-core/tests/heavy_tests.rs +3 -3
- package/sdk-core/tests/integ_tests/client_tests.rs +171 -20
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +45 -39
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +7 -6
- package/sdk-core/tests/integ_tests/metrics_tests.rs +492 -35
- package/sdk-core/tests/integ_tests/polling_tests.rs +7 -5
- package/sdk-core/tests/integ_tests/queries_tests.rs +14 -17
- package/sdk-core/tests/integ_tests/update_tests.rs +47 -44
- package/sdk-core/tests/integ_tests/visibility_tests.rs +4 -3
- package/sdk-core/tests/integ_tests/worker_tests.rs +5 -5
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +15 -13
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +28 -14
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +7 -1
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +57 -4
- package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +24 -18
- package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +506 -0
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/priority.rs +104 -0
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +34 -31
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -7
- package/sdk-core/tests/integ_tests/workflow_tests.rs +152 -116
- package/sdk-core/tests/main.rs +36 -6
- package/sdk-core/tests/runner.rs +30 -9
- package/src/conversions/slot_supplier_bridge.rs +4 -0
- package/src/conversions.rs +1 -0
- package/src/worker.rs +5 -7
- package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +0 -78
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
use std::time::Duration;
|
|
2
|
+
use temporal_client::{Priority, WorkflowClientTrait, WorkflowOptions};
|
|
3
|
+
use temporal_sdk::{ActContext, ActivityOptions, ChildWorkflowOptions, WfContext};
|
|
4
|
+
use temporal_sdk_core_protos::{
|
|
5
|
+
coresdk::AsJsonPayloadExt, temporal::api::history::v1::history_event::Attributes,
|
|
6
|
+
};
|
|
7
|
+
use temporal_sdk_core_test_utils::CoreWfStarter;
|
|
8
|
+
|
|
9
|
+
#[tokio::test]
|
|
10
|
+
async fn priority_values_sent_to_server() {
|
|
11
|
+
let mut starter = CoreWfStarter::new("priority-values-sent-to-server");
|
|
12
|
+
starter.workflow_options.priority = Some(Priority { priority_key: 1 });
|
|
13
|
+
let mut worker = starter.worker().await;
|
|
14
|
+
let child_type = "child-wf";
|
|
15
|
+
|
|
16
|
+
worker.register_wf(starter.get_task_queue(), move |ctx: WfContext| async move {
|
|
17
|
+
let child = ctx.child_workflow(ChildWorkflowOptions {
|
|
18
|
+
workflow_id: format!("{}-child", ctx.task_queue()),
|
|
19
|
+
workflow_type: child_type.to_owned(),
|
|
20
|
+
options: WorkflowOptions {
|
|
21
|
+
priority: Some(Priority { priority_key: 4 }),
|
|
22
|
+
..Default::default()
|
|
23
|
+
},
|
|
24
|
+
..Default::default()
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
let started = child
|
|
28
|
+
.start(&ctx)
|
|
29
|
+
.await
|
|
30
|
+
.into_started()
|
|
31
|
+
.expect("Child should start OK");
|
|
32
|
+
let activity = ctx.activity(ActivityOptions {
|
|
33
|
+
activity_type: "echo".to_owned(),
|
|
34
|
+
input: "hello".as_json_payload().unwrap(),
|
|
35
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
36
|
+
priority: Some(Priority { priority_key: 5 }),
|
|
37
|
+
..Default::default()
|
|
38
|
+
});
|
|
39
|
+
started.result().await;
|
|
40
|
+
activity.await;
|
|
41
|
+
Ok(().into())
|
|
42
|
+
});
|
|
43
|
+
worker.register_wf(child_type.to_owned(), |_ctx: WfContext| async move {
|
|
44
|
+
Ok(().into())
|
|
45
|
+
});
|
|
46
|
+
worker.register_activity("echo", |_ctx: ActContext, echo_me: String| async move {
|
|
47
|
+
Ok(echo_me)
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
starter
|
|
51
|
+
.start_with_worker(starter.get_task_queue(), &mut worker)
|
|
52
|
+
.await;
|
|
53
|
+
worker.run_until_done().await.unwrap();
|
|
54
|
+
|
|
55
|
+
let client = starter.get_client().await;
|
|
56
|
+
let history = client
|
|
57
|
+
.get_workflow_execution_history(starter.get_task_queue().to_owned(), None, vec![])
|
|
58
|
+
.await
|
|
59
|
+
.unwrap()
|
|
60
|
+
.history
|
|
61
|
+
.unwrap();
|
|
62
|
+
let workflow_init_event = history
|
|
63
|
+
.events
|
|
64
|
+
.iter()
|
|
65
|
+
.find_map(|e| {
|
|
66
|
+
if let Attributes::WorkflowExecutionStartedEventAttributes(e) =
|
|
67
|
+
e.attributes.as_ref().unwrap()
|
|
68
|
+
{
|
|
69
|
+
Some(e)
|
|
70
|
+
} else {
|
|
71
|
+
None
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
.unwrap();
|
|
75
|
+
assert_eq!(workflow_init_event.priority.unwrap().priority_key, 1);
|
|
76
|
+
let child_init_event = history
|
|
77
|
+
.events
|
|
78
|
+
.iter()
|
|
79
|
+
.find_map(|e| {
|
|
80
|
+
if let Attributes::StartChildWorkflowExecutionInitiatedEventAttributes(e) =
|
|
81
|
+
e.attributes.as_ref().unwrap()
|
|
82
|
+
{
|
|
83
|
+
Some(e)
|
|
84
|
+
} else {
|
|
85
|
+
None
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
.unwrap();
|
|
89
|
+
assert_eq!(child_init_event.priority.unwrap().priority_key, 4);
|
|
90
|
+
let activity_sched_event = history
|
|
91
|
+
.events
|
|
92
|
+
.iter()
|
|
93
|
+
.find_map(|e| {
|
|
94
|
+
if let Attributes::ActivityTaskScheduledEventAttributes(e) =
|
|
95
|
+
e.attributes.as_ref().unwrap()
|
|
96
|
+
{
|
|
97
|
+
Some(e)
|
|
98
|
+
} else {
|
|
99
|
+
None
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
.unwrap();
|
|
103
|
+
assert_eq!(activity_sched_event.priority.unwrap().priority_key, 5);
|
|
104
|
+
}
|
|
@@ -2,21 +2,21 @@ use crate::integ_tests::workflow_tests::patches::changes_wf;
|
|
|
2
2
|
use assert_matches::assert_matches;
|
|
3
3
|
use parking_lot::Mutex;
|
|
4
4
|
use std::{collections::HashSet, sync::Arc, time::Duration};
|
|
5
|
-
use temporal_sdk::{
|
|
5
|
+
use temporal_sdk::{WfContext, Worker, WorkflowFunction, interceptors::WorkerInterceptor};
|
|
6
6
|
use temporal_sdk_core::replay::{HistoryFeeder, HistoryForReplay};
|
|
7
|
-
use temporal_sdk_core_api::errors::
|
|
7
|
+
use temporal_sdk_core_api::errors::PollError;
|
|
8
8
|
use temporal_sdk_core_protos::{
|
|
9
|
+
DEFAULT_WORKFLOW_TYPE, TestHistoryBuilder,
|
|
9
10
|
coresdk::{
|
|
10
11
|
workflow_activation::remove_from_cache::EvictionReason,
|
|
11
12
|
workflow_commands::{ScheduleActivity, StartTimer},
|
|
12
13
|
workflow_completion::WorkflowActivationCompletion,
|
|
13
14
|
},
|
|
14
15
|
temporal::api::enums::v1::EventType,
|
|
15
|
-
TestHistoryBuilder, DEFAULT_WORKFLOW_TYPE,
|
|
16
16
|
};
|
|
17
17
|
use temporal_sdk_core_test_utils::{
|
|
18
|
-
canned_histories, history_from_proto_binary, init_core_replay_preloaded,
|
|
19
|
-
|
|
18
|
+
WorkerTestHelpers, canned_histories, history_from_proto_binary, init_core_replay_preloaded,
|
|
19
|
+
replay_sdk_worker, replay_sdk_worker_stream,
|
|
20
20
|
};
|
|
21
21
|
use tokio::join;
|
|
22
22
|
|
|
@@ -39,21 +39,20 @@ async fn timer_workflow_replay() {
|
|
|
39
39
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
40
40
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
41
41
|
task.run_id,
|
|
42
|
-
vec![
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
vec![
|
|
43
|
+
StartTimer {
|
|
44
|
+
seq: 0,
|
|
45
|
+
start_to_fire_timeout: Some(prost_dur!(from_secs(1))),
|
|
46
|
+
}
|
|
47
|
+
.into(),
|
|
48
|
+
],
|
|
47
49
|
))
|
|
48
50
|
.await
|
|
49
51
|
.unwrap();
|
|
50
52
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
51
53
|
// Verify that an in-progress poll is interrupted by completion finishing processing history
|
|
52
54
|
let act_poll_fut = async {
|
|
53
|
-
assert_matches!(
|
|
54
|
-
core.poll_activity_task().await,
|
|
55
|
-
Err(PollActivityError::ShutDown)
|
|
56
|
-
);
|
|
55
|
+
assert_matches!(core.poll_activity_task().await, Err(PollError::ShutDown));
|
|
57
56
|
};
|
|
58
57
|
let poll_fut = async {
|
|
59
58
|
let evict_task = core
|
|
@@ -66,7 +65,7 @@ async fn timer_workflow_replay() {
|
|
|
66
65
|
.unwrap();
|
|
67
66
|
assert_matches!(
|
|
68
67
|
core.poll_workflow_activation().await,
|
|
69
|
-
Err(
|
|
68
|
+
Err(PollError::ShutDown)
|
|
70
69
|
);
|
|
71
70
|
};
|
|
72
71
|
let complete_fut = async {
|
|
@@ -77,7 +76,7 @@ async fn timer_workflow_replay() {
|
|
|
77
76
|
// Subsequent polls should still return shutdown
|
|
78
77
|
assert_matches!(
|
|
79
78
|
core.poll_workflow_activation().await,
|
|
80
|
-
Err(
|
|
79
|
+
Err(PollError::ShutDown)
|
|
81
80
|
);
|
|
82
81
|
|
|
83
82
|
core.shutdown().await;
|
|
@@ -97,13 +96,15 @@ async fn workflow_nondeterministic_replay() {
|
|
|
97
96
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
98
97
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
99
98
|
task.run_id,
|
|
100
|
-
vec![
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
vec![
|
|
100
|
+
ScheduleActivity {
|
|
101
|
+
seq: 0,
|
|
102
|
+
activity_id: "0".to_string(),
|
|
103
|
+
activity_type: "fake_act".to_string(),
|
|
104
|
+
..Default::default()
|
|
105
|
+
}
|
|
106
|
+
.into(),
|
|
107
|
+
],
|
|
107
108
|
))
|
|
108
109
|
.await
|
|
109
110
|
.unwrap();
|
|
@@ -117,7 +118,7 @@ async fn workflow_nondeterministic_replay() {
|
|
|
117
118
|
core.shutdown().await;
|
|
118
119
|
assert_matches!(
|
|
119
120
|
core.poll_workflow_activation().await,
|
|
120
|
-
Err(
|
|
121
|
+
Err(PollError::ShutDown)
|
|
121
122
|
);
|
|
122
123
|
}
|
|
123
124
|
|
|
@@ -264,13 +265,15 @@ async fn replay_ends_with_empty_wft() {
|
|
|
264
265
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
265
266
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
266
267
|
task.run_id,
|
|
267
|
-
vec![
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
268
|
+
vec![
|
|
269
|
+
ScheduleActivity {
|
|
270
|
+
seq: 1,
|
|
271
|
+
activity_id: "1".to_string(),
|
|
272
|
+
activity_type: "say_hello".to_string(),
|
|
273
|
+
..Default::default()
|
|
274
|
+
}
|
|
275
|
+
.into(),
|
|
276
|
+
],
|
|
274
277
|
))
|
|
275
278
|
.await
|
|
276
279
|
.unwrap();
|
|
@@ -6,8 +6,8 @@ use temporal_sdk_core_protos::coresdk::{
|
|
|
6
6
|
workflow_completion::WorkflowActivationCompletion,
|
|
7
7
|
};
|
|
8
8
|
use temporal_sdk_core_test_utils::{
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
CoreWfStarter, WorkerTestHelpers, drain_pollers_and_shutdown, init_core_and_create_wf,
|
|
10
|
+
start_timer_cmd,
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
pub(crate) async fn timer_wf(command_sink: WfContext) -> WorkflowResult<()> {
|
|
@@ -35,16 +35,19 @@ async fn timer_workflow_manual() {
|
|
|
35
35
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
36
36
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
37
37
|
task.run_id,
|
|
38
|
-
vec![
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
vec![
|
|
39
|
+
StartTimer {
|
|
40
|
+
seq: 0,
|
|
41
|
+
start_to_fire_timeout: Some(prost_dur!(from_secs(1))),
|
|
42
|
+
}
|
|
43
|
+
.into(),
|
|
44
|
+
],
|
|
43
45
|
))
|
|
44
46
|
.await
|
|
45
47
|
.unwrap();
|
|
46
48
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
47
49
|
core.complete_execution(&task.run_id).await;
|
|
50
|
+
core.handle_eviction().await;
|
|
48
51
|
drain_pollers_and_shutdown(&core).await;
|
|
49
52
|
}
|
|
50
53
|
|
|
@@ -8,7 +8,9 @@ mod determinism;
|
|
|
8
8
|
mod eager;
|
|
9
9
|
mod local_activities;
|
|
10
10
|
mod modify_wf_properties;
|
|
11
|
+
mod nexus;
|
|
11
12
|
mod patches;
|
|
13
|
+
mod priority;
|
|
12
14
|
mod replay;
|
|
13
15
|
mod resets;
|
|
14
16
|
mod signals;
|
|
@@ -18,32 +20,27 @@ mod upsert_search_attrs;
|
|
|
18
20
|
|
|
19
21
|
use crate::integ_tests::{activity_functions::echo, metrics_tests};
|
|
20
22
|
use assert_matches::assert_matches;
|
|
21
|
-
use futures_channel::mpsc::UnboundedReceiver;
|
|
22
|
-
use futures_util::{future, SinkExt, StreamExt};
|
|
23
23
|
use std::{
|
|
24
24
|
collections::{HashMap, HashSet},
|
|
25
|
-
sync::{
|
|
26
|
-
atomic::{AtomicUsize, Ordering},
|
|
27
|
-
Arc,
|
|
28
|
-
},
|
|
25
|
+
sync::atomic::{AtomicUsize, Ordering},
|
|
29
26
|
time::Duration,
|
|
30
27
|
};
|
|
31
|
-
use temporal_client::{WorkflowClientTrait, WorkflowOptions};
|
|
32
|
-
use temporal_sdk::{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
errors::{PollWfError, WorkflowErrorType},
|
|
36
|
-
Worker,
|
|
28
|
+
use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowExecutionResult, WorkflowOptions};
|
|
29
|
+
use temporal_sdk::{
|
|
30
|
+
ActivityOptions, LocalActivityOptions, WfContext, WorkflowResult,
|
|
31
|
+
interceptors::WorkerInterceptor,
|
|
37
32
|
};
|
|
33
|
+
use temporal_sdk_core::{CoreRuntime, replay::HistoryForReplay};
|
|
34
|
+
use temporal_sdk_core_api::errors::{PollError, WorkflowErrorType};
|
|
38
35
|
use temporal_sdk_core_protos::{
|
|
39
36
|
coresdk::{
|
|
37
|
+
ActivityTaskCompletion, AsJsonPayloadExt, IntoCompletion,
|
|
40
38
|
activity_result::ActivityExecutionResult,
|
|
41
|
-
workflow_activation::{
|
|
39
|
+
workflow_activation::{WorkflowActivationJob, workflow_activation_job},
|
|
42
40
|
workflow_commands::{
|
|
43
41
|
ActivityCancellationType, FailWorkflowExecution, QueryResult, QuerySuccess, StartTimer,
|
|
44
42
|
},
|
|
45
43
|
workflow_completion::WorkflowActivationCompletion,
|
|
46
|
-
ActivityTaskCompletion, AsJsonPayloadExt, IntoCompletion,
|
|
47
44
|
},
|
|
48
45
|
temporal::api::{
|
|
49
46
|
enums::v1::EventType, failure::v1::Failure, history::v1::history_event,
|
|
@@ -51,68 +48,36 @@ use temporal_sdk_core_protos::{
|
|
|
51
48
|
},
|
|
52
49
|
};
|
|
53
50
|
use temporal_sdk_core_test_utils::{
|
|
54
|
-
drain_pollers_and_shutdown, history_from_proto_binary,
|
|
55
|
-
init_core_replay_preloaded, schedule_activity_cmd,
|
|
51
|
+
CoreWfStarter, WorkerTestHelpers, drain_pollers_and_shutdown, history_from_proto_binary,
|
|
52
|
+
init_core_and_create_wf, init_core_replay_preloaded, schedule_activity_cmd,
|
|
56
53
|
};
|
|
57
|
-
use tokio::{join, time::sleep};
|
|
54
|
+
use tokio::{join, sync::Notify, time::sleep};
|
|
58
55
|
use uuid::Uuid;
|
|
59
|
-
|
|
60
56
|
// TODO: We should get expected histories for these tests and confirm that the history at the end
|
|
61
57
|
// matches.
|
|
62
58
|
|
|
63
59
|
#[tokio::test]
|
|
64
60
|
async fn parallel_workflows_same_queue() {
|
|
65
|
-
let
|
|
66
|
-
let
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
let run_ids: Vec<_> = future::join_all(
|
|
70
|
-
(0..num_workflows).map(|i| starter.start_wf_with_id(format!("wf-id-{i}"))),
|
|
71
|
-
)
|
|
72
|
-
.await;
|
|
73
|
-
|
|
74
|
-
let mut send_chans = HashMap::new();
|
|
75
|
-
async fn wf_task(
|
|
76
|
-
worker: Arc<dyn Worker>,
|
|
77
|
-
mut task_chan: UnboundedReceiver<WorkflowActivation>,
|
|
78
|
-
) {
|
|
79
|
-
let task = task_chan.next().await.unwrap();
|
|
80
|
-
assert_matches!(
|
|
81
|
-
task.jobs.as_slice(),
|
|
82
|
-
[WorkflowActivationJob {
|
|
83
|
-
variant: Some(workflow_activation_job::Variant::InitializeWorkflow(_)),
|
|
84
|
-
}]
|
|
85
|
-
);
|
|
86
|
-
worker
|
|
87
|
-
.complete_timer(&task.run_id, 1, Duration::from_secs(1))
|
|
88
|
-
.await;
|
|
89
|
-
let task = task_chan.next().await.unwrap();
|
|
90
|
-
worker.complete_execution(&task.run_id).await;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
let handles: Vec<_> = run_ids
|
|
94
|
-
.iter()
|
|
95
|
-
.map(|run_id| {
|
|
96
|
-
let (tx, rx) = futures_channel::mpsc::unbounded();
|
|
97
|
-
send_chans.insert(run_id.clone(), tx);
|
|
98
|
-
tokio::spawn(wf_task(core.clone(), rx))
|
|
99
|
-
})
|
|
100
|
-
.collect();
|
|
101
|
-
|
|
102
|
-
for _ in 0..num_workflows * 2 {
|
|
103
|
-
let task = core.poll_workflow_activation().await.unwrap();
|
|
104
|
-
send_chans
|
|
105
|
-
.get(&task.run_id)
|
|
106
|
-
.unwrap()
|
|
107
|
-
.send(task)
|
|
108
|
-
.await
|
|
109
|
-
.unwrap();
|
|
110
|
-
}
|
|
61
|
+
let wf_name = "parallel_workflows_same_queue";
|
|
62
|
+
let mut starter = CoreWfStarter::new(wf_name);
|
|
63
|
+
starter.worker_config.no_remote_activities(true);
|
|
64
|
+
let mut core = starter.worker().await;
|
|
111
65
|
|
|
112
|
-
|
|
113
|
-
|
|
66
|
+
core.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
|
|
67
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
68
|
+
Ok(().into())
|
|
69
|
+
});
|
|
70
|
+
for i in 0..25 {
|
|
71
|
+
core.submit_wf(
|
|
72
|
+
format!("{}-{}", wf_name, i),
|
|
73
|
+
wf_name,
|
|
74
|
+
vec![],
|
|
75
|
+
starter.workflow_options.clone(),
|
|
76
|
+
)
|
|
77
|
+
.await
|
|
78
|
+
.unwrap();
|
|
114
79
|
}
|
|
115
|
-
|
|
80
|
+
core.run_until_done().await.unwrap();
|
|
116
81
|
}
|
|
117
82
|
|
|
118
83
|
static RUN_CT: AtomicUsize = AtomicUsize::new(0);
|
|
@@ -180,14 +145,14 @@ async fn shutdown_aborts_actively_blocked_poll() {
|
|
|
180
145
|
});
|
|
181
146
|
assert_matches!(
|
|
182
147
|
core.poll_workflow_activation().await.unwrap_err(),
|
|
183
|
-
|
|
148
|
+
PollError::ShutDown
|
|
184
149
|
);
|
|
185
150
|
handle.await.unwrap();
|
|
186
151
|
// Ensure double-shutdown doesn't explode
|
|
187
152
|
core.shutdown().await;
|
|
188
153
|
assert_matches!(
|
|
189
154
|
core.poll_workflow_activation().await.unwrap_err(),
|
|
190
|
-
|
|
155
|
+
PollError::ShutDown
|
|
191
156
|
);
|
|
192
157
|
}
|
|
193
158
|
|
|
@@ -230,26 +195,19 @@ async fn fail_wf_task(#[values(true, false)] replay: bool) {
|
|
|
230
195
|
|
|
231
196
|
// The server will want to retry the task. This time we finish the workflow -- but we need
|
|
232
197
|
// to poll a couple of times as there will be more than one required workflow activation.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
assert_matches!(
|
|
236
|
-
task.jobs.as_slice(),
|
|
237
|
-
[WorkflowActivationJob {
|
|
238
|
-
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
|
239
|
-
}]
|
|
240
|
-
);
|
|
241
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
|
|
242
|
-
.await
|
|
243
|
-
.unwrap();
|
|
198
|
+
// The first poll response will tell us to evict.
|
|
199
|
+
core.handle_eviction().await;
|
|
244
200
|
|
|
245
201
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
246
202
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
247
203
|
task.run_id,
|
|
248
|
-
vec![
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
204
|
+
vec![
|
|
205
|
+
StartTimer {
|
|
206
|
+
seq: 0,
|
|
207
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(200))),
|
|
208
|
+
}
|
|
209
|
+
.into(),
|
|
210
|
+
],
|
|
253
211
|
))
|
|
254
212
|
.await
|
|
255
213
|
.unwrap();
|
|
@@ -269,10 +227,12 @@ async fn fail_workflow_execution() {
|
|
|
269
227
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
270
228
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
271
229
|
task.run_id,
|
|
272
|
-
vec![
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
230
|
+
vec![
|
|
231
|
+
FailWorkflowExecution {
|
|
232
|
+
failure: Some(Failure::application_failure("I'm ded".to_string(), false)),
|
|
233
|
+
}
|
|
234
|
+
.into(),
|
|
235
|
+
],
|
|
276
236
|
))
|
|
277
237
|
.await
|
|
278
238
|
.unwrap();
|
|
@@ -369,11 +329,13 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
|
|
|
369
329
|
// Task is completed with a timer
|
|
370
330
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
371
331
|
res.run_id,
|
|
372
|
-
vec![
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
332
|
+
vec![
|
|
333
|
+
StartTimer {
|
|
334
|
+
seq: 0,
|
|
335
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(10))),
|
|
336
|
+
}
|
|
337
|
+
.into(),
|
|
338
|
+
],
|
|
377
339
|
))
|
|
378
340
|
.await
|
|
379
341
|
.unwrap();
|
|
@@ -408,18 +370,8 @@ async fn signal_workflow_signal_not_handled_on_workflow_completion() {
|
|
|
408
370
|
// Send completion - not having seen a poll response with a signal in it yet (unhandled
|
|
409
371
|
// command error will be logged as a warning and an eviction will be issued)
|
|
410
372
|
core.complete_execution(&run_id).await;
|
|
411
|
-
|
|
412
373
|
// We should be told to evict
|
|
413
|
-
|
|
414
|
-
assert_matches!(
|
|
415
|
-
res.jobs.as_slice(),
|
|
416
|
-
[WorkflowActivationJob {
|
|
417
|
-
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
|
418
|
-
}]
|
|
419
|
-
);
|
|
420
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::empty(res.run_id))
|
|
421
|
-
.await
|
|
422
|
-
.unwrap();
|
|
374
|
+
core.handle_eviction().await;
|
|
423
375
|
// Loop to the top to handle wf from the beginning
|
|
424
376
|
continue;
|
|
425
377
|
}
|
|
@@ -515,16 +467,7 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
|
|
|
515
467
|
.await
|
|
516
468
|
.unwrap();
|
|
517
469
|
// Now poll again, it will be an eviction b/c non-sticky mode.
|
|
518
|
-
|
|
519
|
-
assert_matches!(
|
|
520
|
-
wf_task.jobs.as_slice(),
|
|
521
|
-
[WorkflowActivationJob {
|
|
522
|
-
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
|
523
|
-
}]
|
|
524
|
-
);
|
|
525
|
-
core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
|
|
526
|
-
.await
|
|
527
|
-
.unwrap();
|
|
470
|
+
core.handle_eviction().await;
|
|
528
471
|
// Start from the beginning
|
|
529
472
|
poll_sched_act().await;
|
|
530
473
|
let wf_task = core.poll_workflow_activation().await.unwrap();
|
|
@@ -753,7 +696,7 @@ async fn build_id_correct_in_wf_info() {
|
|
|
753
696
|
async fn nondeterminism_errors_fail_workflow_when_configured_to(
|
|
754
697
|
#[values(true, false)] whole_worker: bool,
|
|
755
698
|
) {
|
|
756
|
-
let (telemopts, addr, _aborter) = metrics_tests::prom_metrics(
|
|
699
|
+
let (telemopts, addr, _aborter) = metrics_tests::prom_metrics(None);
|
|
757
700
|
let rt = CoreRuntime::new_assume_tokio(telemopts).unwrap();
|
|
758
701
|
let wf_name = "nondeterminism_errors_fail_workflow_when_configured_to";
|
|
759
702
|
let mut starter = CoreWfStarter::new_with_runtime(wf_name, rt);
|
|
@@ -836,3 +779,96 @@ async fn nondeterminism_errors_fail_workflow_when_configured_to(
|
|
|
836
779
|
);
|
|
837
780
|
assert!(body.contains(&match_this));
|
|
838
781
|
}
|
|
782
|
+
|
|
783
|
+
#[tokio::test]
|
|
784
|
+
async fn history_out_of_order_on_restart() {
|
|
785
|
+
let wf_name = "history_out_of_order_on_restart";
|
|
786
|
+
let mut starter = CoreWfStarter::new(wf_name);
|
|
787
|
+
starter
|
|
788
|
+
.worker_config
|
|
789
|
+
.workflow_failure_errors([WorkflowErrorType::Nondeterminism]);
|
|
790
|
+
let mut worker = starter.worker().await;
|
|
791
|
+
let mut starter2 = starter.clone_no_worker();
|
|
792
|
+
let mut worker2 = starter2.worker().await;
|
|
793
|
+
|
|
794
|
+
static HIT_SLEEP: Notify = Notify::const_new();
|
|
795
|
+
|
|
796
|
+
worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
|
|
797
|
+
ctx.local_activity(LocalActivityOptions {
|
|
798
|
+
activity_type: "echo".to_owned(),
|
|
799
|
+
input: "hi".as_json_payload().unwrap(),
|
|
800
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
801
|
+
..Default::default()
|
|
802
|
+
})
|
|
803
|
+
.await;
|
|
804
|
+
ctx.activity(ActivityOptions {
|
|
805
|
+
activity_type: "echo".to_owned(),
|
|
806
|
+
input: "hi".as_json_payload().unwrap(),
|
|
807
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
808
|
+
..Default::default()
|
|
809
|
+
})
|
|
810
|
+
.await;
|
|
811
|
+
// Interrupt this sleep on first go
|
|
812
|
+
HIT_SLEEP.notify_one();
|
|
813
|
+
ctx.timer(Duration::from_secs(5)).await;
|
|
814
|
+
Ok(().into())
|
|
815
|
+
});
|
|
816
|
+
worker.register_activity("echo", echo);
|
|
817
|
+
|
|
818
|
+
worker2.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
|
|
819
|
+
ctx.local_activity(LocalActivityOptions {
|
|
820
|
+
activity_type: "echo".to_owned(),
|
|
821
|
+
input: "hi".as_json_payload().unwrap(),
|
|
822
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
823
|
+
..Default::default()
|
|
824
|
+
})
|
|
825
|
+
.await;
|
|
826
|
+
// Timer is added after restarting workflow
|
|
827
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
828
|
+
ctx.activity(ActivityOptions {
|
|
829
|
+
activity_type: "echo".to_owned(),
|
|
830
|
+
input: "hi".as_json_payload().unwrap(),
|
|
831
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
832
|
+
..Default::default()
|
|
833
|
+
})
|
|
834
|
+
.await;
|
|
835
|
+
ctx.timer(Duration::from_secs(2)).await;
|
|
836
|
+
Ok(().into())
|
|
837
|
+
});
|
|
838
|
+
worker2.register_activity("echo", echo);
|
|
839
|
+
worker
|
|
840
|
+
.submit_wf(
|
|
841
|
+
wf_name.to_owned(),
|
|
842
|
+
wf_name.to_owned(),
|
|
843
|
+
vec![],
|
|
844
|
+
WorkflowOptions {
|
|
845
|
+
execution_timeout: Some(Duration::from_secs(20)),
|
|
846
|
+
..Default::default()
|
|
847
|
+
},
|
|
848
|
+
)
|
|
849
|
+
.await
|
|
850
|
+
.unwrap();
|
|
851
|
+
|
|
852
|
+
let w1 = async {
|
|
853
|
+
worker.run_until_done().await.unwrap();
|
|
854
|
+
};
|
|
855
|
+
let w2 = async {
|
|
856
|
+
// wait to hit sleep
|
|
857
|
+
HIT_SLEEP.notified().await;
|
|
858
|
+
starter.shutdown().await;
|
|
859
|
+
// start new worker
|
|
860
|
+
worker2.expect_workflow_completion(wf_name, None);
|
|
861
|
+
worker2.run_until_done().await.unwrap();
|
|
862
|
+
};
|
|
863
|
+
join!(w1, w2);
|
|
864
|
+
// The workflow should fail with the nondeterminism error
|
|
865
|
+
let handle = starter
|
|
866
|
+
.get_client()
|
|
867
|
+
.await
|
|
868
|
+
.get_untyped_workflow_handle(wf_name, "");
|
|
869
|
+
let res = handle
|
|
870
|
+
.get_workflow_result(Default::default())
|
|
871
|
+
.await
|
|
872
|
+
.unwrap();
|
|
873
|
+
assert_matches!(res, WorkflowExecutionResult::Failed(_));
|
|
874
|
+
}
|