@temporalio/core-bridge 1.14.2-canary-release-testing.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +794 -650
- package/bridge-macros/src/derive_tryintojs.rs +40 -0
- package/lib/native.d.ts +24 -3
- package/package.json +4 -4
- 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 +42 -31
- package/sdk-core/Cargo.toml +4 -1
- package/sdk-core/README.md +19 -13
- 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} +370 -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} +104 -29
- package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
- package/sdk-core/crates/common/Cargo.toml +62 -3
- 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/.github/workflows/create-release.yml +0 -5
- package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
- package/sdk-core/crates/common/protos/api_upstream/README.md +8 -0
- 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 +3329 -2647
- package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +2734 -708
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/activity/v1/message.proto +155 -3
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/common/v1/message.proto +8 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +27 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/activity.proto +81 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/event_type.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +15 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +63 -15
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/errordetails/v1/message.proto +8 -0
- 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 +111 -17
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +21 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +20 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/worker/v1/message.proto +4 -7
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflow/v1/message.proto +80 -22
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +347 -23
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +242 -43
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/core_interface.proto +15 -0
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +9 -2
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +8 -0
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +22 -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 +19 -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 +134 -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 +11 -16
- package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
- package/sdk-core/crates/common/src/telemetry/metrics.rs +272 -225
- 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 +278 -19
- package/sdk-core/crates/common/src/worker.rs +68 -636
- 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 +759 -442
- package/sdk-core/crates/sdk/src/workflow_context/options.rs +64 -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 +59 -65
- package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +45 -54
- 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 +22 -21
- 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 +647 -27
- package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +46 -41
- package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +13 -16
- package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
- package/sdk-core/crates/sdk-core/src/lib.rs +60 -123
- package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
- package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +411 -32
- 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 +183 -198
- package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -281
- package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +35 -16
- package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
- package/sdk-core/crates/sdk-core/src/worker/activities/activity_heartbeat_manager.rs +1 -0
- 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 +11 -5
- package/sdk-core/crates/sdk-core/src/worker/client.rs +104 -86
- package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +10 -14
- package/sdk-core/crates/sdk-core/src/worker/mod.rs +1175 -241
- package/sdk-core/crates/sdk-core/src/worker/nexus.rs +150 -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 +25 -27
- package/sdk-core/crates/sdk-core/src/worker/tuner.rs +64 -44
- package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/patch_state_machine.rs +5 -8
- 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 +28 -4
- package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +20 -41
- package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +50 -9
- 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 +281 -236
- package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
- package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +9 -14
- package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -66
- package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +306 -268
- 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 +37 -38
- package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +49 -40
- package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +447 -300
- 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 +157 -157
- 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 -463
- 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 +389 -265
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +250 -185
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -49
- 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 +437 -327
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -58
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -30
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -251
- 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 +110 -46
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -149
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -32
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1040
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -43
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +402 -245
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +343 -207
- 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 +155 -140
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -113
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -44
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -48
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -56
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +365 -242
- package/sdk-core/crates/sdk-core/tests/main.rs +22 -16
- package/sdk-core/crates/sdk-core/tests/manual_tests.rs +233 -187
- package/sdk-core/crates/sdk-core/tests/runner.rs +4 -6
- package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +73 -27
- 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 +8 -1
- package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +37 -26
- package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +180 -87
- package/sdk-core/crates/sdk-core-c-bridge/src/lib.rs +89 -5
- package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +10 -16
- package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +59 -67
- package/sdk-core/crates/sdk-core-c-bridge/src/testing.rs +10 -10
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +57 -22
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +108 -12
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +9 -52
- package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +74 -91
- package/sdk-core/rustfmt.toml +2 -1
- package/src/client.rs +206 -289
- package/src/helpers/try_into_js.rs +88 -2
- package/src/metrics.rs +277 -35
- package/src/runtime.rs +94 -45
- package/src/testing.rs +9 -16
- package/src/worker.rs +86 -68
- package/ts/native.ts +39 -3
- 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/macros/LICENSE.txt +0 -21
- 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
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
use crate::common::{CoreWfStarter, get_integ_connection, integ_namespace};
|
|
2
|
+
use futures::{FutureExt, future::BoxFuture};
|
|
3
|
+
use std::{
|
|
4
|
+
sync::{
|
|
5
|
+
Arc,
|
|
6
|
+
atomic::{AtomicUsize, Ordering},
|
|
7
|
+
},
|
|
8
|
+
time::Duration,
|
|
9
|
+
};
|
|
10
|
+
use temporalio_client::{Client, ClientOptions, UntypedWorkflow, WorkflowStartOptions};
|
|
11
|
+
use temporalio_common::{
|
|
12
|
+
data_converters::{
|
|
13
|
+
DataConverter, DefaultFailureConverter, MultiArgs2, PayloadCodec, PayloadConversionError,
|
|
14
|
+
PayloadConverter, SerializationContext, SerializationContextData, TemporalDeserializable,
|
|
15
|
+
TemporalSerializable,
|
|
16
|
+
},
|
|
17
|
+
protos::temporal::api::{common::v1::Payload, history::v1::history_event::Attributes},
|
|
18
|
+
worker::WorkerTaskTypes,
|
|
19
|
+
};
|
|
20
|
+
use temporalio_macros::{activities, workflow, workflow_methods};
|
|
21
|
+
use temporalio_sdk::{
|
|
22
|
+
ActivityOptions, WorkflowContext, WorkflowResult,
|
|
23
|
+
activities::{ActivityContext, ActivityError},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
#[derive(Clone, Debug)]
|
|
27
|
+
struct TrackedWrapper(TrackedValue);
|
|
28
|
+
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
|
29
|
+
struct TrackedValue {
|
|
30
|
+
data: String,
|
|
31
|
+
serialize_count: u32,
|
|
32
|
+
deserialize_count: u32,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
impl TrackedValue {
|
|
36
|
+
fn new(data: String) -> Self {
|
|
37
|
+
Self {
|
|
38
|
+
data,
|
|
39
|
+
serialize_count: 0,
|
|
40
|
+
deserialize_count: 0,
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
impl TemporalSerializable for TrackedWrapper {
|
|
46
|
+
fn to_payload(&self, _: &SerializationContext<'_>) -> Result<Payload, PayloadConversionError> {
|
|
47
|
+
let mut wire = self.0.clone();
|
|
48
|
+
wire.serialize_count += 1;
|
|
49
|
+
let json = serde_json::to_vec(&wire)
|
|
50
|
+
.map_err(|e| PayloadConversionError::EncodingError(Box::new(e)))?;
|
|
51
|
+
Ok(Payload {
|
|
52
|
+
metadata: {
|
|
53
|
+
let mut hm = std::collections::HashMap::new();
|
|
54
|
+
hm.insert("encoding".to_string(), b"json/plain".to_vec());
|
|
55
|
+
hm
|
|
56
|
+
},
|
|
57
|
+
data: json,
|
|
58
|
+
external_payloads: vec![],
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
impl TemporalDeserializable for TrackedWrapper {
|
|
64
|
+
fn from_payload(
|
|
65
|
+
_: &SerializationContext<'_>,
|
|
66
|
+
payload: Payload,
|
|
67
|
+
) -> Result<Self, PayloadConversionError> {
|
|
68
|
+
let wire: TrackedValue = serde_json::from_slice(&payload.data)
|
|
69
|
+
.map_err(|e| PayloadConversionError::EncodingError(Box::new(e)))?;
|
|
70
|
+
let mut val = wire.clone();
|
|
71
|
+
val.deserialize_count += 1;
|
|
72
|
+
Ok(TrackedWrapper(val))
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
struct TestActivities;
|
|
77
|
+
#[activities]
|
|
78
|
+
impl TestActivities {
|
|
79
|
+
#[activity]
|
|
80
|
+
async fn process_tracked(
|
|
81
|
+
_ctx: ActivityContext,
|
|
82
|
+
mut input: TrackedWrapper,
|
|
83
|
+
) -> Result<TrackedWrapper, ActivityError> {
|
|
84
|
+
input.0.data = format!("activity-processed:{}", input.0.data);
|
|
85
|
+
Ok(input)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
#[workflow]
|
|
90
|
+
#[derive(Default)]
|
|
91
|
+
struct DataConverterTestWorkflow;
|
|
92
|
+
#[workflow_methods]
|
|
93
|
+
impl DataConverterTestWorkflow {
|
|
94
|
+
#[run]
|
|
95
|
+
async fn run(
|
|
96
|
+
ctx: &mut WorkflowContext<Self>,
|
|
97
|
+
input: TrackedWrapper,
|
|
98
|
+
) -> WorkflowResult<TrackedWrapper> {
|
|
99
|
+
let output = ctx
|
|
100
|
+
.start_activity(
|
|
101
|
+
TestActivities::process_tracked,
|
|
102
|
+
input,
|
|
103
|
+
ActivityOptions {
|
|
104
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
105
|
+
..Default::default()
|
|
106
|
+
},
|
|
107
|
+
)
|
|
108
|
+
.await
|
|
109
|
+
.map_err(|e| anyhow::anyhow!("{e}"))?;
|
|
110
|
+
|
|
111
|
+
Ok(output)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
#[tokio::test]
|
|
116
|
+
async fn data_converter_tracks_serialization_points() {
|
|
117
|
+
let wf_name = DataConverterTestWorkflow::name();
|
|
118
|
+
let mut starter = CoreWfStarter::new(wf_name);
|
|
119
|
+
starter.sdk_config.register_activities(TestActivities);
|
|
120
|
+
starter
|
|
121
|
+
.sdk_config
|
|
122
|
+
.register_workflow::<DataConverterTestWorkflow>();
|
|
123
|
+
let mut worker = starter.worker().await;
|
|
124
|
+
|
|
125
|
+
let input = TrackedValue::new("test-input".to_string());
|
|
126
|
+
assert_eq!(input.serialize_count, 0);
|
|
127
|
+
assert_eq!(input.deserialize_count, 0);
|
|
128
|
+
|
|
129
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
130
|
+
let handle = worker
|
|
131
|
+
.submit_workflow(
|
|
132
|
+
DataConverterTestWorkflow::run,
|
|
133
|
+
TrackedWrapper(input),
|
|
134
|
+
WorkflowStartOptions::new(task_queue, wf_name.to_owned()).build(),
|
|
135
|
+
)
|
|
136
|
+
.await
|
|
137
|
+
.unwrap();
|
|
138
|
+
worker.run_until_done().await.unwrap();
|
|
139
|
+
|
|
140
|
+
let output = handle.get_result(Default::default()).await.unwrap().0;
|
|
141
|
+
|
|
142
|
+
assert!(
|
|
143
|
+
output.data.contains("activity-processed:test-input"),
|
|
144
|
+
"Activity should have processed the input, got: {}",
|
|
145
|
+
output.data
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// Expected path:
|
|
149
|
+
// 1. Client serializes input (serialize_count: 0 -> 1)
|
|
150
|
+
// 2. Workflow deserializes input (deserialize_count: 0 -> 1)
|
|
151
|
+
// 3. Workflow serializes for activity call (serialize_count: 1 -> 2)
|
|
152
|
+
// 4. Activity deserializes input (deserialize_count: 1 -> 2)
|
|
153
|
+
// 5. Activity serializes result (serialize_count: 2 -> 3)
|
|
154
|
+
// 6. Workflow deserializes activity result (deserialize_count: 2 -> 3)
|
|
155
|
+
// 7. Workflow serializes final result (serialize_count: 3 -> 4)
|
|
156
|
+
// 8. Client deserializes result (deserialize_count: 3 -> 4)
|
|
157
|
+
|
|
158
|
+
assert!(
|
|
159
|
+
output.serialize_count == 4,
|
|
160
|
+
"Value should have been serialized 4 times, was serialized {} times",
|
|
161
|
+
output.serialize_count
|
|
162
|
+
);
|
|
163
|
+
assert!(
|
|
164
|
+
output.deserialize_count == 4,
|
|
165
|
+
"Value should have been deserialized 4 times, was deserialized {} times",
|
|
166
|
+
output.deserialize_count
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#[workflow]
|
|
171
|
+
#[derive(Default)]
|
|
172
|
+
struct MultiArgs2Workflow;
|
|
173
|
+
#[workflow_methods]
|
|
174
|
+
impl MultiArgs2Workflow {
|
|
175
|
+
#[run]
|
|
176
|
+
async fn run(
|
|
177
|
+
_ctx: &mut WorkflowContext<Self>,
|
|
178
|
+
input: MultiArgs2<String, i32>,
|
|
179
|
+
) -> WorkflowResult<String> {
|
|
180
|
+
Ok(format!("received: {} and {}", input.0, input.1))
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
#[tokio::test]
|
|
185
|
+
async fn multi_args_serializes_as_multiple_payloads() {
|
|
186
|
+
let wf_name = MultiArgs2Workflow::name();
|
|
187
|
+
let mut starter = CoreWfStarter::new(wf_name);
|
|
188
|
+
starter.sdk_config.register_workflow::<MultiArgs2Workflow>();
|
|
189
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
190
|
+
let mut worker = starter.worker().await;
|
|
191
|
+
|
|
192
|
+
let input = MultiArgs2("hello".to_string(), 42);
|
|
193
|
+
|
|
194
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
195
|
+
let handle = worker
|
|
196
|
+
.submit_workflow(
|
|
197
|
+
MultiArgs2Workflow::run,
|
|
198
|
+
input,
|
|
199
|
+
WorkflowStartOptions::new(task_queue, wf_name.to_owned()).build(),
|
|
200
|
+
)
|
|
201
|
+
.await
|
|
202
|
+
.unwrap();
|
|
203
|
+
worker.run_until_done().await.unwrap();
|
|
204
|
+
|
|
205
|
+
let output = handle.get_result(Default::default()).await.unwrap();
|
|
206
|
+
assert_eq!(output, "received: hello and 42");
|
|
207
|
+
|
|
208
|
+
// Verify the workflow history contains multiple payloads in the input
|
|
209
|
+
let client = starter.get_client().await;
|
|
210
|
+
let events = client
|
|
211
|
+
.get_workflow_handle::<UntypedWorkflow>(wf_name)
|
|
212
|
+
.fetch_history(Default::default())
|
|
213
|
+
.await
|
|
214
|
+
.unwrap()
|
|
215
|
+
.into_events();
|
|
216
|
+
|
|
217
|
+
let workflow_started_event = events
|
|
218
|
+
.iter()
|
|
219
|
+
.find_map(|e| {
|
|
220
|
+
if let Attributes::WorkflowExecutionStartedEventAttributes(attrs) =
|
|
221
|
+
e.attributes.as_ref().unwrap()
|
|
222
|
+
{
|
|
223
|
+
Some(attrs)
|
|
224
|
+
} else {
|
|
225
|
+
None
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
.expect("Should find WorkflowExecutionStarted event");
|
|
229
|
+
|
|
230
|
+
let input_payloads = workflow_started_event
|
|
231
|
+
.input
|
|
232
|
+
.as_ref()
|
|
233
|
+
.expect("Should have input payloads");
|
|
234
|
+
|
|
235
|
+
assert_eq!(
|
|
236
|
+
input_payloads.payloads.len(),
|
|
237
|
+
2,
|
|
238
|
+
"MultiArgs2<A, B> should produce 2 payloads, got {}",
|
|
239
|
+
input_payloads.payloads.len()
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
// Verify the content of each payload
|
|
243
|
+
let first_payload_data: String =
|
|
244
|
+
serde_json::from_slice(&input_payloads.payloads[0].data).unwrap();
|
|
245
|
+
assert_eq!(first_payload_data, "hello");
|
|
246
|
+
|
|
247
|
+
let second_payload_data: i32 =
|
|
248
|
+
serde_json::from_slice(&input_payloads.payloads[1].data).unwrap();
|
|
249
|
+
assert_eq!(second_payload_data, 42);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/// A codec that XORs payload data with a key and tracks encode/decode operations.
|
|
253
|
+
struct XorCodec {
|
|
254
|
+
key: u8,
|
|
255
|
+
encode_count: AtomicUsize,
|
|
256
|
+
decode_count: AtomicUsize,
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
impl XorCodec {
|
|
260
|
+
fn new(key: u8) -> Self {
|
|
261
|
+
Self {
|
|
262
|
+
key,
|
|
263
|
+
encode_count: AtomicUsize::new(0),
|
|
264
|
+
decode_count: AtomicUsize::new(0),
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
fn encode_count(&self) -> usize {
|
|
269
|
+
self.encode_count.load(Ordering::SeqCst)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
fn decode_count(&self) -> usize {
|
|
273
|
+
self.decode_count.load(Ordering::SeqCst)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
impl PayloadCodec for XorCodec {
|
|
278
|
+
fn encode(
|
|
279
|
+
&self,
|
|
280
|
+
_context: &SerializationContextData,
|
|
281
|
+
payloads: Vec<Payload>,
|
|
282
|
+
) -> BoxFuture<'static, Vec<Payload>> {
|
|
283
|
+
let count = payloads.len();
|
|
284
|
+
eprintln!("XorCodec::encode called with {} payloads", count);
|
|
285
|
+
self.encode_count.fetch_add(count, Ordering::SeqCst);
|
|
286
|
+
let key = self.key;
|
|
287
|
+
async move {
|
|
288
|
+
payloads
|
|
289
|
+
.into_iter()
|
|
290
|
+
.map(|mut p| {
|
|
291
|
+
p.data = p.data.iter().map(|b| b ^ key).collect();
|
|
292
|
+
p.metadata.insert("xor_encoded".to_string(), vec![key]);
|
|
293
|
+
p
|
|
294
|
+
})
|
|
295
|
+
.collect()
|
|
296
|
+
}
|
|
297
|
+
.boxed()
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
fn decode(
|
|
301
|
+
&self,
|
|
302
|
+
_context: &SerializationContextData,
|
|
303
|
+
payloads: Vec<Payload>,
|
|
304
|
+
) -> BoxFuture<'static, Vec<Payload>> {
|
|
305
|
+
let count = payloads.len();
|
|
306
|
+
eprintln!("XorCodec::decode called with {} payloads", count);
|
|
307
|
+
self.decode_count.fetch_add(count, Ordering::SeqCst);
|
|
308
|
+
let key = self.key;
|
|
309
|
+
async move {
|
|
310
|
+
payloads
|
|
311
|
+
.into_iter()
|
|
312
|
+
.map(|mut p| {
|
|
313
|
+
if p.metadata.remove("xor_encoded").is_some() {
|
|
314
|
+
p.data = p.data.iter().map(|b| b ^ key).collect();
|
|
315
|
+
}
|
|
316
|
+
p
|
|
317
|
+
})
|
|
318
|
+
.collect()
|
|
319
|
+
}
|
|
320
|
+
.boxed()
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
#[tokio::test]
|
|
325
|
+
async fn codec_encodes_and_decodes_payloads() {
|
|
326
|
+
let wf_name = DataConverterTestWorkflow::name();
|
|
327
|
+
let codec = Arc::new(XorCodec::new(0x42));
|
|
328
|
+
|
|
329
|
+
// Create a client with our custom codec
|
|
330
|
+
let connection = get_integ_connection(None).await;
|
|
331
|
+
let data_converter = DataConverter::new(
|
|
332
|
+
PayloadConverter::default(),
|
|
333
|
+
DefaultFailureConverter,
|
|
334
|
+
codec.clone(),
|
|
335
|
+
);
|
|
336
|
+
let client_opts = ClientOptions::new(integ_namespace())
|
|
337
|
+
.data_converter(data_converter)
|
|
338
|
+
.build();
|
|
339
|
+
let client = Client::new(connection, client_opts).unwrap();
|
|
340
|
+
|
|
341
|
+
let mut starter = CoreWfStarter::new_with_overrides(wf_name, None, Some(client));
|
|
342
|
+
starter.sdk_config.register_activities(TestActivities);
|
|
343
|
+
starter.sdk_config.task_types = WorkerTaskTypes::all();
|
|
344
|
+
starter
|
|
345
|
+
.sdk_config
|
|
346
|
+
.register_workflow::<DataConverterTestWorkflow>();
|
|
347
|
+
// Use task queue name as workflow ID to avoid collisions with parallel tests
|
|
348
|
+
let wf_id = starter.get_task_queue().to_owned();
|
|
349
|
+
let mut worker = starter.worker().await;
|
|
350
|
+
|
|
351
|
+
let input = TrackedValue::new("codec-test".to_string());
|
|
352
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
353
|
+
let handle = worker
|
|
354
|
+
.submit_workflow(
|
|
355
|
+
DataConverterTestWorkflow::run,
|
|
356
|
+
TrackedWrapper(input),
|
|
357
|
+
WorkflowStartOptions::new(task_queue, wf_id).build(),
|
|
358
|
+
)
|
|
359
|
+
.await
|
|
360
|
+
.unwrap();
|
|
361
|
+
worker.run_until_done().await.unwrap();
|
|
362
|
+
|
|
363
|
+
let output = handle.get_result(Default::default()).await.unwrap().0;
|
|
364
|
+
|
|
365
|
+
// Verify the workflow processed correctly (activity echoed the data)
|
|
366
|
+
assert!(
|
|
367
|
+
output.data.contains("activity-processed:codec-test"),
|
|
368
|
+
"Activity should have processed the input, got: {}",
|
|
369
|
+
output.data
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
// Verify the codec was used for both encoding and decoding
|
|
373
|
+
assert!(
|
|
374
|
+
codec.encode_count() > 0,
|
|
375
|
+
"Codec should have encoded payloads, but encode_count was 0"
|
|
376
|
+
);
|
|
377
|
+
assert!(
|
|
378
|
+
codec.decode_count() > 0,
|
|
379
|
+
"Codec should have decoded payloads, but decode_count was 0"
|
|
380
|
+
);
|
|
381
|
+
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
use crate::common::{INTEG_CLIENT_IDENTITY, INTEG_CLIENT_NAME, INTEG_CLIENT_VERSION, NAMESPACE};
|
|
2
2
|
use futures_util::{TryStreamExt, stream};
|
|
3
3
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
4
|
-
use temporalio_client::{
|
|
4
|
+
use temporalio_client::{
|
|
5
|
+
Connection, ConnectionOptions,
|
|
6
|
+
grpc::{TestService, WorkflowService},
|
|
7
|
+
};
|
|
5
8
|
use temporalio_common::protos::temporal::api::workflowservice::v1::DescribeNamespaceRequest;
|
|
6
9
|
use temporalio_sdk_core::ephemeral_server::{
|
|
7
|
-
EphemeralExe, EphemeralExeVersion, EphemeralServer,
|
|
10
|
+
EphemeralExe, EphemeralExeVersion, EphemeralServer, TemporalDevServerConfig,
|
|
8
11
|
default_cached_download,
|
|
9
12
|
};
|
|
10
13
|
use tonic::IntoRequest;
|
|
@@ -12,10 +15,9 @@ use url::Url;
|
|
|
12
15
|
|
|
13
16
|
#[tokio::test]
|
|
14
17
|
async fn temporal_cli_default() {
|
|
15
|
-
let config =
|
|
18
|
+
let config = TemporalDevServerConfig::builder()
|
|
16
19
|
.exe(default_cached_download())
|
|
17
|
-
.build()
|
|
18
|
-
.unwrap();
|
|
20
|
+
.build();
|
|
19
21
|
let mut server = config.start_server().await.unwrap();
|
|
20
22
|
assert_ephemeral_server(&server).await;
|
|
21
23
|
|
|
@@ -28,10 +30,9 @@ async fn temporal_cli_default() {
|
|
|
28
30
|
|
|
29
31
|
#[tokio::test]
|
|
30
32
|
async fn temporal_cli_fixed() {
|
|
31
|
-
let config =
|
|
33
|
+
let config = TemporalDevServerConfig::builder()
|
|
32
34
|
.exe(fixed_cached_download("v1.2.0"))
|
|
33
|
-
.build()
|
|
34
|
-
.unwrap();
|
|
35
|
+
.build();
|
|
35
36
|
let mut server = config.start_server().await.unwrap();
|
|
36
37
|
assert_ephemeral_server(&server).await;
|
|
37
38
|
server.shutdown().await.unwrap();
|
|
@@ -41,11 +42,10 @@ async fn temporal_cli_fixed() {
|
|
|
41
42
|
async fn temporal_cli_shutdown_port_reuse() {
|
|
42
43
|
// Start, test shutdown, do again immediately on same port to ensure we can
|
|
43
44
|
// reuse after shutdown
|
|
44
|
-
let config =
|
|
45
|
+
let config = TemporalDevServerConfig::builder()
|
|
45
46
|
.exe(default_cached_download())
|
|
46
|
-
.port(
|
|
47
|
-
.build()
|
|
48
|
-
.unwrap();
|
|
47
|
+
.port(10123)
|
|
48
|
+
.build();
|
|
49
49
|
let mut server = config.start_server().await.unwrap();
|
|
50
50
|
assert_ephemeral_server(&server).await;
|
|
51
51
|
server.shutdown().await.unwrap();
|
|
@@ -66,10 +66,11 @@ async fn temporal_cli_shutdown_port_reuse() {
|
|
|
66
66
|
#[ignore]
|
|
67
67
|
async fn temporal_cli_concurrent_starts() -> Result<(), Box<dyn std::error::Error>> {
|
|
68
68
|
stream::iter((0..80).map(|_| {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
Ok::<TemporalDevServerConfig, Box<dyn std::error::Error>>(
|
|
70
|
+
TemporalDevServerConfig::builder()
|
|
71
|
+
.exe(default_cached_download())
|
|
72
|
+
.build(),
|
|
73
|
+
)
|
|
73
74
|
}))
|
|
74
75
|
.try_for_each_concurrent(8, |config| async move {
|
|
75
76
|
let mut server = config.start_server().await?;
|
|
@@ -85,14 +86,13 @@ async fn temporal_cli_concurrent_starts() -> Result<(), Box<dyn std::error::Erro
|
|
|
85
86
|
#[cfg(not(all(target_os = "linux", any(target_arch = "arm", target_arch = "aarch64"))))]
|
|
86
87
|
mod test_server {
|
|
87
88
|
use super::*;
|
|
88
|
-
use temporalio_sdk_core::ephemeral_server::
|
|
89
|
+
use temporalio_sdk_core::ephemeral_server::TestServerConfig;
|
|
89
90
|
|
|
90
91
|
#[tokio::test]
|
|
91
92
|
async fn test_server_default() {
|
|
92
|
-
let config =
|
|
93
|
+
let config = TestServerConfig::builder()
|
|
93
94
|
.exe(default_cached_download())
|
|
94
|
-
.build()
|
|
95
|
-
.unwrap();
|
|
95
|
+
.build();
|
|
96
96
|
let mut server = config.start_server().await.unwrap();
|
|
97
97
|
assert_ephemeral_server(&server).await;
|
|
98
98
|
server.shutdown().await.unwrap();
|
|
@@ -100,10 +100,9 @@ mod test_server {
|
|
|
100
100
|
|
|
101
101
|
#[tokio::test]
|
|
102
102
|
async fn test_server_fixed() {
|
|
103
|
-
let config =
|
|
103
|
+
let config = TestServerConfig::builder()
|
|
104
104
|
.exe(fixed_cached_download("v1.16.0"))
|
|
105
|
-
.build()
|
|
106
|
-
.unwrap();
|
|
105
|
+
.build();
|
|
107
106
|
let mut server = config.start_server().await.unwrap();
|
|
108
107
|
assert_ephemeral_server(&server).await;
|
|
109
108
|
server.shutdown().await.unwrap();
|
|
@@ -113,11 +112,10 @@ mod test_server {
|
|
|
113
112
|
async fn test_server_shutdown_port_reuse() {
|
|
114
113
|
// Start, test shutdown, do again immediately on same port to ensure we can
|
|
115
114
|
// reuse after shutdown
|
|
116
|
-
let config =
|
|
115
|
+
let config = TestServerConfig::builder()
|
|
117
116
|
.exe(default_cached_download())
|
|
118
|
-
.port(
|
|
119
|
-
.build()
|
|
120
|
-
.unwrap();
|
|
117
|
+
.port(10124)
|
|
118
|
+
.build();
|
|
121
119
|
let mut server = config.start_server().await.unwrap();
|
|
122
120
|
assert_ephemeral_server(&server).await;
|
|
123
121
|
server.shutdown().await.unwrap();
|
|
@@ -137,16 +135,14 @@ fn fixed_cached_download(version: &str) -> EphemeralExe {
|
|
|
137
135
|
|
|
138
136
|
async fn assert_ephemeral_server(server: &EphemeralServer) {
|
|
139
137
|
// Connect and describe namespace
|
|
140
|
-
let
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
.unwrap();
|
|
149
|
-
let resp = client
|
|
138
|
+
let connection_opts =
|
|
139
|
+
ConnectionOptions::new(Url::try_from(&*format!("http://{}", server.target)).unwrap())
|
|
140
|
+
.identity(INTEG_CLIENT_IDENTITY.to_string())
|
|
141
|
+
.client_name(INTEG_CLIENT_NAME.to_string())
|
|
142
|
+
.client_version(INTEG_CLIENT_VERSION.to_string())
|
|
143
|
+
.build();
|
|
144
|
+
let mut connection = Connection::connect(connection_opts).await.unwrap();
|
|
145
|
+
let resp = connection
|
|
150
146
|
.describe_namespace(
|
|
151
147
|
DescribeNamespaceRequest {
|
|
152
148
|
namespace: NAMESPACE.to_string(),
|
|
@@ -160,7 +156,10 @@ async fn assert_ephemeral_server(server: &EphemeralServer) {
|
|
|
160
156
|
|
|
161
157
|
// If it has test service, make sure we can use it too
|
|
162
158
|
if server.has_test_service {
|
|
163
|
-
let resp =
|
|
159
|
+
let resp = connection
|
|
160
|
+
.get_current_time(().into_request())
|
|
161
|
+
.await
|
|
162
|
+
.unwrap();
|
|
164
163
|
// Make sure it's within 5 mins of now
|
|
165
164
|
let resp_seconds = resp.get_ref().time.as_ref().unwrap().seconds as u64;
|
|
166
165
|
let curr_seconds = SystemTime::now()
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
use crate::common::{CoreWfStarter, init_core_and_create_wf};
|
|
1
|
+
use crate::common::{CoreWfStarter, activity_functions::StdActivities, init_core_and_create_wf};
|
|
2
2
|
use assert_matches::assert_matches;
|
|
3
3
|
use std::time::Duration;
|
|
4
|
-
use temporalio_client::
|
|
4
|
+
use temporalio_client::WorkflowStartOptions;
|
|
5
5
|
use temporalio_common::{
|
|
6
6
|
prost_dur,
|
|
7
7
|
protos::{
|
|
8
8
|
DEFAULT_ACTIVITY_TYPE,
|
|
9
9
|
coresdk::{
|
|
10
|
-
ActivityHeartbeat, ActivityTaskCompletion,
|
|
10
|
+
ActivityHeartbeat, ActivityTaskCompletion, IntoCompletion,
|
|
11
11
|
activity_result::{
|
|
12
12
|
self, ActivityExecutionResult, ActivityResolution, activity_resolution as act_res,
|
|
13
13
|
},
|
|
@@ -25,10 +25,44 @@ use temporalio_common::{
|
|
|
25
25
|
test_utils::schedule_activity_cmd,
|
|
26
26
|
},
|
|
27
27
|
};
|
|
28
|
-
use
|
|
28
|
+
use temporalio_macros::{workflow, workflow_methods};
|
|
29
|
+
use temporalio_sdk::{ActivityExecutionError, ActivityOptions, WorkflowContext, WorkflowResult};
|
|
29
30
|
use temporalio_sdk_core::test_help::{WorkerTestHelpers, drain_pollers_and_shutdown};
|
|
30
31
|
use tokio::time::sleep;
|
|
31
32
|
|
|
33
|
+
#[workflow]
|
|
34
|
+
#[derive(Default)]
|
|
35
|
+
struct ActivityDoesntHeartbeatHitsTimeoutThenCompletesWf;
|
|
36
|
+
|
|
37
|
+
#[workflow_methods]
|
|
38
|
+
impl ActivityDoesntHeartbeatHitsTimeoutThenCompletesWf {
|
|
39
|
+
#[run]
|
|
40
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
41
|
+
let res: Result<(), ActivityExecutionError> = ctx
|
|
42
|
+
.start_activity(
|
|
43
|
+
StdActivities::delay,
|
|
44
|
+
Duration::from_secs(4),
|
|
45
|
+
ActivityOptions {
|
|
46
|
+
start_to_close_timeout: Some(Duration::from_secs(10)),
|
|
47
|
+
heartbeat_timeout: Some(Duration::from_secs(2)),
|
|
48
|
+
retry_policy: Some(RetryPolicy {
|
|
49
|
+
maximum_attempts: 1,
|
|
50
|
+
..Default::default()
|
|
51
|
+
}),
|
|
52
|
+
..Default::default()
|
|
53
|
+
},
|
|
54
|
+
)
|
|
55
|
+
.await;
|
|
56
|
+
let err = res.unwrap_err();
|
|
57
|
+
if let ActivityExecutionError::Failed(f) = &err {
|
|
58
|
+
assert_eq!(f.is_timeout(), Some(TimeoutType::Heartbeat));
|
|
59
|
+
} else {
|
|
60
|
+
panic!("expected Failed, got {err:?}");
|
|
61
|
+
}
|
|
62
|
+
Ok(())
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
32
66
|
#[tokio::test]
|
|
33
67
|
async fn activity_heartbeat() {
|
|
34
68
|
let mut starter = init_core_and_create_wf("activity_heartbeat").await;
|
|
@@ -72,6 +106,7 @@ async fn activity_heartbeat() {
|
|
|
72
106
|
let response_payload = Payload {
|
|
73
107
|
data: b"hello ".to_vec(),
|
|
74
108
|
metadata: Default::default(),
|
|
109
|
+
external_payloads: Default::default(),
|
|
75
110
|
};
|
|
76
111
|
// Complete activity successfully.
|
|
77
112
|
core.complete_activity_task(ActivityTaskCompletion {
|
|
@@ -183,46 +218,20 @@ async fn many_act_fails_with_heartbeats() {
|
|
|
183
218
|
async fn activity_doesnt_heartbeat_hits_timeout_then_completes() {
|
|
184
219
|
let wf_name = "activity_doesnt_heartbeat_hits_timeout_then_completes";
|
|
185
220
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
221
|
+
starter.sdk_config.register_activities(StdActivities);
|
|
186
222
|
let mut worker = starter.worker().await;
|
|
187
|
-
let client = starter.get_client().await;
|
|
188
|
-
worker.register_activity(
|
|
189
|
-
"echo_activity",
|
|
190
|
-
|_ctx: ActContext, echo_me: String| async move {
|
|
191
|
-
sleep(Duration::from_secs(4)).await;
|
|
192
|
-
Ok(echo_me)
|
|
193
|
-
},
|
|
194
|
-
);
|
|
195
|
-
worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
|
|
196
|
-
let res = ctx
|
|
197
|
-
.activity(ActivityOptions {
|
|
198
|
-
activity_type: "echo_activity".to_string(),
|
|
199
|
-
input: "hi!".as_json_payload().expect("serializes fine"),
|
|
200
|
-
start_to_close_timeout: Some(Duration::from_secs(10)),
|
|
201
|
-
heartbeat_timeout: Some(Duration::from_secs(2)),
|
|
202
|
-
retry_policy: Some(RetryPolicy {
|
|
203
|
-
maximum_attempts: 1,
|
|
204
|
-
..Default::default()
|
|
205
|
-
}),
|
|
206
|
-
..Default::default()
|
|
207
|
-
})
|
|
208
|
-
.await;
|
|
209
|
-
assert_eq!(res.timed_out(), Some(TimeoutType::Heartbeat));
|
|
210
|
-
Ok(().into())
|
|
211
|
-
});
|
|
212
223
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
224
|
+
worker.register_workflow::<ActivityDoesntHeartbeatHitsTimeoutThenCompletesWf>();
|
|
225
|
+
|
|
226
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
227
|
+
let handle = worker
|
|
228
|
+
.submit_workflow(
|
|
229
|
+
ActivityDoesntHeartbeatHitsTimeoutThenCompletesWf::run,
|
|
230
|
+
(),
|
|
231
|
+
WorkflowStartOptions::new(task_queue, wf_name.to_owned()).build(),
|
|
219
232
|
)
|
|
220
233
|
.await
|
|
221
234
|
.unwrap();
|
|
222
235
|
worker.run_until_done().await.unwrap();
|
|
223
|
-
|
|
224
|
-
handle
|
|
225
|
-
.get_workflow_result(Default::default())
|
|
226
|
-
.await
|
|
227
|
-
.unwrap();
|
|
236
|
+
handle.get_result(Default::default()).await.unwrap();
|
|
228
237
|
}
|