@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
|
@@ -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,7 +1,10 @@
|
|
|
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
10
|
EphemeralExe, EphemeralExeVersion, EphemeralServer, TemporalDevServerConfig,
|
|
@@ -132,16 +135,14 @@ fn fixed_cached_download(version: &str) -> EphemeralExe {
|
|
|
132
135
|
|
|
133
136
|
async fn assert_ephemeral_server(server: &EphemeralServer) {
|
|
134
137
|
// Connect and describe namespace
|
|
135
|
-
let
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
.unwrap();
|
|
144
|
-
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
|
|
145
146
|
.describe_namespace(
|
|
146
147
|
DescribeNamespaceRequest {
|
|
147
148
|
namespace: NAMESPACE.to_string(),
|
|
@@ -155,7 +156,10 @@ async fn assert_ephemeral_server(server: &EphemeralServer) {
|
|
|
155
156
|
|
|
156
157
|
// If it has test service, make sure we can use it too
|
|
157
158
|
if server.has_test_service {
|
|
158
|
-
let resp =
|
|
159
|
+
let resp = connection
|
|
160
|
+
.get_current_time(().into_request())
|
|
161
|
+
.await
|
|
162
|
+
.unwrap();
|
|
159
163
|
// Make sure it's within 5 mins of now
|
|
160
164
|
let resp_seconds = resp.get_ref().time.as_ref().unwrap().seconds as u64;
|
|
161
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;
|
|
@@ -184,46 +218,20 @@ async fn many_act_fails_with_heartbeats() {
|
|
|
184
218
|
async fn activity_doesnt_heartbeat_hits_timeout_then_completes() {
|
|
185
219
|
let wf_name = "activity_doesnt_heartbeat_hits_timeout_then_completes";
|
|
186
220
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
221
|
+
starter.sdk_config.register_activities(StdActivities);
|
|
187
222
|
let mut worker = starter.worker().await;
|
|
188
|
-
let client = starter.get_client().await;
|
|
189
|
-
worker.register_activity(
|
|
190
|
-
"echo_activity",
|
|
191
|
-
|_ctx: ActContext, echo_me: String| async move {
|
|
192
|
-
sleep(Duration::from_secs(4)).await;
|
|
193
|
-
Ok(echo_me)
|
|
194
|
-
},
|
|
195
|
-
);
|
|
196
|
-
worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
|
|
197
|
-
let res = ctx
|
|
198
|
-
.activity(ActivityOptions {
|
|
199
|
-
activity_type: "echo_activity".to_string(),
|
|
200
|
-
input: "hi!".as_json_payload().expect("serializes fine"),
|
|
201
|
-
start_to_close_timeout: Some(Duration::from_secs(10)),
|
|
202
|
-
heartbeat_timeout: Some(Duration::from_secs(2)),
|
|
203
|
-
retry_policy: Some(RetryPolicy {
|
|
204
|
-
maximum_attempts: 1,
|
|
205
|
-
..Default::default()
|
|
206
|
-
}),
|
|
207
|
-
..Default::default()
|
|
208
|
-
})
|
|
209
|
-
.await;
|
|
210
|
-
assert_eq!(res.timed_out(), Some(TimeoutType::Heartbeat));
|
|
211
|
-
Ok(().into())
|
|
212
|
-
});
|
|
213
223
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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(),
|
|
220
232
|
)
|
|
221
233
|
.await
|
|
222
234
|
.unwrap();
|
|
223
235
|
worker.run_until_done().await.unwrap();
|
|
224
|
-
|
|
225
|
-
handle
|
|
226
|
-
.get_workflow_result(Default::default())
|
|
227
|
-
.await
|
|
228
|
-
.unwrap();
|
|
236
|
+
handle.get_result(Default::default()).await.unwrap();
|
|
229
237
|
}
|