@temporalio/core-bridge 1.13.0 → 1.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +239 -382
- package/Cargo.toml +11 -11
- package/lib/native.d.ts +10 -3
- package/package.json +3 -3
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.cargo/config.toml +71 -11
- package/sdk-core/.clippy.toml +1 -0
- package/sdk-core/.github/workflows/heavy.yml +2 -0
- package/sdk-core/.github/workflows/per-pr.yml +50 -18
- package/sdk-core/ARCHITECTURE.md +44 -48
- package/sdk-core/Cargo.toml +26 -7
- package/sdk-core/README.md +4 -0
- package/sdk-core/arch_docs/diagrams/TimerMachine_Coverage.puml +14 -0
- package/sdk-core/arch_docs/diagrams/initial_event_history.png +0 -0
- package/sdk-core/arch_docs/sdks_intro.md +299 -0
- package/sdk-core/client/Cargo.toml +8 -7
- package/sdk-core/client/src/callback_based.rs +1 -2
- package/sdk-core/client/src/lib.rs +485 -299
- package/sdk-core/client/src/metrics.rs +32 -8
- package/sdk-core/client/src/proxy.rs +124 -5
- package/sdk-core/client/src/raw.rs +598 -307
- package/sdk-core/client/src/replaceable.rs +253 -0
- package/sdk-core/client/src/retry.rs +9 -6
- package/sdk-core/client/src/worker_registry/mod.rs +19 -3
- package/sdk-core/client/src/workflow_handle/mod.rs +20 -17
- package/sdk-core/core/Cargo.toml +100 -31
- package/sdk-core/core/src/core_tests/activity_tasks.rs +55 -225
- package/sdk-core/core/src/core_tests/mod.rs +2 -8
- package/sdk-core/core/src/core_tests/queries.rs +3 -5
- package/sdk-core/core/src/core_tests/replay_flag.rs +3 -62
- package/sdk-core/core/src/core_tests/updates.rs +4 -5
- package/sdk-core/core/src/core_tests/workers.rs +4 -3
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +10 -7
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +28 -291
- package/sdk-core/core/src/ephemeral_server/mod.rs +15 -3
- package/sdk-core/core/src/internal_flags.rs +11 -1
- package/sdk-core/core/src/lib.rs +50 -36
- package/sdk-core/core/src/pollers/mod.rs +5 -5
- package/sdk-core/core/src/pollers/poll_buffer.rs +2 -2
- package/sdk-core/core/src/protosext/mod.rs +13 -5
- package/sdk-core/core/src/protosext/protocol_messages.rs +4 -11
- package/sdk-core/core/src/retry_logic.rs +256 -108
- package/sdk-core/core/src/telemetry/metrics.rs +1 -0
- package/sdk-core/core/src/telemetry/mod.rs +8 -2
- package/sdk-core/core/src/telemetry/prometheus_meter.rs +2 -2
- package/sdk-core/core/src/test_help/integ_helpers.rs +971 -0
- package/sdk-core/core/src/test_help/mod.rs +10 -1100
- package/sdk-core/core/src/test_help/unit_helpers.rs +218 -0
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +42 -6
- package/sdk-core/core/src/worker/activities/local_activities.rs +19 -19
- package/sdk-core/core/src/worker/activities.rs +10 -3
- package/sdk-core/core/src/worker/client/mocks.rs +3 -3
- package/sdk-core/core/src/worker/client.rs +130 -93
- package/sdk-core/core/src/worker/heartbeat.rs +12 -13
- package/sdk-core/core/src/worker/mod.rs +31 -21
- package/sdk-core/core/src/worker/nexus.rs +14 -3
- package/sdk-core/core/src/worker/slot_provider.rs +9 -0
- package/sdk-core/core/src/worker/tuner.rs +159 -0
- package/sdk-core/core/src/worker/workflow/history_update.rs +3 -265
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -54
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +0 -82
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +0 -67
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -192
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +0 -43
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +6 -554
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -71
- package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +102 -3
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +10 -539
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +0 -139
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -119
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +6 -63
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +9 -4
- package/sdk-core/core/src/worker/workflow/mod.rs +5 -1
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +8 -3
- package/sdk-core/core-api/Cargo.toml +4 -4
- package/sdk-core/core-api/src/envconfig.rs +153 -54
- package/sdk-core/core-api/src/lib.rs +68 -0
- package/sdk-core/core-api/src/telemetry/metrics.rs +2 -1
- package/sdk-core/core-api/src/telemetry.rs +13 -0
- package/sdk-core/core-c-bridge/Cargo.toml +13 -8
- package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +184 -22
- package/sdk-core/core-c-bridge/src/client.rs +462 -184
- package/sdk-core/core-c-bridge/src/envconfig.rs +314 -0
- package/sdk-core/core-c-bridge/src/lib.rs +1 -0
- package/sdk-core/core-c-bridge/src/random.rs +4 -4
- package/sdk-core/core-c-bridge/src/runtime.rs +22 -23
- package/sdk-core/core-c-bridge/src/testing.rs +1 -4
- package/sdk-core/core-c-bridge/src/tests/context.rs +31 -31
- package/sdk-core/core-c-bridge/src/tests/mod.rs +32 -28
- package/sdk-core/core-c-bridge/src/tests/utils.rs +7 -7
- package/sdk-core/core-c-bridge/src/worker.rs +319 -66
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -1
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +5 -5
- package/sdk-core/sdk/Cargo.toml +8 -2
- package/sdk-core/sdk/src/activity_context.rs +1 -1
- package/sdk-core/sdk/src/app_data.rs +1 -1
- package/sdk-core/sdk/src/interceptors.rs +1 -4
- package/sdk-core/sdk/src/lib.rs +1 -5
- package/sdk-core/sdk/src/workflow_context/options.rs +10 -1
- package/sdk-core/sdk/src/workflow_future.rs +1 -1
- package/sdk-core/sdk-core-protos/Cargo.toml +6 -6
- package/sdk-core/sdk-core-protos/build.rs +10 -23
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +9 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +254 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +234 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +6 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -6
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
- package/sdk-core/{test-utils → sdk-core-protos}/src/canned_histories.rs +5 -5
- package/sdk-core/sdk-core-protos/src/history_builder.rs +2 -2
- package/sdk-core/sdk-core-protos/src/lib.rs +25 -9
- package/sdk-core/sdk-core-protos/src/test_utils.rs +89 -0
- package/sdk-core/sdk-core-protos/src/utilities.rs +14 -5
- package/sdk-core/tests/c_bridge_smoke_test.c +10 -0
- package/sdk-core/tests/cloud_tests.rs +10 -8
- package/sdk-core/tests/common/http_proxy.rs +134 -0
- package/sdk-core/{test-utils/src/lib.rs → tests/common/mod.rs} +214 -281
- package/sdk-core/{test-utils/src → tests/common}/workflows.rs +4 -3
- package/sdk-core/tests/fuzzy_workflow.rs +1 -1
- package/sdk-core/tests/global_metric_tests.rs +8 -7
- package/sdk-core/tests/heavy_tests.rs +7 -3
- package/sdk-core/tests/integ_tests/client_tests.rs +111 -24
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +14 -9
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +4 -4
- package/sdk-core/tests/integ_tests/metrics_tests.rs +114 -14
- package/sdk-core/tests/integ_tests/pagination_tests.rs +273 -0
- package/sdk-core/tests/integ_tests/polling_tests.rs +311 -93
- package/sdk-core/tests/integ_tests/queries_tests.rs +4 -4
- package/sdk-core/tests/integ_tests/update_tests.rs +13 -7
- package/sdk-core/tests/integ_tests/visibility_tests.rs +26 -9
- package/sdk-core/tests/integ_tests/worker_tests.rs +668 -13
- package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +40 -24
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +244 -11
- package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +78 -2
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +61 -2
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +465 -7
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +41 -2
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +315 -3
- package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1990 -14
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +65 -2
- package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +123 -23
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +525 -3
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +65 -16
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +32 -23
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +126 -5
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +1 -2
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +124 -8
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +62 -2
- package/sdk-core/tests/integ_tests/workflow_tests.rs +67 -8
- package/sdk-core/tests/main.rs +26 -17
- package/sdk-core/tests/manual_tests.rs +5 -1
- package/sdk-core/tests/runner.rs +22 -40
- package/sdk-core/tests/shared_tests/mod.rs +1 -1
- package/sdk-core/tests/shared_tests/priority.rs +1 -1
- package/sdk-core/{core/benches/workflow_replay.rs → tests/workflow_replay_bench.rs} +10 -5
- package/src/client.rs +97 -20
- package/src/helpers/callbacks.rs +4 -4
- package/src/helpers/errors.rs +7 -1
- package/src/helpers/handles.rs +1 -0
- package/src/helpers/try_from_js.rs +4 -3
- package/src/lib.rs +3 -2
- package/src/metrics.rs +3 -0
- package/src/runtime.rs +5 -2
- package/src/worker.rs +9 -12
- package/ts/native.ts +13 -3
- package/sdk-core/arch_docs/diagrams/workflow_internals.svg +0 -1
- package/sdk-core/core/src/core_tests/child_workflows.rs +0 -281
- package/sdk-core/core/src/core_tests/determinism.rs +0 -318
- package/sdk-core/core/src/core_tests/local_activities.rs +0 -1442
- package/sdk-core/test-utils/Cargo.toml +0 -38
- package/sdk-core/test-utils/src/histfetch.rs +0 -28
- package/sdk-core/test-utils/src/interceptors.rs +0 -46
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
use crate::
|
|
1
|
+
use crate::{
|
|
2
|
+
common::{CoreWfStarter, eventually},
|
|
3
|
+
integ_tests::activity_functions::echo,
|
|
4
|
+
};
|
|
2
5
|
use std::time::Duration;
|
|
3
6
|
use temporal_client::{NamespacedClient, WorkflowOptions, WorkflowService};
|
|
4
7
|
use temporal_sdk::{ActivityOptions, WfContext};
|
|
8
|
+
use temporal_sdk_core::test_help::WorkerTestHelpers;
|
|
5
9
|
use temporal_sdk_core_api::worker::{
|
|
6
10
|
WorkerDeploymentOptions, WorkerDeploymentVersion, WorkerVersioningStrategy,
|
|
7
11
|
};
|
|
@@ -18,8 +22,8 @@ use temporal_sdk_core_protos::{
|
|
|
18
22
|
},
|
|
19
23
|
},
|
|
20
24
|
};
|
|
21
|
-
use temporal_sdk_core_test_utils::{CoreWfStarter, WorkerTestHelpers, eventually};
|
|
22
25
|
use tokio::join;
|
|
26
|
+
use tonic::IntoRequest;
|
|
23
27
|
|
|
24
28
|
#[rstest::rstest]
|
|
25
29
|
#[tokio::test]
|
|
@@ -73,10 +77,13 @@ async fn sets_deployment_info_on_task_responses(#[values(true, false)] use_defau
|
|
|
73
77
|
client
|
|
74
78
|
.get_client()
|
|
75
79
|
.clone()
|
|
76
|
-
.describe_worker_deployment(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
.describe_worker_deployment(
|
|
81
|
+
DescribeWorkerDeploymentRequest {
|
|
82
|
+
namespace: client.namespace(),
|
|
83
|
+
deployment_name: deploy_name.clone(),
|
|
84
|
+
}
|
|
85
|
+
.into_request(),
|
|
86
|
+
)
|
|
80
87
|
.await
|
|
81
88
|
},
|
|
82
89
|
Duration::from_secs(5),
|
|
@@ -89,13 +96,16 @@ async fn sets_deployment_info_on_task_responses(#[values(true, false)] use_defau
|
|
|
89
96
|
client
|
|
90
97
|
.get_client()
|
|
91
98
|
.clone()
|
|
92
|
-
.set_worker_deployment_current_version(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
.set_worker_deployment_current_version(
|
|
100
|
+
SetWorkerDeploymentCurrentVersionRequest {
|
|
101
|
+
namespace: client.namespace(),
|
|
102
|
+
deployment_name: deploy_name.clone(),
|
|
103
|
+
version: format!("{deploy_name}.1.0"),
|
|
104
|
+
conflict_token: desc_resp.conflict_token,
|
|
105
|
+
..Default::default()
|
|
106
|
+
}
|
|
107
|
+
.into_request(),
|
|
108
|
+
)
|
|
99
109
|
.await
|
|
100
110
|
.unwrap();
|
|
101
111
|
|
|
@@ -175,10 +185,13 @@ async fn activity_has_deployment_stamp() {
|
|
|
175
185
|
client
|
|
176
186
|
.get_client()
|
|
177
187
|
.clone()
|
|
178
|
-
.describe_worker_deployment(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
188
|
+
.describe_worker_deployment(
|
|
189
|
+
DescribeWorkerDeploymentRequest {
|
|
190
|
+
namespace: client.namespace(),
|
|
191
|
+
deployment_name: deploy_name.clone(),
|
|
192
|
+
}
|
|
193
|
+
.into_request(),
|
|
194
|
+
)
|
|
182
195
|
.await
|
|
183
196
|
},
|
|
184
197
|
Duration::from_secs(50),
|
|
@@ -191,13 +204,16 @@ async fn activity_has_deployment_stamp() {
|
|
|
191
204
|
client
|
|
192
205
|
.get_client()
|
|
193
206
|
.clone()
|
|
194
|
-
.set_worker_deployment_current_version(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
207
|
+
.set_worker_deployment_current_version(
|
|
208
|
+
SetWorkerDeploymentCurrentVersionRequest {
|
|
209
|
+
namespace: client.namespace(),
|
|
210
|
+
deployment_name: deploy_name.clone(),
|
|
211
|
+
version: format!("{deploy_name}.1.0"),
|
|
212
|
+
conflict_token: desc_resp.conflict_token,
|
|
213
|
+
..Default::default()
|
|
214
|
+
}
|
|
215
|
+
.into_request(),
|
|
216
|
+
)
|
|
201
217
|
.await
|
|
202
218
|
.unwrap();
|
|
203
219
|
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
use crate::
|
|
1
|
+
use crate::{
|
|
2
|
+
common::{
|
|
3
|
+
ActivationAssertionsInterceptor, CoreWfStarter, INTEG_CLIENT_IDENTITY, build_fake_sdk,
|
|
4
|
+
eventually, init_core_and_create_wf, mock_sdk, mock_sdk_cfg,
|
|
5
|
+
},
|
|
6
|
+
integ_tests::activity_functions::echo,
|
|
7
|
+
};
|
|
2
8
|
use anyhow::anyhow;
|
|
3
9
|
use assert_matches::assert_matches;
|
|
4
10
|
use futures_util::future::join_all;
|
|
@@ -9,14 +15,17 @@ use std::{
|
|
|
9
15
|
use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowExecutionResult, WorkflowOptions};
|
|
10
16
|
use temporal_sdk::{
|
|
11
17
|
ActContext, ActExitValue, ActivityError, ActivityOptions, CancellableFuture, WfContext,
|
|
12
|
-
WfExitValue, WorkflowResult,
|
|
18
|
+
WfExitValue, WorkflowFunction, WorkflowResult,
|
|
19
|
+
};
|
|
20
|
+
use temporal_sdk_core::test_help::{
|
|
21
|
+
MockPollCfg, ResponseType, WorkerTestHelpers, drain_pollers_and_shutdown, mock_worker_client,
|
|
13
22
|
};
|
|
14
23
|
use temporal_sdk_core_api::worker::PollerBehavior;
|
|
15
24
|
use temporal_sdk_core_protos::{
|
|
16
|
-
DEFAULT_ACTIVITY_TYPE, TaskToken,
|
|
25
|
+
DEFAULT_ACTIVITY_TYPE, DEFAULT_WORKFLOW_TYPE, TaskToken, TestHistoryBuilder, canned_histories,
|
|
17
26
|
coresdk::{
|
|
18
27
|
ActivityHeartbeat, ActivityTaskCompletion, AsJsonPayloadExt, FromJsonPayloadExt,
|
|
19
|
-
IntoCompletion,
|
|
28
|
+
IntoCompletion, IntoPayloadsExt,
|
|
20
29
|
activity_result::{
|
|
21
30
|
self, ActivityExecutionResult, ActivityResolution, activity_resolution as act_res,
|
|
22
31
|
},
|
|
@@ -29,15 +38,14 @@ use temporal_sdk_core_protos::{
|
|
|
29
38
|
},
|
|
30
39
|
workflow_completion::WorkflowActivationCompletion,
|
|
31
40
|
},
|
|
41
|
+
prost_dur,
|
|
32
42
|
temporal::api::{
|
|
33
43
|
common::v1::{ActivityType, Payload, Payloads, RetryPolicy},
|
|
34
|
-
enums::v1::RetryState,
|
|
44
|
+
enums::v1::{CommandType, EventType, RetryState},
|
|
35
45
|
failure::v1::{ActivityFailureInfo, Failure, failure::FailureInfo},
|
|
46
|
+
sdk::v1::UserMetadata,
|
|
36
47
|
},
|
|
37
|
-
|
|
38
|
-
use temporal_sdk_core_test_utils::{
|
|
39
|
-
CoreWfStarter, WorkerTestHelpers, drain_pollers_and_shutdown, init_core_and_create_wf,
|
|
40
|
-
schedule_activity_cmd,
|
|
48
|
+
test_utils::schedule_activity_cmd,
|
|
41
49
|
};
|
|
42
50
|
use tokio::{join, sync::Semaphore, time::sleep};
|
|
43
51
|
|
|
@@ -198,7 +206,7 @@ async fn activity_non_retryable_failure() {
|
|
|
198
206
|
}),
|
|
199
207
|
scheduled_event_id: 5,
|
|
200
208
|
started_event_id: 6,
|
|
201
|
-
identity:
|
|
209
|
+
identity: INTEG_CLIENT_IDENTITY.to_owned(),
|
|
202
210
|
retry_state: RetryState::NonRetryableFailure as i32,
|
|
203
211
|
})),
|
|
204
212
|
..Default::default()
|
|
@@ -265,7 +273,7 @@ async fn activity_non_retryable_failure_with_error() {
|
|
|
265
273
|
}),
|
|
266
274
|
scheduled_event_id: 5,
|
|
267
275
|
started_event_id: 6,
|
|
268
|
-
identity:
|
|
276
|
+
identity: INTEG_CLIENT_IDENTITY.to_owned(),
|
|
269
277
|
retry_state: RetryState::NonRetryableFailure as i32,
|
|
270
278
|
})),
|
|
271
279
|
..Default::default()
|
|
@@ -790,6 +798,86 @@ async fn activity_cancelled_after_heartbeat_times_out() {
|
|
|
790
798
|
.unwrap();
|
|
791
799
|
}
|
|
792
800
|
|
|
801
|
+
#[ignore] // Currently skipped because of https://github.com/temporalio/temporal/issues/8376
|
|
802
|
+
#[tokio::test]
|
|
803
|
+
async fn activity_heartbeat_not_flushed_on_success() {
|
|
804
|
+
let mut starter = init_core_and_create_wf("activity_heartbeat_not_flushed_on_success").await;
|
|
805
|
+
let core = starter.get_worker().await;
|
|
806
|
+
let task_q = starter.get_task_queue().to_string();
|
|
807
|
+
let activity_id = "act-1";
|
|
808
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
|
809
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
810
|
+
task.run_id,
|
|
811
|
+
ScheduleActivity {
|
|
812
|
+
seq: 0,
|
|
813
|
+
activity_id: activity_id.to_string(),
|
|
814
|
+
activity_type: "dontcare".to_string(),
|
|
815
|
+
task_queue: task_q.clone(),
|
|
816
|
+
schedule_to_close_timeout: Some(prost_dur!(from_secs(60))),
|
|
817
|
+
heartbeat_timeout: Some(prost_dur!(from_secs(10))),
|
|
818
|
+
retry_policy: Some(RetryPolicy {
|
|
819
|
+
maximum_attempts: 2,
|
|
820
|
+
initial_interval: Some(prost_dur!(from_secs(5))),
|
|
821
|
+
..Default::default()
|
|
822
|
+
}),
|
|
823
|
+
..Default::default()
|
|
824
|
+
}
|
|
825
|
+
.into(),
|
|
826
|
+
))
|
|
827
|
+
.await
|
|
828
|
+
.unwrap();
|
|
829
|
+
// Poll activity and verify that it's been scheduled
|
|
830
|
+
let task = core.poll_activity_task().await.unwrap();
|
|
831
|
+
assert_matches!(task.variant, Some(act_task::Variant::Start(_)));
|
|
832
|
+
// heartbeat 1 (will send immediately)
|
|
833
|
+
core.record_activity_heartbeat(ActivityHeartbeat {
|
|
834
|
+
task_token: task.task_token.clone(),
|
|
835
|
+
details: vec!["one".into()],
|
|
836
|
+
});
|
|
837
|
+
// heartbeat 2 (would be throttled if not flushed)
|
|
838
|
+
core.record_activity_heartbeat(ActivityHeartbeat {
|
|
839
|
+
task_token: task.task_token.clone(),
|
|
840
|
+
details: vec!["two".into()],
|
|
841
|
+
});
|
|
842
|
+
// Complete activity with fail
|
|
843
|
+
let failure = Failure::application_failure("activity failed".to_string(), false);
|
|
844
|
+
core.complete_activity_task(ActivityTaskCompletion {
|
|
845
|
+
task_token: task.task_token,
|
|
846
|
+
result: Some(ActivityExecutionResult::fail(failure)),
|
|
847
|
+
})
|
|
848
|
+
.await
|
|
849
|
+
.unwrap();
|
|
850
|
+
// The activity is still in the pending state since it has retries left
|
|
851
|
+
let client = starter.get_client().await;
|
|
852
|
+
eventually(
|
|
853
|
+
|| async {
|
|
854
|
+
// Verify pending details has the flushed heartbeat
|
|
855
|
+
let details = client
|
|
856
|
+
.describe_workflow_execution(starter.get_wf_id().to_string(), None)
|
|
857
|
+
.await
|
|
858
|
+
.unwrap();
|
|
859
|
+
let last_deets = details
|
|
860
|
+
.pending_activities
|
|
861
|
+
.into_iter()
|
|
862
|
+
.find(|i| i.activity_id == activity_id)
|
|
863
|
+
.and_then(|i| i.heartbeat_details);
|
|
864
|
+
if last_deets == ["two".into()].into_payloads() {
|
|
865
|
+
Ok(())
|
|
866
|
+
} else {
|
|
867
|
+
Err("details don't yet match")
|
|
868
|
+
}
|
|
869
|
+
},
|
|
870
|
+
Duration::from_secs(5),
|
|
871
|
+
)
|
|
872
|
+
.await
|
|
873
|
+
.unwrap();
|
|
874
|
+
client
|
|
875
|
+
.terminate_workflow_execution(task_q, None)
|
|
876
|
+
.await
|
|
877
|
+
.unwrap();
|
|
878
|
+
drain_pollers_and_shutdown(&core).await;
|
|
879
|
+
}
|
|
880
|
+
|
|
793
881
|
#[tokio::test]
|
|
794
882
|
async fn one_activity_abandon_cancelled_before_started() {
|
|
795
883
|
let wf_name = "one_activity_abandon_cancelled_before_started";
|
|
@@ -1114,3 +1202,148 @@ async fn long_activity_timeout_repro() {
|
|
|
1114
1202
|
starter.start_with_worker(wf_name, &mut worker).await;
|
|
1115
1203
|
worker.run_until_done().await.unwrap();
|
|
1116
1204
|
}
|
|
1205
|
+
|
|
1206
|
+
#[tokio::test]
|
|
1207
|
+
async fn pass_activity_summary_to_metadata() {
|
|
1208
|
+
let t = canned_histories::single_activity("1");
|
|
1209
|
+
let mut mock_cfg = MockPollCfg::from_hist_builder(t);
|
|
1210
|
+
let wf_id = mock_cfg.hists[0].wf_id.clone();
|
|
1211
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
1212
|
+
let expected_user_metadata = Some(UserMetadata {
|
|
1213
|
+
summary: Some(b"activity summary".into()),
|
|
1214
|
+
details: None,
|
|
1215
|
+
});
|
|
1216
|
+
mock_cfg.completion_asserts_from_expectations(|mut asserts| {
|
|
1217
|
+
asserts
|
|
1218
|
+
.then(move |wft| {
|
|
1219
|
+
assert_eq!(wft.commands.len(), 1);
|
|
1220
|
+
assert_eq!(
|
|
1221
|
+
wft.commands[0].command_type(),
|
|
1222
|
+
CommandType::ScheduleActivityTask
|
|
1223
|
+
);
|
|
1224
|
+
assert_eq!(wft.commands[0].user_metadata, expected_user_metadata)
|
|
1225
|
+
})
|
|
1226
|
+
.then(move |wft| {
|
|
1227
|
+
assert_eq!(wft.commands.len(), 1);
|
|
1228
|
+
assert_eq!(
|
|
1229
|
+
wft.commands[0].command_type(),
|
|
1230
|
+
CommandType::CompleteWorkflowExecution
|
|
1231
|
+
);
|
|
1232
|
+
});
|
|
1233
|
+
});
|
|
1234
|
+
|
|
1235
|
+
let mut worker = mock_sdk_cfg(mock_cfg, |_| {});
|
|
1236
|
+
worker.register_wf(wf_type, |ctx: WfContext| async move {
|
|
1237
|
+
ctx.activity(ActivityOptions {
|
|
1238
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
1239
|
+
summary: Some("activity summary".to_string()),
|
|
1240
|
+
..Default::default()
|
|
1241
|
+
})
|
|
1242
|
+
.await;
|
|
1243
|
+
Ok(().into())
|
|
1244
|
+
});
|
|
1245
|
+
worker
|
|
1246
|
+
.submit_wf(
|
|
1247
|
+
wf_id.to_owned(),
|
|
1248
|
+
wf_type.to_owned(),
|
|
1249
|
+
vec![],
|
|
1250
|
+
WorkflowOptions::default(),
|
|
1251
|
+
)
|
|
1252
|
+
.await
|
|
1253
|
+
.unwrap();
|
|
1254
|
+
worker.run_until_done().await.unwrap();
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
#[rstest(hist_batches, case::incremental(&[1, 2, 3, 4]), case::replay(&[4]))]
|
|
1258
|
+
#[tokio::test]
|
|
1259
|
+
async fn abandoned_activities_ignore_start_and_complete(hist_batches: &'static [usize]) {
|
|
1260
|
+
let wfid = "fake_wf_id";
|
|
1261
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
|
1262
|
+
let activity_id = "1";
|
|
1263
|
+
|
|
1264
|
+
let mut t = TestHistoryBuilder::default();
|
|
1265
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
1266
|
+
t.add_full_wf_task();
|
|
1267
|
+
let act_scheduled_event_id = t.add_activity_task_scheduled(activity_id);
|
|
1268
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
1269
|
+
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
1270
|
+
t.add_full_wf_task();
|
|
1271
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
1272
|
+
let act_started_event_id = t.add_activity_task_started(act_scheduled_event_id);
|
|
1273
|
+
t.add_activity_task_completed(
|
|
1274
|
+
act_scheduled_event_id,
|
|
1275
|
+
act_started_event_id,
|
|
1276
|
+
Default::default(),
|
|
1277
|
+
);
|
|
1278
|
+
t.add_full_wf_task();
|
|
1279
|
+
t.add_timer_fired(timer_started_event_id, "2".to_string());
|
|
1280
|
+
t.add_full_wf_task();
|
|
1281
|
+
t.add_workflow_execution_completed();
|
|
1282
|
+
let mock = mock_worker_client();
|
|
1283
|
+
let mut worker = mock_sdk(MockPollCfg::from_resp_batches(wfid, t, hist_batches, mock));
|
|
1284
|
+
|
|
1285
|
+
worker.register_wf(wf_type.to_owned(), |ctx: WfContext| async move {
|
|
1286
|
+
let act_fut = ctx.activity(ActivityOptions {
|
|
1287
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
1288
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
1289
|
+
cancellation_type: ActivityCancellationType::Abandon,
|
|
1290
|
+
..Default::default()
|
|
1291
|
+
});
|
|
1292
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
1293
|
+
act_fut.cancel(&ctx);
|
|
1294
|
+
ctx.timer(Duration::from_secs(3)).await;
|
|
1295
|
+
act_fut.await;
|
|
1296
|
+
Ok(().into())
|
|
1297
|
+
});
|
|
1298
|
+
worker
|
|
1299
|
+
.submit_wf(wfid, wf_type, vec![], Default::default())
|
|
1300
|
+
.await
|
|
1301
|
+
.unwrap();
|
|
1302
|
+
worker.run_until_done().await.unwrap();
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
#[tokio::test]
|
|
1306
|
+
async fn immediate_activity_cancelation() {
|
|
1307
|
+
let func = WorkflowFunction::new(|ctx: WfContext| async move {
|
|
1308
|
+
let cancel_activity_future = ctx.activity(ActivityOptions::default());
|
|
1309
|
+
// Immediately cancel the activity
|
|
1310
|
+
cancel_activity_future.cancel(&ctx);
|
|
1311
|
+
cancel_activity_future.await;
|
|
1312
|
+
Ok(().into())
|
|
1313
|
+
});
|
|
1314
|
+
|
|
1315
|
+
let mut t = TestHistoryBuilder::default();
|
|
1316
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
1317
|
+
t.add_full_wf_task();
|
|
1318
|
+
t.add_workflow_execution_completed();
|
|
1319
|
+
let mut worker = build_fake_sdk(MockPollCfg::from_resps(t, [ResponseType::AllHistory]));
|
|
1320
|
+
worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
|
|
1321
|
+
|
|
1322
|
+
let mut aai = ActivationAssertionsInterceptor::default();
|
|
1323
|
+
aai.then(|a| {
|
|
1324
|
+
assert_matches!(
|
|
1325
|
+
a.jobs.as_slice(),
|
|
1326
|
+
[WorkflowActivationJob {
|
|
1327
|
+
variant: Some(workflow_activation_job::Variant::InitializeWorkflow(_)),
|
|
1328
|
+
}]
|
|
1329
|
+
)
|
|
1330
|
+
});
|
|
1331
|
+
aai.then(|a| {
|
|
1332
|
+
assert_matches!(
|
|
1333
|
+
a.jobs.as_slice(),
|
|
1334
|
+
[WorkflowActivationJob {
|
|
1335
|
+
variant: Some(workflow_activation_job::Variant::ResolveActivity(
|
|
1336
|
+
ResolveActivity {
|
|
1337
|
+
result: Some(ActivityResolution {
|
|
1338
|
+
status: Some(act_res::Status::Cancelled(_))
|
|
1339
|
+
}),
|
|
1340
|
+
..
|
|
1341
|
+
}
|
|
1342
|
+
)),
|
|
1343
|
+
},]
|
|
1344
|
+
)
|
|
1345
|
+
});
|
|
1346
|
+
|
|
1347
|
+
worker.set_worker_interceptor(aai);
|
|
1348
|
+
worker.run().await.unwrap();
|
|
1349
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
use crate::common::CoreWfStarter;
|
|
1
2
|
use assert_matches::assert_matches;
|
|
2
3
|
use std::time::Duration;
|
|
3
4
|
use temporal_client::{WfClientExt, WorkflowExecutionResult, WorkflowOptions};
|
|
4
5
|
use temporal_sdk::{ActContext, ActivityOptions, WfContext, WorkflowResult};
|
|
5
6
|
use temporal_sdk_core_protos::coresdk::AsJsonPayloadExt;
|
|
6
|
-
use temporal_sdk_core_test_utils::CoreWfStarter;
|
|
7
7
|
|
|
8
8
|
const TEST_APPDATA_MESSAGE: &str = "custom app data, yay";
|
|
9
9
|
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
use crate::common::{CoreWfStarter, build_fake_sdk};
|
|
1
2
|
use temporal_client::{GetWorkflowResultOpts, WfClientExt, WorkflowOptions};
|
|
2
3
|
use temporal_sdk::{WfContext, WorkflowResult};
|
|
3
|
-
use
|
|
4
|
-
use
|
|
4
|
+
use temporal_sdk_core::test_help::MockPollCfg;
|
|
5
|
+
use temporal_sdk_core_protos::{
|
|
6
|
+
DEFAULT_WORKFLOW_TYPE, TestHistoryBuilder,
|
|
7
|
+
coresdk::{FromJsonPayloadExt, common::NamespacedWorkflowExecution},
|
|
8
|
+
temporal::api::enums::v1::{CommandType, EventType},
|
|
9
|
+
};
|
|
5
10
|
|
|
6
11
|
const RECEIVER_WFID: &str = "sends-cancel-receiver";
|
|
7
12
|
|
|
@@ -72,3 +77,74 @@ async fn sends_cancel_to_other_wf() {
|
|
|
72
77
|
assert!(res.contains("Cancel requested by workflow"));
|
|
73
78
|
assert!(res.contains("cancel-reason"));
|
|
74
79
|
}
|
|
80
|
+
|
|
81
|
+
async fn cancel_sender_canned(ctx: WfContext) -> WorkflowResult<()> {
|
|
82
|
+
let res = ctx
|
|
83
|
+
.cancel_external(
|
|
84
|
+
NamespacedWorkflowExecution {
|
|
85
|
+
namespace: "some_namespace".to_string(),
|
|
86
|
+
workflow_id: "fake_wid".to_string(),
|
|
87
|
+
run_id: "fake_rid".to_string(),
|
|
88
|
+
},
|
|
89
|
+
"cancel reason".to_string(),
|
|
90
|
+
)
|
|
91
|
+
.await;
|
|
92
|
+
if res.is_err() {
|
|
93
|
+
Err(anyhow::anyhow!("Cancel fail!"))
|
|
94
|
+
} else {
|
|
95
|
+
Ok(().into())
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#[rstest::rstest]
|
|
100
|
+
#[case::succeeds(false)]
|
|
101
|
+
#[case::fails(true)]
|
|
102
|
+
#[tokio::test]
|
|
103
|
+
async fn sends_cancel_canned(#[case] fails: bool) {
|
|
104
|
+
let mut t = TestHistoryBuilder::default();
|
|
105
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
106
|
+
t.add_full_wf_task();
|
|
107
|
+
let id = t.add_cancel_external_wf(NamespacedWorkflowExecution {
|
|
108
|
+
namespace: "some_namespace".to_string(),
|
|
109
|
+
workflow_id: "fake_wid".to_string(),
|
|
110
|
+
run_id: "fake_rid".to_string(),
|
|
111
|
+
});
|
|
112
|
+
if fails {
|
|
113
|
+
t.add_cancel_external_wf_failed(id);
|
|
114
|
+
} else {
|
|
115
|
+
t.add_cancel_external_wf_completed(id);
|
|
116
|
+
}
|
|
117
|
+
t.add_full_wf_task();
|
|
118
|
+
if fails {
|
|
119
|
+
t.add_workflow_execution_failed();
|
|
120
|
+
} else {
|
|
121
|
+
t.add_workflow_execution_completed();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let mut mock_cfg = MockPollCfg::from_hist_builder(t);
|
|
125
|
+
mock_cfg.completion_asserts_from_expectations(|mut asserts| {
|
|
126
|
+
asserts
|
|
127
|
+
.then(|wft| {
|
|
128
|
+
assert_matches!(
|
|
129
|
+
wft.commands[0].command_type(),
|
|
130
|
+
CommandType::RequestCancelExternalWorkflowExecution
|
|
131
|
+
);
|
|
132
|
+
})
|
|
133
|
+
.then(move |wft| {
|
|
134
|
+
if fails {
|
|
135
|
+
assert_eq!(
|
|
136
|
+
wft.commands[0].command_type(),
|
|
137
|
+
CommandType::FailWorkflowExecution
|
|
138
|
+
);
|
|
139
|
+
} else {
|
|
140
|
+
assert_eq!(
|
|
141
|
+
wft.commands[0].command_type(),
|
|
142
|
+
CommandType::CompleteWorkflowExecution
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
let mut worker = build_fake_sdk(mock_cfg);
|
|
148
|
+
worker.register_wf(DEFAULT_WORKFLOW_TYPE, cancel_sender_canned);
|
|
149
|
+
worker.run().await.unwrap();
|
|
150
|
+
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
use crate::common::{ActivationAssertionsInterceptor, CoreWfStarter, build_fake_sdk};
|
|
1
2
|
use std::time::Duration;
|
|
2
3
|
use temporal_client::WorkflowClientTrait;
|
|
3
4
|
use temporal_sdk::{WfContext, WfExitValue, WorkflowResult};
|
|
4
|
-
use
|
|
5
|
-
use
|
|
5
|
+
use temporal_sdk_core::test_help::MockPollCfg;
|
|
6
|
+
use temporal_sdk_core_protos::{
|
|
7
|
+
DEFAULT_WORKFLOW_TYPE, canned_histories,
|
|
8
|
+
coresdk::workflow_activation::{WorkflowActivationJob, workflow_activation_job},
|
|
9
|
+
temporal::api::enums::v1::{CommandType, WorkflowExecutionStatus},
|
|
10
|
+
};
|
|
6
11
|
|
|
7
12
|
async fn cancelled_wf(ctx: WfContext) -> WorkflowResult<()> {
|
|
8
13
|
let mut reason = "".to_string();
|
|
@@ -55,3 +60,57 @@ async fn cancel_during_timer() {
|
|
|
55
60
|
WorkflowExecutionStatus::Canceled as i32
|
|
56
61
|
);
|
|
57
62
|
}
|
|
63
|
+
|
|
64
|
+
async fn wf_with_timer(ctx: WfContext) -> WorkflowResult<()> {
|
|
65
|
+
ctx.timer(Duration::from_millis(500)).await;
|
|
66
|
+
Ok(WfExitValue::Cancelled)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#[tokio::test]
|
|
70
|
+
async fn wf_completing_with_cancelled() {
|
|
71
|
+
let t = canned_histories::timer_wf_cancel_req_cancelled("1");
|
|
72
|
+
|
|
73
|
+
let mut aai = ActivationAssertionsInterceptor::default();
|
|
74
|
+
aai.then(|a| {
|
|
75
|
+
assert_matches!(
|
|
76
|
+
a.jobs.as_slice(),
|
|
77
|
+
[WorkflowActivationJob {
|
|
78
|
+
variant: Some(workflow_activation_job::Variant::InitializeWorkflow(_)),
|
|
79
|
+
}]
|
|
80
|
+
)
|
|
81
|
+
});
|
|
82
|
+
aai.then(|a| {
|
|
83
|
+
assert_matches!(
|
|
84
|
+
a.jobs.as_slice(),
|
|
85
|
+
[
|
|
86
|
+
WorkflowActivationJob {
|
|
87
|
+
variant: Some(workflow_activation_job::Variant::FireTimer(_)),
|
|
88
|
+
},
|
|
89
|
+
WorkflowActivationJob {
|
|
90
|
+
variant: Some(workflow_activation_job::Variant::CancelWorkflow(_)),
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
let mut mock_cfg = MockPollCfg::from_hist_builder(t);
|
|
97
|
+
mock_cfg.completion_asserts_from_expectations(|mut asserts| {
|
|
98
|
+
asserts
|
|
99
|
+
.then(|wft| {
|
|
100
|
+
assert_eq!(wft.commands.len(), 1);
|
|
101
|
+
assert_matches!(wft.commands[0].command_type(), CommandType::StartTimer);
|
|
102
|
+
})
|
|
103
|
+
.then(move |wft| {
|
|
104
|
+
assert_eq!(wft.commands.len(), 1);
|
|
105
|
+
assert_matches!(
|
|
106
|
+
wft.commands[0].command_type(),
|
|
107
|
+
CommandType::CancelWorkflowExecution
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
let mut worker = build_fake_sdk(mock_cfg);
|
|
113
|
+
worker.register_wf(DEFAULT_WORKFLOW_TYPE, wf_with_timer);
|
|
114
|
+
worker.set_worker_interceptor(aai);
|
|
115
|
+
worker.run().await.unwrap();
|
|
116
|
+
}
|