@temporalio/core-bridge 1.15.0 → 1.16.1
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 +172 -70
- package/lib/native.d.ts +1 -1
- package/package.json +2 -2
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.github/workflows/per-pr.yml +6 -6
- package/sdk-core/AGENTS.md +41 -30
- package/sdk-core/Cargo.toml +3 -0
- package/sdk-core/README.md +15 -9
- package/sdk-core/crates/client/Cargo.toml +4 -0
- package/sdk-core/crates/client/README.md +139 -0
- package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
- package/sdk-core/crates/client/src/callback_based.rs +7 -0
- package/sdk-core/crates/client/src/errors.rs +294 -0
- package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +280 -159
- package/sdk-core/crates/client/src/lib.rs +920 -1326
- package/sdk-core/crates/client/src/metrics.rs +24 -33
- package/sdk-core/crates/client/src/options_structs.rs +457 -0
- package/sdk-core/crates/client/src/replaceable.rs +5 -4
- package/sdk-core/crates/client/src/request_extensions.rs +8 -9
- package/sdk-core/crates/client/src/retry.rs +99 -54
- package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +1 -1
- package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
- package/sdk-core/crates/common/Cargo.toml +61 -2
- package/sdk-core/crates/common/build.rs +742 -12
- package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
- package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
- package/sdk-core/crates/common/protos/api_upstream/buf.yaml +0 -3
- package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
- package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +1166 -770
- package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +1243 -750
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +2 -2
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +4 -3
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +16 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -6
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +88 -33
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +4 -2
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +4 -0
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +5 -5
- package/sdk-core/crates/common/src/activity_definition.rs +20 -0
- package/sdk-core/crates/common/src/data_converters.rs +770 -0
- package/sdk-core/crates/common/src/envconfig.rs +5 -0
- package/sdk-core/crates/common/src/lib.rs +15 -211
- package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
- package/sdk-core/crates/common/src/priority.rs +110 -0
- package/sdk-core/crates/common/src/protos/canned_histories.rs +3 -0
- package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
- package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
- package/sdk-core/crates/common/src/protos/mod.rs +122 -27
- package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
- package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +5 -7
- package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
- package/sdk-core/crates/common/src/telemetry/metrics.rs +268 -223
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
- package/sdk-core/crates/common/src/telemetry.rs +264 -4
- package/sdk-core/crates/common/src/worker.rs +68 -603
- package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
- package/sdk-core/crates/macros/Cargo.toml +5 -1
- package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
- package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
- package/sdk-core/crates/macros/src/lib.rs +138 -512
- package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
- package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
- package/sdk-core/crates/sdk/Cargo.toml +19 -6
- package/sdk-core/crates/sdk/README.md +415 -0
- package/sdk-core/crates/sdk/src/activities.rs +417 -0
- package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
- package/sdk-core/crates/sdk/src/lib.rs +757 -442
- package/sdk-core/crates/sdk/src/workflow_context/options.rs +45 -35
- package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
- package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
- package/sdk-core/crates/sdk/src/workflows.rs +711 -0
- package/sdk-core/crates/sdk-core/Cargo.toml +57 -64
- package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +41 -35
- package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
- package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
- package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
- package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +13 -15
- package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
- package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
- package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
- package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +493 -26
- package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +4 -8
- package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +7 -7
- package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
- package/sdk-core/crates/sdk-core/src/lib.rs +41 -111
- package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
- package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +118 -19
- package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
- package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
- package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +179 -196
- package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -280
- package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +6 -9
- package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
- package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
- package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
- package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +9 -5
- package/sdk-core/crates/sdk-core/src/worker/client.rs +103 -81
- package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +7 -11
- package/sdk-core/crates/sdk-core/src/worker/mod.rs +1124 -229
- package/sdk-core/crates/sdk-core/src/worker/nexus.rs +145 -23
- package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
- package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
- package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +13 -13
- package/sdk-core/crates/sdk-core/src/worker/tuner.rs +28 -8
- package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +19 -4
- package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +14 -18
- package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +4 -6
- package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
- package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
- package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
- package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
- package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
- package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
- package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
- package/sdk-core/crates/sdk-core/tests/common/mod.rs +241 -196
- package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
- package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +3 -5
- package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -64
- package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +298 -252
- package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
- package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +16 -12
- package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +48 -40
- package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +327 -255
- package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
- package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +147 -126
- package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
- package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -453
- package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +360 -231
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +248 -185
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -43
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +428 -315
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -56
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -28
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -243
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +101 -42
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -147
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -28
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1036
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -41
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +397 -238
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +414 -189
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +154 -137
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -105
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -38
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -40
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -54
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +363 -226
- package/sdk-core/crates/sdk-core/tests/main.rs +17 -15
- package/sdk-core/crates/sdk-core/tests/manual_tests.rs +207 -152
- package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +65 -34
- package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
- package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +7 -1
- package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +14 -14
- package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +83 -74
- package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +9 -14
- package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +1 -2
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +13 -13
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +6 -6
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +3 -4
- package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +62 -75
- package/sdk-core/rustfmt.toml +2 -1
- package/src/client.rs +205 -318
- package/src/metrics.rs +22 -30
- package/src/runtime.rs +4 -5
- package/src/worker.rs +16 -19
- package/ts/native.ts +1 -1
- package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
- package/sdk-core/crates/common/src/errors.rs +0 -85
- package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
- package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
- package/sdk-core/crates/sdk/src/app_data.rs +0 -37
- package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
use crate::common::{
|
|
2
|
-
CoreWfStarter, WorkflowHandleExt,
|
|
2
|
+
CoreWfStarter, WorkflowHandleExt, activity_functions::StdActivities, init_core_and_create_wf,
|
|
3
|
+
init_core_replay_preloaded,
|
|
3
4
|
};
|
|
4
5
|
use anyhow::anyhow;
|
|
5
6
|
use assert_matches::assert_matches;
|
|
6
|
-
use futures_util::{
|
|
7
|
+
use futures_util::{future, future::join_all};
|
|
7
8
|
use std::{
|
|
8
9
|
sync::{
|
|
9
|
-
|
|
10
|
+
LazyLock,
|
|
10
11
|
atomic::{AtomicBool, AtomicUsize, Ordering},
|
|
11
12
|
},
|
|
12
13
|
time::Duration,
|
|
13
14
|
};
|
|
14
15
|
use temporalio_client::{
|
|
15
|
-
Client, NamespacedClient,
|
|
16
|
+
Client, NamespacedClient, UntypedSignal, UntypedUpdate, UntypedWorkflow,
|
|
17
|
+
WorkflowExecuteUpdateOptions, WorkflowExecutionInfo, WorkflowSignalOptions,
|
|
18
|
+
WorkflowStartOptions, grpc::WorkflowService,
|
|
16
19
|
};
|
|
17
20
|
use temporalio_common::{
|
|
18
|
-
|
|
21
|
+
data_converters::RawValue,
|
|
22
|
+
prost_dur,
|
|
19
23
|
protos::{
|
|
20
24
|
coresdk::{
|
|
21
|
-
ActivityTaskCompletion,
|
|
25
|
+
ActivityTaskCompletion,
|
|
22
26
|
activity_result::ActivityExecutionResult,
|
|
23
27
|
workflow_activation::{
|
|
24
28
|
WorkflowActivationJob, remove_from_cache::EvictionReason, workflow_activation_job,
|
|
@@ -30,16 +34,21 @@ use temporalio_common::{
|
|
|
30
34
|
},
|
|
31
35
|
temporal::api::{
|
|
32
36
|
common::v1::WorkflowExecution,
|
|
33
|
-
enums::v1::{EventType, ResetReapplyType
|
|
34
|
-
|
|
35
|
-
workflowservice::v1::ResetWorkflowExecutionRequest,
|
|
37
|
+
enums::v1::{EventType, ResetReapplyType},
|
|
38
|
+
workflowservice::v1::{ResetStickyTaskQueueRequest, ResetWorkflowExecutionRequest},
|
|
36
39
|
},
|
|
37
40
|
test_utils::start_timer_cmd,
|
|
38
41
|
},
|
|
39
42
|
worker::WorkerTaskTypes,
|
|
40
43
|
};
|
|
41
|
-
use
|
|
44
|
+
use temporalio_macros::{activities, workflow, workflow_methods};
|
|
45
|
+
use temporalio_sdk::{
|
|
46
|
+
ActivityOptions, LocalActivityOptions, SyncWorkflowContext, WorkflowContext,
|
|
47
|
+
WorkflowContextView, WorkflowResult,
|
|
48
|
+
activities::{ActivityContext, ActivityError},
|
|
49
|
+
};
|
|
42
50
|
use temporalio_sdk_core::{
|
|
51
|
+
Worker,
|
|
43
52
|
replay::HistoryForReplay,
|
|
44
53
|
test_help::{WorkerTestHelpers, drain_pollers_and_shutdown},
|
|
45
54
|
};
|
|
@@ -73,18 +82,18 @@ async fn update_workflow(#[values(FailUpdate::Yes, FailUpdate::No)] will_fail: F
|
|
|
73
82
|
will_fail,
|
|
74
83
|
CompleteWorkflow::Yes,
|
|
75
84
|
core.as_ref(),
|
|
76
|
-
client
|
|
85
|
+
&client,
|
|
77
86
|
)
|
|
78
87
|
.await;
|
|
79
88
|
|
|
80
89
|
// Make sure replay works
|
|
81
|
-
let
|
|
82
|
-
.
|
|
90
|
+
let events = client
|
|
91
|
+
.get_workflow_handle::<UntypedWorkflow>(workflow_id)
|
|
92
|
+
.fetch_history(Default::default())
|
|
83
93
|
.await
|
|
84
94
|
.unwrap()
|
|
85
|
-
.
|
|
86
|
-
|
|
87
|
-
let with_id = HistoryForReplay::new(history, workflow_id.to_string());
|
|
95
|
+
.into_events();
|
|
96
|
+
let with_id = HistoryForReplay::new(events, workflow_id.to_string());
|
|
88
97
|
let replay_worker = init_core_replay_preloaded(workflow_id, [with_id]);
|
|
89
98
|
// Init workflow comes by itself
|
|
90
99
|
let act = replay_worker.poll_workflow_activation().await.unwrap();
|
|
@@ -92,7 +101,7 @@ async fn update_workflow(#[values(FailUpdate::Yes, FailUpdate::No)] will_fail: F
|
|
|
92
101
|
.complete_workflow_activation(WorkflowActivationCompletion::empty(act.run_id))
|
|
93
102
|
.await
|
|
94
103
|
.unwrap();
|
|
95
|
-
handle_update(will_fail, CompleteWorkflow::Yes, replay_worker
|
|
104
|
+
handle_update(will_fail, CompleteWorkflow::Yes, &replay_worker, 0).await;
|
|
96
105
|
}
|
|
97
106
|
|
|
98
107
|
#[tokio::test]
|
|
@@ -107,7 +116,7 @@ async fn reapplied_updates_due_to_reset() {
|
|
|
107
116
|
FailUpdate::No,
|
|
108
117
|
CompleteWorkflow::Yes,
|
|
109
118
|
core.as_ref(),
|
|
110
|
-
client
|
|
119
|
+
&client,
|
|
111
120
|
)
|
|
112
121
|
.await;
|
|
113
122
|
|
|
@@ -116,12 +125,12 @@ async fn reapplied_updates_due_to_reset() {
|
|
|
116
125
|
|
|
117
126
|
let mut client_mut = client.clone();
|
|
118
127
|
let reset_response = WorkflowService::reset_workflow_execution(
|
|
119
|
-
|
|
128
|
+
&mut client_mut,
|
|
120
129
|
#[allow(deprecated)]
|
|
121
130
|
ResetWorkflowExecutionRequest {
|
|
122
131
|
namespace: client.namespace(),
|
|
123
132
|
workflow_execution: Some(WorkflowExecution {
|
|
124
|
-
workflow_id: workflow_id.
|
|
133
|
+
workflow_id: workflow_id.to_string(),
|
|
125
134
|
run_id: pre_reset_run_id.clone(),
|
|
126
135
|
}),
|
|
127
136
|
workflow_task_finish_event_id,
|
|
@@ -147,32 +156,31 @@ async fn reapplied_updates_due_to_reset() {
|
|
|
147
156
|
FailUpdate::No,
|
|
148
157
|
CompleteWorkflow::Yes,
|
|
149
158
|
core.as_ref(),
|
|
150
|
-
client
|
|
159
|
+
&client,
|
|
151
160
|
)
|
|
152
161
|
.await;
|
|
153
162
|
|
|
154
163
|
assert_eq!(post_reset_run_id, reset_response.run_id);
|
|
155
164
|
|
|
156
165
|
// Make sure replay works
|
|
157
|
-
let
|
|
158
|
-
.
|
|
159
|
-
.
|
|
160
|
-
.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
let events = WorkflowExecutionInfo {
|
|
167
|
+
namespace: client.namespace(),
|
|
168
|
+
workflow_id: workflow_id.to_string(),
|
|
169
|
+
run_id: Some(post_reset_run_id.clone()),
|
|
170
|
+
first_execution_run_id: None,
|
|
171
|
+
}
|
|
172
|
+
.bind_untyped(client.clone())
|
|
173
|
+
.fetch_history(Default::default())
|
|
174
|
+
.await
|
|
175
|
+
.unwrap()
|
|
176
|
+
.into_events();
|
|
177
|
+
let with_id = HistoryForReplay::new(events, workflow_id.to_string());
|
|
164
178
|
|
|
165
179
|
let replay_worker = init_core_replay_preloaded(workflow_id, [with_id]);
|
|
166
180
|
// We now recapitulate the actions that the worker took on first execution above, pretending
|
|
167
181
|
// that we always followed the post-reset history.
|
|
168
182
|
// First, we handled the post-reset reapplied update and did not complete the workflow.
|
|
169
|
-
handle_update(
|
|
170
|
-
FailUpdate::No,
|
|
171
|
-
CompleteWorkflow::No,
|
|
172
|
-
replay_worker.as_ref(),
|
|
173
|
-
2,
|
|
174
|
-
)
|
|
175
|
-
.await;
|
|
183
|
+
handle_update(FailUpdate::No, CompleteWorkflow::No, &replay_worker, 2).await;
|
|
176
184
|
// Then the timer fires
|
|
177
185
|
let act = replay_worker.poll_workflow_activation().await.unwrap();
|
|
178
186
|
replay_worker
|
|
@@ -180,13 +188,7 @@ async fn reapplied_updates_due_to_reset() {
|
|
|
180
188
|
.await
|
|
181
189
|
.unwrap();
|
|
182
190
|
// Then the client sent a second update; we handled it and completed the workflow.
|
|
183
|
-
handle_update(
|
|
184
|
-
FailUpdate::No,
|
|
185
|
-
CompleteWorkflow::Yes,
|
|
186
|
-
replay_worker.as_ref(),
|
|
187
|
-
0,
|
|
188
|
-
)
|
|
189
|
-
.await;
|
|
191
|
+
handle_update(FailUpdate::No, CompleteWorkflow::Yes, &replay_worker, 0).await;
|
|
190
192
|
|
|
191
193
|
drain_pollers_and_shutdown(&replay_worker).await;
|
|
192
194
|
}
|
|
@@ -197,8 +199,8 @@ async fn send_and_handle_update(
|
|
|
197
199
|
update_id: &str,
|
|
198
200
|
fail_update: FailUpdate,
|
|
199
201
|
complete_workflow: CompleteWorkflow,
|
|
200
|
-
core: &
|
|
201
|
-
client: &
|
|
202
|
+
core: &Worker,
|
|
203
|
+
client: &Client,
|
|
202
204
|
) -> String {
|
|
203
205
|
// Complete first task with no commands
|
|
204
206
|
let act = core.poll_workflow_activation().await.unwrap();
|
|
@@ -206,30 +208,32 @@ async fn send_and_handle_update(
|
|
|
206
208
|
.await
|
|
207
209
|
.unwrap();
|
|
208
210
|
|
|
211
|
+
let handle = WorkflowExecutionInfo {
|
|
212
|
+
namespace: client.namespace(),
|
|
213
|
+
workflow_id: workflow_id.to_string(),
|
|
214
|
+
run_id: Some(act.run_id.clone()),
|
|
215
|
+
first_execution_run_id: None,
|
|
216
|
+
}
|
|
217
|
+
.bind_untyped(client.clone());
|
|
218
|
+
|
|
209
219
|
// Send the update to the server
|
|
210
220
|
let update_task = async {
|
|
211
|
-
|
|
212
|
-
.
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
WaitPolicy {
|
|
217
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
218
|
-
},
|
|
219
|
-
Some("hi".into()),
|
|
221
|
+
handle
|
|
222
|
+
.execute_update(
|
|
223
|
+
UntypedUpdate::new(update_id),
|
|
224
|
+
RawValue::from_value(&"hi", client.data_converter().payload_converter()),
|
|
225
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
220
226
|
)
|
|
221
227
|
.await
|
|
222
|
-
.unwrap()
|
|
223
228
|
};
|
|
224
229
|
|
|
225
230
|
// Accept update, complete update and complete workflow
|
|
226
231
|
let processing_task = handle_update(fail_update, complete_workflow, core, 0);
|
|
227
232
|
let (ur, _) = join!(update_task, processing_task);
|
|
228
233
|
|
|
229
|
-
let v = ur.outcome.unwrap().value.unwrap();
|
|
230
234
|
match fail_update {
|
|
231
|
-
FailUpdate::Yes =>
|
|
232
|
-
FailUpdate::No =>
|
|
235
|
+
FailUpdate::Yes => assert!(ur.is_err()),
|
|
236
|
+
FailUpdate::No => assert!(ur.is_ok()),
|
|
233
237
|
}
|
|
234
238
|
act.run_id
|
|
235
239
|
}
|
|
@@ -241,7 +245,7 @@ async fn send_and_handle_update(
|
|
|
241
245
|
async fn handle_update(
|
|
242
246
|
fail_update: FailUpdate,
|
|
243
247
|
complete_workflow: CompleteWorkflow,
|
|
244
|
-
core: &
|
|
248
|
+
core: &Worker,
|
|
245
249
|
update_job_index: usize,
|
|
246
250
|
) {
|
|
247
251
|
let act = core.poll_workflow_activation().await.unwrap();
|
|
@@ -313,20 +317,24 @@ async fn update_rejection() {
|
|
|
313
317
|
.await
|
|
314
318
|
.unwrap();
|
|
315
319
|
|
|
320
|
+
let handle = WorkflowExecutionInfo {
|
|
321
|
+
namespace: client.namespace(),
|
|
322
|
+
workflow_id: workflow_id.clone(),
|
|
323
|
+
run_id: Some(res.run_id.clone()),
|
|
324
|
+
first_execution_run_id: None,
|
|
325
|
+
}
|
|
326
|
+
.bind_untyped(client.clone());
|
|
327
|
+
|
|
316
328
|
// Send the update to the server
|
|
317
329
|
let update_task = async {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
325
|
-
},
|
|
326
|
-
Some("hi".into()),
|
|
330
|
+
// rejected
|
|
331
|
+
let _ = handle
|
|
332
|
+
.execute_update(
|
|
333
|
+
UntypedUpdate::new(update_id),
|
|
334
|
+
RawValue::from_value(&"hi", client.data_converter().payload_converter()),
|
|
335
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
327
336
|
)
|
|
328
|
-
.await
|
|
329
|
-
.unwrap();
|
|
337
|
+
.await;
|
|
330
338
|
};
|
|
331
339
|
|
|
332
340
|
let processing_task = async {
|
|
@@ -355,13 +363,13 @@ async fn update_rejection() {
|
|
|
355
363
|
core.complete_execution(&res.run_id).await;
|
|
356
364
|
};
|
|
357
365
|
join!(update_task, processing_task);
|
|
358
|
-
let
|
|
359
|
-
.
|
|
366
|
+
let events = client
|
|
367
|
+
.get_workflow_handle::<UntypedWorkflow>(&workflow_id)
|
|
368
|
+
.fetch_history(Default::default())
|
|
360
369
|
.await
|
|
361
370
|
.unwrap()
|
|
362
|
-
.
|
|
363
|
-
|
|
364
|
-
let has_update_event = history.events.iter().any(|e| {
|
|
371
|
+
.into_events();
|
|
372
|
+
let has_update_event = events.iter().any(|e| {
|
|
365
373
|
matches!(
|
|
366
374
|
e.event_type(),
|
|
367
375
|
EventType::WorkflowExecutionUpdateAccepted | EventType::WorkflowExecutionUpdateRejected
|
|
@@ -388,17 +396,21 @@ async fn update_insta_complete(#[values(true, false)] accept_first: bool) {
|
|
|
388
396
|
.await
|
|
389
397
|
.unwrap();
|
|
390
398
|
|
|
399
|
+
let handle = WorkflowExecutionInfo {
|
|
400
|
+
namespace: client.namespace(),
|
|
401
|
+
workflow_id,
|
|
402
|
+
run_id: Some(res.run_id.clone()),
|
|
403
|
+
first_execution_run_id: None,
|
|
404
|
+
}
|
|
405
|
+
.bind_untyped(client.clone());
|
|
406
|
+
|
|
391
407
|
// Send the update to the server
|
|
392
408
|
let (update_task, stop_wait_update) = future::abortable(async {
|
|
393
|
-
|
|
394
|
-
.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
WaitPolicy {
|
|
399
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
400
|
-
},
|
|
401
|
-
Some("hi".into()),
|
|
409
|
+
handle
|
|
410
|
+
.execute_update(
|
|
411
|
+
UntypedUpdate::new(update_id),
|
|
412
|
+
RawValue::from_value(&"hi", client.data_converter().payload_converter()),
|
|
413
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
402
414
|
)
|
|
403
415
|
.await
|
|
404
416
|
.unwrap();
|
|
@@ -477,17 +489,21 @@ async fn update_complete_after_accept_without_new_task() {
|
|
|
477
489
|
.await
|
|
478
490
|
.unwrap();
|
|
479
491
|
|
|
492
|
+
let handle = WorkflowExecutionInfo {
|
|
493
|
+
namespace: client.namespace(),
|
|
494
|
+
workflow_id,
|
|
495
|
+
run_id: Some(res.run_id.clone()),
|
|
496
|
+
first_execution_run_id: None,
|
|
497
|
+
}
|
|
498
|
+
.bind_untyped(client.clone());
|
|
499
|
+
|
|
480
500
|
// Send the update to the server
|
|
481
501
|
let update_task = async {
|
|
482
|
-
|
|
483
|
-
.
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
WaitPolicy {
|
|
488
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
489
|
-
},
|
|
490
|
-
Some("hi".into()),
|
|
502
|
+
handle
|
|
503
|
+
.execute_update(
|
|
504
|
+
UntypedUpdate::new(update_id),
|
|
505
|
+
RawValue::from_value(&"hi", client.data_converter().payload_converter()),
|
|
506
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
491
507
|
)
|
|
492
508
|
.await
|
|
493
509
|
.unwrap();
|
|
@@ -565,30 +581,26 @@ async fn update_speculative_wft() {
|
|
|
565
581
|
|
|
566
582
|
let update_id = "some_update";
|
|
567
583
|
|
|
584
|
+
let handle = client.get_workflow_handle::<UntypedWorkflow>(workflow_id);
|
|
585
|
+
|
|
568
586
|
// Send update after the timer has fired
|
|
569
587
|
let barr = Barrier::new(2);
|
|
570
588
|
let sender_task = async {
|
|
571
589
|
barr.wait().await;
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
579
|
-
},
|
|
580
|
-
Some("hi".into()),
|
|
590
|
+
// rejected
|
|
591
|
+
let _ = handle
|
|
592
|
+
.execute_update(
|
|
593
|
+
UntypedUpdate::new(update_id),
|
|
594
|
+
RawValue::from_value(&"hi", client.data_converter().payload_converter()),
|
|
595
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
581
596
|
)
|
|
582
|
-
.await
|
|
583
|
-
.unwrap();
|
|
597
|
+
.await;
|
|
584
598
|
barr.wait().await;
|
|
585
|
-
|
|
586
|
-
.
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
None,
|
|
591
|
-
None,
|
|
599
|
+
handle
|
|
600
|
+
.signal(
|
|
601
|
+
UntypedSignal::new("hi"),
|
|
602
|
+
RawValue::empty(),
|
|
603
|
+
WorkflowSignalOptions::default(),
|
|
592
604
|
)
|
|
593
605
|
.await
|
|
594
606
|
.unwrap();
|
|
@@ -649,63 +661,70 @@ async fn update_with_local_acts() {
|
|
|
649
661
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
650
662
|
// Short task timeout to get activities to heartbeat without taking ages
|
|
651
663
|
starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
|
|
664
|
+
starter.sdk_config.register_activities(StdActivities);
|
|
652
665
|
let mut worker = starter.worker().await;
|
|
653
|
-
let client = starter.get_client().await;
|
|
654
|
-
worker.register_wf(wf_name.to_owned(), move |ctx: WfContext| async move {
|
|
655
|
-
ctx.update_handler(
|
|
656
|
-
"update",
|
|
657
|
-
|_: &_, _: ()| Ok(()),
|
|
658
|
-
move |ctx: UpdateContext, _: ()| async move {
|
|
659
|
-
ctx.wf_ctx
|
|
660
|
-
.local_activity(LocalActivityOptions {
|
|
661
|
-
activity_type: "echo_activity".to_string(),
|
|
662
|
-
input: "hi!".as_json_payload().expect("serializes fine"),
|
|
663
|
-
..Default::default()
|
|
664
|
-
})
|
|
665
|
-
.await;
|
|
666
|
-
Ok("hi")
|
|
667
|
-
},
|
|
668
|
-
);
|
|
669
|
-
let mut sig = ctx.make_signal_channel("done");
|
|
670
|
-
sig.next().await;
|
|
671
|
-
Ok(().into())
|
|
672
|
-
});
|
|
673
|
-
worker.register_activity(
|
|
674
|
-
"echo_activity",
|
|
675
|
-
|_ctx: ActContext, echo_me: String| async move {
|
|
676
|
-
// Sleep so we'll heartbeat
|
|
677
|
-
tokio::time::sleep(Duration::from_secs(3)).await;
|
|
678
|
-
Ok(echo_me)
|
|
679
|
-
},
|
|
680
|
-
);
|
|
681
666
|
|
|
682
|
-
|
|
683
|
-
|
|
667
|
+
#[workflow]
|
|
668
|
+
#[derive(Default)]
|
|
669
|
+
struct UpdateWithLocalActsWf {
|
|
670
|
+
done: bool,
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
#[workflow_methods]
|
|
674
|
+
impl UpdateWithLocalActsWf {
|
|
675
|
+
#[run]
|
|
676
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
677
|
+
ctx.wait_condition(|s| s.done).await;
|
|
678
|
+
Ok(())
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
#[signal]
|
|
682
|
+
fn done_signal(&mut self, _ctx: &mut SyncWorkflowContext<Self>, _: ()) {
|
|
683
|
+
self.done = true;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
#[update]
|
|
687
|
+
async fn do_update(
|
|
688
|
+
ctx: &mut WorkflowContext<Self>,
|
|
689
|
+
_: (),
|
|
690
|
+
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
|
691
|
+
ctx.start_local_activity(
|
|
692
|
+
StdActivities::delay,
|
|
693
|
+
Duration::from_secs(3),
|
|
694
|
+
LocalActivityOptions::default(),
|
|
695
|
+
)
|
|
696
|
+
.await?;
|
|
697
|
+
Ok("hi".to_string())
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
worker.register_workflow::<UpdateWithLocalActsWf>();
|
|
702
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
703
|
+
let handle = worker
|
|
704
|
+
.submit_workflow(
|
|
705
|
+
UpdateWithLocalActsWf::run,
|
|
706
|
+
(),
|
|
707
|
+
WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
|
|
708
|
+
)
|
|
709
|
+
.await
|
|
710
|
+
.unwrap();
|
|
684
711
|
let update = async {
|
|
685
|
-
// make sure update has a chance to get registered
|
|
686
|
-
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
687
712
|
// do a handful at once
|
|
688
713
|
let updates = (1..=5).map(|_| {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
WaitPolicy {
|
|
694
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
695
|
-
},
|
|
696
|
-
[().as_json_payload().unwrap()].into_payloads(),
|
|
714
|
+
handle.execute_update(
|
|
715
|
+
UpdateWithLocalActsWf::do_update,
|
|
716
|
+
(),
|
|
717
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
697
718
|
)
|
|
698
719
|
});
|
|
699
720
|
for res in join_all(updates).await {
|
|
700
|
-
assert!(res.unwrap()
|
|
721
|
+
assert!(res.unwrap() == "hi");
|
|
701
722
|
}
|
|
702
|
-
|
|
703
|
-
.
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
None,
|
|
708
|
-
None,
|
|
723
|
+
handle
|
|
724
|
+
.signal(
|
|
725
|
+
UpdateWithLocalActsWf::done_signal,
|
|
726
|
+
(),
|
|
727
|
+
WorkflowSignalOptions::default(),
|
|
709
728
|
)
|
|
710
729
|
.await
|
|
711
730
|
.unwrap();
|
|
@@ -724,35 +743,57 @@ async fn update_with_local_acts() {
|
|
|
724
743
|
async fn update_rejection_sdk() {
|
|
725
744
|
let wf_name = "update_rejection_sdk";
|
|
726
745
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
727
|
-
starter.
|
|
746
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
728
747
|
let mut worker = starter.worker().await;
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
ctx
|
|
737
|
-
|
|
738
|
-
|
|
748
|
+
#[workflow]
|
|
749
|
+
#[derive(Default)]
|
|
750
|
+
struct UpdateRejectionSdkWf;
|
|
751
|
+
|
|
752
|
+
#[workflow_methods]
|
|
753
|
+
impl UpdateRejectionSdkWf {
|
|
754
|
+
#[run]
|
|
755
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
756
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
757
|
+
Ok(())
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
#[update_validator(do_update)]
|
|
761
|
+
fn validate_do_update(
|
|
762
|
+
&self,
|
|
763
|
+
_ctx: &WorkflowContextView,
|
|
764
|
+
_: &(),
|
|
765
|
+
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
766
|
+
Err("ahhhhh noooo".into())
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
#[update]
|
|
770
|
+
async fn do_update(
|
|
771
|
+
_ctx: &mut WorkflowContext<Self>,
|
|
772
|
+
_: (),
|
|
773
|
+
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
|
774
|
+
Ok("hi".to_string())
|
|
775
|
+
}
|
|
776
|
+
}
|
|
739
777
|
|
|
740
|
-
|
|
741
|
-
let
|
|
778
|
+
worker.register_workflow::<UpdateRejectionSdkWf>();
|
|
779
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
780
|
+
let handle = worker
|
|
781
|
+
.submit_workflow(
|
|
782
|
+
UpdateRejectionSdkWf::run,
|
|
783
|
+
(),
|
|
784
|
+
WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
|
|
785
|
+
)
|
|
786
|
+
.await
|
|
787
|
+
.unwrap();
|
|
742
788
|
let update = async {
|
|
743
|
-
let res =
|
|
744
|
-
.
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
WaitPolicy {
|
|
749
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
750
|
-
},
|
|
751
|
-
[().as_json_payload().unwrap()].into_payloads(),
|
|
789
|
+
let res = handle
|
|
790
|
+
.execute_update(
|
|
791
|
+
UpdateRejectionSdkWf::do_update,
|
|
792
|
+
(),
|
|
793
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
752
794
|
)
|
|
753
|
-
.await
|
|
754
|
-
|
|
755
|
-
assert!(!res.outcome.unwrap().is_success());
|
|
795
|
+
.await;
|
|
796
|
+
assert!(res.is_err());
|
|
756
797
|
};
|
|
757
798
|
let run = async {
|
|
758
799
|
worker.run_until_done().await.unwrap();
|
|
@@ -768,35 +809,48 @@ async fn update_rejection_sdk() {
|
|
|
768
809
|
async fn update_fail_sdk() {
|
|
769
810
|
let wf_name = "update_fail_sdk";
|
|
770
811
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
771
|
-
starter.
|
|
812
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
772
813
|
let mut worker = starter.worker().await;
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
ctx
|
|
781
|
-
|
|
782
|
-
|
|
814
|
+
#[workflow]
|
|
815
|
+
#[derive(Default)]
|
|
816
|
+
struct UpdateFailSdkWf;
|
|
817
|
+
|
|
818
|
+
#[workflow_methods]
|
|
819
|
+
impl UpdateFailSdkWf {
|
|
820
|
+
#[run]
|
|
821
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
822
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
823
|
+
Ok(())
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
#[update]
|
|
827
|
+
async fn do_update(
|
|
828
|
+
_ctx: &mut WorkflowContext<Self>,
|
|
829
|
+
_: (),
|
|
830
|
+
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
831
|
+
Err("nooooo".into())
|
|
832
|
+
}
|
|
833
|
+
}
|
|
783
834
|
|
|
784
|
-
|
|
785
|
-
let
|
|
835
|
+
worker.register_workflow::<UpdateFailSdkWf>();
|
|
836
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
837
|
+
let handle = worker
|
|
838
|
+
.submit_workflow(
|
|
839
|
+
UpdateFailSdkWf::run,
|
|
840
|
+
(),
|
|
841
|
+
WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
|
|
842
|
+
)
|
|
843
|
+
.await
|
|
844
|
+
.unwrap();
|
|
786
845
|
let update = async {
|
|
787
|
-
let res =
|
|
788
|
-
.
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
WaitPolicy {
|
|
793
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
794
|
-
},
|
|
795
|
-
[().as_json_payload().unwrap()].into_payloads(),
|
|
846
|
+
let res = handle
|
|
847
|
+
.execute_update(
|
|
848
|
+
UpdateFailSdkWf::do_update,
|
|
849
|
+
(),
|
|
850
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
796
851
|
)
|
|
797
|
-
.await
|
|
798
|
-
|
|
799
|
-
assert!(!res.outcome.unwrap().is_success());
|
|
852
|
+
.await;
|
|
853
|
+
assert!(res.is_err());
|
|
800
854
|
};
|
|
801
855
|
let run = async {
|
|
802
856
|
worker.run_until_done().await.unwrap();
|
|
@@ -812,39 +866,53 @@ async fn update_fail_sdk() {
|
|
|
812
866
|
async fn update_timer_sequence() {
|
|
813
867
|
let wf_name = "update_timer_sequence";
|
|
814
868
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
815
|
-
starter.
|
|
869
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
816
870
|
let mut worker = starter.worker().await;
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
});
|
|
871
|
+
#[workflow]
|
|
872
|
+
#[derive(Default)]
|
|
873
|
+
struct UpdateTimerSequenceWf {
|
|
874
|
+
done: bool,
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
#[workflow_methods]
|
|
878
|
+
impl UpdateTimerSequenceWf {
|
|
879
|
+
#[run]
|
|
880
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
881
|
+
ctx.wait_condition(|s| s.done).await;
|
|
882
|
+
Ok(())
|
|
883
|
+
}
|
|
831
884
|
|
|
832
|
-
|
|
833
|
-
|
|
885
|
+
#[update]
|
|
886
|
+
async fn do_update(
|
|
887
|
+
ctx: &mut WorkflowContext<Self>,
|
|
888
|
+
_: (),
|
|
889
|
+
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
|
890
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
891
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
892
|
+
ctx.state_mut(|s| s.done = true);
|
|
893
|
+
Ok("done".to_string())
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
worker.register_workflow::<UpdateTimerSequenceWf>();
|
|
898
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
899
|
+
let handle = worker
|
|
900
|
+
.submit_workflow(
|
|
901
|
+
UpdateTimerSequenceWf::run,
|
|
902
|
+
(),
|
|
903
|
+
WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
|
|
904
|
+
)
|
|
905
|
+
.await
|
|
906
|
+
.unwrap();
|
|
834
907
|
let update = async {
|
|
835
|
-
let res =
|
|
836
|
-
.
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
WaitPolicy {
|
|
841
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
842
|
-
},
|
|
843
|
-
[().as_json_payload().unwrap()].into_payloads(),
|
|
908
|
+
let res = handle
|
|
909
|
+
.execute_update(
|
|
910
|
+
UpdateTimerSequenceWf::do_update,
|
|
911
|
+
(),
|
|
912
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
844
913
|
)
|
|
845
|
-
.await
|
|
846
|
-
|
|
847
|
-
assert!(res.outcome.unwrap().is_success());
|
|
914
|
+
.await;
|
|
915
|
+
assert!(res.unwrap() == "done");
|
|
848
916
|
};
|
|
849
917
|
let run = async {
|
|
850
918
|
worker.run_until_done().await.unwrap();
|
|
@@ -860,42 +928,62 @@ async fn update_timer_sequence() {
|
|
|
860
928
|
async fn task_failure_during_validation() {
|
|
861
929
|
let wf_name = "task_failure_during_validation";
|
|
862
930
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
863
|
-
starter.
|
|
931
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
864
932
|
starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
|
|
865
933
|
let mut worker = starter.worker().await;
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
)
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
934
|
+
#[workflow]
|
|
935
|
+
#[derive(Default)]
|
|
936
|
+
struct TaskFailureDuringValidationWf;
|
|
937
|
+
|
|
938
|
+
#[workflow_methods]
|
|
939
|
+
impl TaskFailureDuringValidationWf {
|
|
940
|
+
#[run]
|
|
941
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
942
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
943
|
+
Ok(())
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
#[update_validator(do_update)]
|
|
947
|
+
fn validate_do_update(
|
|
948
|
+
&self,
|
|
949
|
+
_ctx: &WorkflowContextView,
|
|
950
|
+
_: &(),
|
|
951
|
+
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
952
|
+
static FAILCT: AtomicUsize = AtomicUsize::new(0);
|
|
953
|
+
if FAILCT.fetch_add(1, Ordering::Relaxed) < 2 {
|
|
954
|
+
panic!("ahhhhhh");
|
|
955
|
+
}
|
|
956
|
+
Ok(())
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
#[update]
|
|
960
|
+
async fn do_update(
|
|
961
|
+
_ctx: &mut WorkflowContext<Self>,
|
|
962
|
+
_: (),
|
|
963
|
+
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
|
964
|
+
Ok("done".to_string())
|
|
965
|
+
}
|
|
966
|
+
}
|
|
882
967
|
|
|
883
|
-
|
|
884
|
-
let
|
|
968
|
+
worker.register_workflow::<TaskFailureDuringValidationWf>();
|
|
969
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
970
|
+
let handle = worker
|
|
971
|
+
.submit_workflow(
|
|
972
|
+
TaskFailureDuringValidationWf::run,
|
|
973
|
+
(),
|
|
974
|
+
WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
|
|
975
|
+
)
|
|
976
|
+
.await
|
|
977
|
+
.unwrap();
|
|
885
978
|
let update = async {
|
|
886
|
-
let res =
|
|
887
|
-
.
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
WaitPolicy {
|
|
892
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
893
|
-
},
|
|
894
|
-
[().as_json_payload().unwrap()].into_payloads(),
|
|
979
|
+
let res = handle
|
|
980
|
+
.execute_update(
|
|
981
|
+
TaskFailureDuringValidationWf::do_update,
|
|
982
|
+
(),
|
|
983
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
895
984
|
)
|
|
896
|
-
.await
|
|
897
|
-
|
|
898
|
-
assert!(res.outcome.unwrap().is_success());
|
|
985
|
+
.await;
|
|
986
|
+
assert!(res.unwrap() == "done");
|
|
899
987
|
};
|
|
900
988
|
let run = async {
|
|
901
989
|
worker.run_until_done().await.unwrap();
|
|
@@ -921,40 +1009,53 @@ async fn task_failure_during_validation() {
|
|
|
921
1009
|
async fn task_failure_after_update() {
|
|
922
1010
|
let wf_name = "task_failure_after_update";
|
|
923
1011
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
924
|
-
starter.
|
|
1012
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
925
1013
|
starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
|
|
926
1014
|
let mut worker = starter.worker().await;
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
)
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1015
|
+
#[workflow]
|
|
1016
|
+
#[derive(Default)]
|
|
1017
|
+
struct TaskFailureAfterUpdateWf;
|
|
1018
|
+
|
|
1019
|
+
#[workflow_methods]
|
|
1020
|
+
impl TaskFailureAfterUpdateWf {
|
|
1021
|
+
#[run]
|
|
1022
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
1023
|
+
static FAILCT: AtomicUsize = AtomicUsize::new(0);
|
|
1024
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
1025
|
+
if FAILCT.fetch_add(1, Ordering::Relaxed) < 1 {
|
|
1026
|
+
panic!("ahhhhhh");
|
|
1027
|
+
}
|
|
1028
|
+
Ok(())
|
|
938
1029
|
}
|
|
939
|
-
Ok(().into())
|
|
940
|
-
});
|
|
941
1030
|
|
|
942
|
-
|
|
943
|
-
|
|
1031
|
+
#[update]
|
|
1032
|
+
async fn do_update(
|
|
1033
|
+
_ctx: &mut WorkflowContext<Self>,
|
|
1034
|
+
_: (),
|
|
1035
|
+
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
|
1036
|
+
Ok("done".to_string())
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
worker.register_workflow::<TaskFailureAfterUpdateWf>();
|
|
1041
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
1042
|
+
let handle = worker
|
|
1043
|
+
.submit_workflow(
|
|
1044
|
+
TaskFailureAfterUpdateWf::run,
|
|
1045
|
+
(),
|
|
1046
|
+
WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
|
|
1047
|
+
)
|
|
1048
|
+
.await
|
|
1049
|
+
.unwrap();
|
|
944
1050
|
let update = async {
|
|
945
|
-
let res =
|
|
946
|
-
.
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
WaitPolicy {
|
|
951
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
952
|
-
},
|
|
953
|
-
[().as_json_payload().unwrap()].into_payloads(),
|
|
1051
|
+
let res = handle
|
|
1052
|
+
.execute_update(
|
|
1053
|
+
TaskFailureAfterUpdateWf::do_update,
|
|
1054
|
+
(),
|
|
1055
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
954
1056
|
)
|
|
955
|
-
.await
|
|
956
|
-
|
|
957
|
-
assert!(res.outcome.unwrap().is_success());
|
|
1057
|
+
.await;
|
|
1058
|
+
assert!(res.unwrap() == "done");
|
|
958
1059
|
};
|
|
959
1060
|
let run = async {
|
|
960
1061
|
worker.run_until_done().await.unwrap();
|
|
@@ -966,68 +1067,94 @@ async fn task_failure_after_update() {
|
|
|
966
1067
|
.unwrap();
|
|
967
1068
|
}
|
|
968
1069
|
|
|
1070
|
+
static BARR: LazyLock<Barrier> = LazyLock::new(|| Barrier::new(2));
|
|
1071
|
+
static ACT_RAN: AtomicBool = AtomicBool::new(false);
|
|
969
1072
|
#[tokio::test]
|
|
970
1073
|
async fn worker_restarted_in_middle_of_update() {
|
|
971
1074
|
let wf_name = "worker_restarted_in_middle_of_update";
|
|
972
1075
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
1076
|
+
|
|
1077
|
+
struct BlockingActivities;
|
|
1078
|
+
#[activities]
|
|
1079
|
+
impl BlockingActivities {
|
|
1080
|
+
#[activity]
|
|
1081
|
+
async fn blocks(_ctx: ActivityContext, echo_me: String) -> Result<String, ActivityError> {
|
|
1082
|
+
BARR.wait().await;
|
|
1083
|
+
if !ACT_RAN.fetch_or(true, Ordering::Relaxed) {
|
|
1084
|
+
// On first run fail the task so we'll get retried on the new worker
|
|
1085
|
+
return Err(anyhow!("Fail first time").into());
|
|
1086
|
+
}
|
|
1087
|
+
Ok(echo_me)
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
starter.sdk_config.register_activities(BlockingActivities);
|
|
973
1092
|
let mut worker = starter.worker().await;
|
|
974
1093
|
let client = starter.get_client().await;
|
|
975
1094
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
..Default::default()
|
|
989
|
-
})
|
|
990
|
-
.await;
|
|
991
|
-
Ok(())
|
|
992
|
-
},
|
|
993
|
-
);
|
|
994
|
-
let mut sig = ctx.make_signal_channel("done");
|
|
995
|
-
sig.next().await;
|
|
996
|
-
Ok(().into())
|
|
997
|
-
});
|
|
998
|
-
worker.register_activity("blocks", |_ctx: ActContext, echo_me: String| async move {
|
|
999
|
-
BARR.wait().await;
|
|
1000
|
-
if !ACT_RAN.fetch_or(true, Ordering::Relaxed) {
|
|
1001
|
-
// On first run fail the task so we'll get retried on the new worker
|
|
1002
|
-
return Err(anyhow!("Fail first time").into());
|
|
1095
|
+
#[workflow]
|
|
1096
|
+
#[derive(Default)]
|
|
1097
|
+
struct WorkerRestartedInMiddleOfUpdateWf {
|
|
1098
|
+
done: bool,
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
#[workflow_methods]
|
|
1102
|
+
impl WorkerRestartedInMiddleOfUpdateWf {
|
|
1103
|
+
#[run]
|
|
1104
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
1105
|
+
ctx.wait_condition(|s| s.done).await;
|
|
1106
|
+
Ok(())
|
|
1003
1107
|
}
|
|
1004
|
-
Ok(echo_me)
|
|
1005
|
-
});
|
|
1006
1108
|
|
|
1007
|
-
|
|
1109
|
+
#[signal]
|
|
1110
|
+
fn done_signal(&mut self, _ctx: &mut SyncWorkflowContext<Self>, _: ()) {
|
|
1111
|
+
self.done = true;
|
|
1112
|
+
}
|
|
1008
1113
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1114
|
+
#[update]
|
|
1115
|
+
async fn do_update(
|
|
1116
|
+
ctx: &mut WorkflowContext<Self>,
|
|
1117
|
+
_: (),
|
|
1118
|
+
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
1119
|
+
ctx.start_activity(
|
|
1120
|
+
BlockingActivities::blocks,
|
|
1121
|
+
"hi!".to_string(),
|
|
1122
|
+
ActivityOptions {
|
|
1123
|
+
start_to_close_timeout: Some(Duration::from_secs(2)),
|
|
1124
|
+
..Default::default()
|
|
1018
1125
|
},
|
|
1019
|
-
[().as_json_payload().unwrap()].into_payloads(),
|
|
1020
1126
|
)
|
|
1021
|
-
.await
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1127
|
+
.await?;
|
|
1128
|
+
Ok(())
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
worker.register_workflow::<WorkerRestartedInMiddleOfUpdateWf>();
|
|
1133
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
1134
|
+
let handle = worker
|
|
1135
|
+
.submit_workflow(
|
|
1136
|
+
WorkerRestartedInMiddleOfUpdateWf::run,
|
|
1137
|
+
(),
|
|
1138
|
+
WorkflowStartOptions::new(task_queue.clone(), starter.get_wf_id().to_owned()).build(),
|
|
1139
|
+
)
|
|
1140
|
+
.await
|
|
1141
|
+
.unwrap();
|
|
1142
|
+
|
|
1143
|
+
let wf_id = task_queue;
|
|
1144
|
+
let update = async {
|
|
1145
|
+
let res = handle
|
|
1146
|
+
.execute_update(
|
|
1147
|
+
WorkerRestartedInMiddleOfUpdateWf::do_update,
|
|
1148
|
+
(),
|
|
1149
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
1150
|
+
)
|
|
1151
|
+
.await;
|
|
1152
|
+
assert!(res.is_ok());
|
|
1153
|
+
handle
|
|
1154
|
+
.signal(
|
|
1155
|
+
WorkerRestartedInMiddleOfUpdateWf::done_signal,
|
|
1156
|
+
(),
|
|
1157
|
+
WorkflowSignalOptions::default(),
|
|
1031
1158
|
)
|
|
1032
1159
|
.await
|
|
1033
1160
|
.unwrap();
|
|
@@ -1041,10 +1168,19 @@ async fn worker_restarted_in_middle_of_update() {
|
|
|
1041
1168
|
// Allow it to start again, the second time
|
|
1042
1169
|
BARR.wait().await;
|
|
1043
1170
|
// Poke the workflow off the sticky queue to get it to complete faster than WFT timeout
|
|
1044
|
-
|
|
1045
|
-
.
|
|
1046
|
-
|
|
1047
|
-
|
|
1171
|
+
WorkflowService::reset_sticky_task_queue(
|
|
1172
|
+
&mut client.clone(),
|
|
1173
|
+
ResetStickyTaskQueueRequest {
|
|
1174
|
+
namespace: client.namespace(),
|
|
1175
|
+
execution: Some(WorkflowExecution {
|
|
1176
|
+
workflow_id: wf_id.clone(),
|
|
1177
|
+
run_id: "".to_string(),
|
|
1178
|
+
}),
|
|
1179
|
+
}
|
|
1180
|
+
.into_request(),
|
|
1181
|
+
)
|
|
1182
|
+
.await
|
|
1183
|
+
.unwrap();
|
|
1048
1184
|
};
|
|
1049
1185
|
let run = async {
|
|
1050
1186
|
// This run attempt will get shut down
|
|
@@ -1066,79 +1202,94 @@ async fn worker_restarted_in_middle_of_update() {
|
|
|
1066
1202
|
async fn update_after_empty_wft() {
|
|
1067
1203
|
let wf_name = "update_after_empty_wft";
|
|
1068
1204
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
1205
|
+
starter.sdk_config.register_activities(StdActivities);
|
|
1069
1206
|
let mut worker = starter.worker().await;
|
|
1070
|
-
let client = starter.get_client().await;
|
|
1071
1207
|
|
|
1072
1208
|
static ACT_STARTED: AtomicBool = AtomicBool::new(false);
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1209
|
+
|
|
1210
|
+
#[workflow]
|
|
1211
|
+
#[derive(Default)]
|
|
1212
|
+
struct UpdateAfterEmptyWftWf {
|
|
1213
|
+
signal_received: bool,
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
#[workflow_methods]
|
|
1217
|
+
impl UpdateAfterEmptyWftWf {
|
|
1218
|
+
#[run]
|
|
1219
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
1220
|
+
let sig_handle = async {
|
|
1221
|
+
ctx.wait_condition(|s| s.signal_received).await;
|
|
1222
|
+
ACT_STARTED.store(true, Ordering::Release);
|
|
1223
|
+
let _ = ctx
|
|
1224
|
+
.start_activity(
|
|
1225
|
+
StdActivities::echo,
|
|
1226
|
+
"hi!".to_string(),
|
|
1227
|
+
ActivityOptions {
|
|
1228
|
+
start_to_close_timeout: Some(Duration::from_secs(2)),
|
|
1229
|
+
..Default::default()
|
|
1230
|
+
},
|
|
1231
|
+
)
|
|
1232
|
+
.await;
|
|
1233
|
+
ACT_STARTED.store(false, Ordering::Release);
|
|
1234
|
+
};
|
|
1235
|
+
join!(sig_handle, async {
|
|
1236
|
+
ctx.timer(Duration::from_secs(2)).await;
|
|
1237
|
+
});
|
|
1238
|
+
Ok(())
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
#[signal]
|
|
1242
|
+
fn signal_handler(&mut self, _ctx: &mut SyncWorkflowContext<Self>, _: ()) {
|
|
1243
|
+
self.signal_received = true;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
#[update]
|
|
1247
|
+
async fn do_update(ctx: &mut WorkflowContext<Self>, _: ()) {
|
|
1248
|
+
if ACT_STARTED.load(Ordering::Acquire) {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
let _ = ctx
|
|
1252
|
+
.start_activity(
|
|
1253
|
+
StdActivities::echo,
|
|
1254
|
+
"hi!".to_string(),
|
|
1255
|
+
ActivityOptions {
|
|
1085
1256
|
start_to_close_timeout: Some(Duration::from_secs(2)),
|
|
1086
1257
|
..Default::default()
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
let mut sig = ctx.make_signal_channel("signal");
|
|
1093
|
-
let sig_handle = async {
|
|
1094
|
-
sig.next().await;
|
|
1095
|
-
ACT_STARTED.store(true, Ordering::Release);
|
|
1096
|
-
ctx.activity(ActivityOptions {
|
|
1097
|
-
activity_type: "echo".to_string(),
|
|
1098
|
-
input: "hi!".as_json_payload().expect("serializes fine"),
|
|
1099
|
-
start_to_close_timeout: Some(Duration::from_secs(2)),
|
|
1100
|
-
..Default::default()
|
|
1101
|
-
})
|
|
1102
|
-
.await;
|
|
1103
|
-
ACT_STARTED.store(false, Ordering::Release);
|
|
1104
|
-
};
|
|
1105
|
-
join!(sig_handle, async {
|
|
1106
|
-
ctx.timer(Duration::from_secs(2)).await;
|
|
1107
|
-
});
|
|
1108
|
-
Ok(().into())
|
|
1109
|
-
});
|
|
1110
|
-
worker.register_activity("echo", |_ctx: ActContext, echo_me: String| async move {
|
|
1111
|
-
Ok(echo_me)
|
|
1112
|
-
});
|
|
1258
|
+
},
|
|
1259
|
+
)
|
|
1260
|
+
.await;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1113
1263
|
|
|
1114
|
-
|
|
1264
|
+
worker.register_workflow::<UpdateAfterEmptyWftWf>();
|
|
1265
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
1266
|
+
let handle = worker
|
|
1267
|
+
.submit_workflow(
|
|
1268
|
+
UpdateAfterEmptyWftWf::run,
|
|
1269
|
+
(),
|
|
1270
|
+
WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
|
|
1271
|
+
)
|
|
1272
|
+
.await
|
|
1273
|
+
.unwrap();
|
|
1115
1274
|
|
|
1116
|
-
let wf_id = starter.get_task_queue().to_string();
|
|
1117
1275
|
let update = async {
|
|
1118
|
-
|
|
1119
|
-
.
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
None,
|
|
1124
|
-
None,
|
|
1276
|
+
handle
|
|
1277
|
+
.signal(
|
|
1278
|
+
UpdateAfterEmptyWftWf::signal_handler,
|
|
1279
|
+
(),
|
|
1280
|
+
WorkflowSignalOptions::default(),
|
|
1125
1281
|
)
|
|
1126
1282
|
.await
|
|
1127
1283
|
.unwrap();
|
|
1128
1284
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
|
1129
|
-
|
|
1130
|
-
.
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
WaitPolicy {
|
|
1135
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
1136
|
-
},
|
|
1137
|
-
[().as_json_payload().unwrap()].into_payloads(),
|
|
1285
|
+
handle
|
|
1286
|
+
.execute_update(
|
|
1287
|
+
UpdateAfterEmptyWftWf::do_update,
|
|
1288
|
+
(),
|
|
1289
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
1138
1290
|
)
|
|
1139
1291
|
.await
|
|
1140
1292
|
.unwrap();
|
|
1141
|
-
assert!(res.outcome.unwrap().is_success());
|
|
1142
1293
|
};
|
|
1143
1294
|
let runner = async {
|
|
1144
1295
|
worker.run_until_done().await.unwrap();
|
|
@@ -1154,64 +1305,69 @@ async fn update_after_empty_wft() {
|
|
|
1154
1305
|
async fn update_lost_on_activity_mismatch() {
|
|
1155
1306
|
let wf_name = "update_lost_on_activity_mismatch";
|
|
1156
1307
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
1308
|
+
starter.sdk_config.register_activities(StdActivities);
|
|
1157
1309
|
let mut worker = starter.worker().await;
|
|
1158
|
-
let client = starter.get_client().await;
|
|
1159
1310
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1311
|
+
#[workflow]
|
|
1312
|
+
#[derive(Default)]
|
|
1313
|
+
struct UpdateLostOnActivityMismatchWf {
|
|
1314
|
+
can_run: usize,
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
#[workflow_methods]
|
|
1318
|
+
impl UpdateLostOnActivityMismatchWf {
|
|
1319
|
+
#[run]
|
|
1320
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
1321
|
+
ctx.state_mut(|s| s.can_run = 1);
|
|
1322
|
+
for _ in 1..=3 {
|
|
1323
|
+
ctx.wait_condition(|s| s.can_run > 0).await;
|
|
1324
|
+
let _ = ctx
|
|
1325
|
+
.start_activity(
|
|
1326
|
+
StdActivities::echo,
|
|
1327
|
+
"hi!".to_string(),
|
|
1328
|
+
ActivityOptions {
|
|
1329
|
+
start_to_close_timeout: Some(Duration::from_secs(2)),
|
|
1330
|
+
..Default::default()
|
|
1331
|
+
},
|
|
1332
|
+
)
|
|
1333
|
+
.await;
|
|
1334
|
+
ctx.state_mut(|s| s.can_run -= 1);
|
|
1335
|
+
}
|
|
1336
|
+
Ok(())
|
|
1185
1337
|
}
|
|
1186
|
-
Ok(().into())
|
|
1187
|
-
});
|
|
1188
|
-
worker.register_activity("echo", |_ctx: ActContext, echo_me: String| async move {
|
|
1189
|
-
Ok(echo_me)
|
|
1190
|
-
});
|
|
1191
1338
|
|
|
1192
|
-
|
|
1193
|
-
|
|
1339
|
+
#[update]
|
|
1340
|
+
fn do_update(&mut self, _ctx: &mut SyncWorkflowContext<Self>, _: ()) {
|
|
1341
|
+
self.can_run += 1;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
worker.register_workflow::<UpdateLostOnActivityMismatchWf>();
|
|
1346
|
+
let core_worker = worker.core_worker();
|
|
1347
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
1348
|
+
let handle = worker
|
|
1349
|
+
.submit_workflow(
|
|
1350
|
+
UpdateLostOnActivityMismatchWf::run,
|
|
1351
|
+
(),
|
|
1352
|
+
WorkflowStartOptions::new(task_queue, starter.get_wf_id().to_owned()).build(),
|
|
1353
|
+
)
|
|
1354
|
+
.await
|
|
1355
|
+
.unwrap();
|
|
1194
1356
|
|
|
1195
|
-
let wf_id = starter.get_task_queue().to_string();
|
|
1196
1357
|
let update = async {
|
|
1197
1358
|
// Need time to get to condition
|
|
1198
1359
|
tokio::time::sleep(Duration::from_millis(200)).await;
|
|
1199
1360
|
// Evict wf
|
|
1200
|
-
core_worker.request_workflow_eviction(handle.
|
|
1361
|
+
core_worker.request_workflow_eviction(handle.run_id().unwrap());
|
|
1201
1362
|
for _ in 1..=2 {
|
|
1202
|
-
|
|
1203
|
-
.
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
WaitPolicy {
|
|
1208
|
-
lifecycle_stage: UpdateWorkflowExecutionLifecycleStage::Completed as i32,
|
|
1209
|
-
},
|
|
1210
|
-
[().as_json_payload().unwrap()].into_payloads(),
|
|
1363
|
+
handle
|
|
1364
|
+
.execute_update(
|
|
1365
|
+
UpdateLostOnActivityMismatchWf::do_update,
|
|
1366
|
+
(),
|
|
1367
|
+
WorkflowExecuteUpdateOptions::default(),
|
|
1211
1368
|
)
|
|
1212
1369
|
.await
|
|
1213
1370
|
.unwrap();
|
|
1214
|
-
assert!(res.outcome.unwrap().is_success());
|
|
1215
1371
|
}
|
|
1216
1372
|
};
|
|
1217
1373
|
let runner = async {
|