@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,31 +1,29 @@
|
|
|
1
|
-
//!
|
|
2
|
-
//!
|
|
1
|
+
//! Common integration testing utilities
|
|
2
|
+
//! These utilities are specific to integration tests and depend on the full temporal-client stack.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
pub(crate) mod http_proxy;
|
|
5
|
+
pub(crate) mod workflows;
|
|
6
6
|
|
|
7
|
-
pub mod canned_histories;
|
|
8
|
-
pub mod interceptors;
|
|
9
|
-
pub mod workflows;
|
|
10
|
-
|
|
11
|
-
pub use temporal_sdk_core::replay::HistoryForReplay;
|
|
12
|
-
|
|
13
|
-
use crate::stream::{Stream, TryStreamExt};
|
|
14
7
|
use anyhow::{Context, Error, bail};
|
|
15
|
-
use
|
|
16
|
-
|
|
8
|
+
use futures_util::{
|
|
9
|
+
Future, StreamExt, future, stream,
|
|
10
|
+
stream::{Stream, TryStreamExt},
|
|
11
|
+
};
|
|
17
12
|
use parking_lot::Mutex;
|
|
18
13
|
use prost::Message;
|
|
19
14
|
use rand::Rng;
|
|
20
15
|
use std::{
|
|
21
16
|
cell::Cell,
|
|
17
|
+
collections::VecDeque,
|
|
22
18
|
convert::TryFrom,
|
|
23
19
|
env,
|
|
24
|
-
future::Future,
|
|
25
20
|
net::SocketAddr,
|
|
26
21
|
path::PathBuf,
|
|
27
22
|
str::FromStr,
|
|
28
|
-
sync::
|
|
23
|
+
sync::{
|
|
24
|
+
Arc,
|
|
25
|
+
atomic::{AtomicBool, Ordering},
|
|
26
|
+
},
|
|
29
27
|
time::{Duration, Instant},
|
|
30
28
|
};
|
|
31
29
|
use temporal_client::{
|
|
@@ -40,17 +38,14 @@ use temporal_sdk::{
|
|
|
40
38
|
WorkerInterceptor,
|
|
41
39
|
},
|
|
42
40
|
};
|
|
43
|
-
#[cfg(feature = "ephemeral-server")]
|
|
44
|
-
use temporal_sdk_core::ephemeral_server::{EphemeralExe, EphemeralExeVersion};
|
|
45
41
|
use temporal_sdk_core::{
|
|
46
42
|
ClientOptions, ClientOptionsBuilder, CoreRuntime, WorkerConfigBuilder, init_replay_worker,
|
|
47
43
|
init_worker,
|
|
48
|
-
replay::ReplayWorkerInput,
|
|
44
|
+
replay::{HistoryForReplay, ReplayWorkerInput},
|
|
49
45
|
telemetry::{build_otlp_metric_exporter, start_prometheus_metric_exporter},
|
|
50
46
|
};
|
|
51
47
|
use temporal_sdk_core_api::{
|
|
52
48
|
Worker as CoreWorker,
|
|
53
|
-
errors::PollError,
|
|
54
49
|
telemetry::{
|
|
55
50
|
Logger, OtelCollectorOptionsBuilder, PrometheusExporterOptions,
|
|
56
51
|
PrometheusExporterOptionsBuilder, TelemetryOptions, TelemetryOptionsBuilder,
|
|
@@ -59,14 +54,8 @@ use temporal_sdk_core_api::{
|
|
|
59
54
|
worker::WorkerVersioningStrategy,
|
|
60
55
|
};
|
|
61
56
|
use temporal_sdk_core_protos::{
|
|
62
|
-
DEFAULT_ACTIVITY_TYPE,
|
|
63
57
|
coresdk::{
|
|
64
|
-
FromPayloadsExt,
|
|
65
|
-
workflow_activation::{WorkflowActivation, WorkflowActivationJob, workflow_activation_job},
|
|
66
|
-
workflow_commands::{
|
|
67
|
-
ActivityCancellationType, CompleteWorkflowExecution, QueryResult, QuerySuccess,
|
|
68
|
-
ScheduleActivity, ScheduleLocalActivity, StartTimer, workflow_command,
|
|
69
|
-
},
|
|
58
|
+
FromPayloadsExt, workflow_activation::WorkflowActivation,
|
|
70
59
|
workflow_completion::WorkflowActivationCompletion,
|
|
71
60
|
},
|
|
72
61
|
temporal::api::{
|
|
@@ -76,47 +65,40 @@ use temporal_sdk_core_protos::{
|
|
|
76
65
|
},
|
|
77
66
|
};
|
|
78
67
|
use tokio::{sync::OnceCell, task::AbortHandle};
|
|
68
|
+
use tonic::IntoRequest;
|
|
69
|
+
use tracing::{debug, warn};
|
|
79
70
|
use url::Url;
|
|
80
71
|
|
|
81
|
-
pub
|
|
82
|
-
pub const TEST_Q: &str = "q";
|
|
72
|
+
pub(crate) use temporal_sdk_core::test_help::NAMESPACE;
|
|
83
73
|
/// The env var used to specify where the integ tests should point
|
|
84
|
-
pub const INTEG_SERVER_TARGET_ENV_VAR: &str = "TEMPORAL_SERVICE_ADDRESS";
|
|
85
|
-
pub const INTEG_NAMESPACE_ENV_VAR: &str = "TEMPORAL_NAMESPACE";
|
|
86
|
-
pub const INTEG_USE_TLS_ENV_VAR: &str = "TEMPORAL_USE_TLS";
|
|
87
|
-
pub const INTEG_API_KEY: &str = "TEMPORAL_API_KEY_PATH";
|
|
88
|
-
|
|
89
|
-
pub
|
|
90
|
-
/// This env var is set (to any value) if the test server is in use
|
|
91
|
-
pub const INTEG_TEST_SERVER_USED_ENV_VAR: &str = "INTEG_TEST_SERVER_ON";
|
|
92
|
-
pub static SEARCH_ATTR_TXT: &str = "CustomTextField";
|
|
93
|
-
pub static SEARCH_ATTR_INT: &str = "CustomIntField";
|
|
74
|
+
pub(crate) const INTEG_SERVER_TARGET_ENV_VAR: &str = "TEMPORAL_SERVICE_ADDRESS";
|
|
75
|
+
pub(crate) const INTEG_NAMESPACE_ENV_VAR: &str = "TEMPORAL_NAMESPACE";
|
|
76
|
+
pub(crate) const INTEG_USE_TLS_ENV_VAR: &str = "TEMPORAL_USE_TLS";
|
|
77
|
+
pub(crate) const INTEG_API_KEY: &str = "TEMPORAL_API_KEY_PATH";
|
|
78
|
+
pub(crate) static SEARCH_ATTR_TXT: &str = "CustomTextField";
|
|
79
|
+
pub(crate) static SEARCH_ATTR_INT: &str = "CustomIntField";
|
|
94
80
|
/// If set, turn export traces and metrics to the OTel collector at the given URL
|
|
95
|
-
pub const OTEL_URL_ENV_VAR: &str = "TEMPORAL_INTEG_OTEL_URL";
|
|
81
|
+
pub(crate) const OTEL_URL_ENV_VAR: &str = "TEMPORAL_INTEG_OTEL_URL";
|
|
96
82
|
/// If set, enable direct scraping of prom metrics on the specified port
|
|
97
|
-
pub const PROM_ENABLE_ENV_VAR: &str = "TEMPORAL_INTEG_PROM_PORT";
|
|
83
|
+
pub(crate) const PROM_ENABLE_ENV_VAR: &str = "TEMPORAL_INTEG_PROM_PORT";
|
|
98
84
|
/// This should match the prometheus port exposed in docker-compose-ci.yaml
|
|
99
|
-
pub const PROMETHEUS_QUERY_API: &str = "http://localhost:9090/api/v1/query";
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
.try_into()
|
|
106
|
-
.expect("test duration fits")
|
|
107
|
-
};
|
|
108
|
-
}
|
|
85
|
+
pub(crate) const PROMETHEUS_QUERY_API: &str = "http://localhost:9090/api/v1/query";
|
|
86
|
+
/// If set, integ tests will use this specific version of CLI for starting dev server
|
|
87
|
+
pub(crate) const CLI_VERSION_OVERRIDE_ENV_VAR: &str = "CLI_VERSION_OVERRIDE";
|
|
88
|
+
pub(crate) const INTEG_CLIENT_IDENTITY: &str = "integ_tester";
|
|
89
|
+
pub(crate) const INTEG_CLIENT_NAME: &str = "temporal-core";
|
|
90
|
+
pub(crate) const INTEG_CLIENT_VERSION: &str = "0.1.0";
|
|
109
91
|
|
|
110
92
|
/// Create a worker instance which will use the provided test name to base the task queue and wf id
|
|
111
93
|
/// upon. Returns the instance.
|
|
112
|
-
pub async fn init_core_and_create_wf(test_name: &str) -> CoreWfStarter {
|
|
94
|
+
pub(crate) async fn init_core_and_create_wf(test_name: &str) -> CoreWfStarter {
|
|
113
95
|
let mut starter = CoreWfStarter::new(test_name);
|
|
114
96
|
let _ = starter.get_worker().await;
|
|
115
97
|
starter.start_wf().await;
|
|
116
98
|
starter
|
|
117
99
|
}
|
|
118
100
|
|
|
119
|
-
pub fn integ_worker_config(tq: &str) -> WorkerConfigBuilder {
|
|
101
|
+
pub(crate) fn integ_worker_config(tq: &str) -> WorkerConfigBuilder {
|
|
120
102
|
let mut b = WorkerConfigBuilder::default();
|
|
121
103
|
b.namespace(NAMESPACE)
|
|
122
104
|
.task_queue(tq)
|
|
@@ -130,14 +112,14 @@ pub fn integ_worker_config(tq: &str) -> WorkerConfigBuilder {
|
|
|
130
112
|
}
|
|
131
113
|
|
|
132
114
|
/// Create a worker replay instance preloaded with provided histories. Returns the worker impl.
|
|
133
|
-
pub fn init_core_replay_preloaded<I>(test_name: &str, histories: I) -> Arc<dyn CoreWorker>
|
|
115
|
+
pub(crate) fn init_core_replay_preloaded<I>(test_name: &str, histories: I) -> Arc<dyn CoreWorker>
|
|
134
116
|
where
|
|
135
117
|
I: IntoIterator<Item = HistoryForReplay> + 'static,
|
|
136
118
|
<I as IntoIterator>::IntoIter: Send,
|
|
137
119
|
{
|
|
138
120
|
init_core_replay_stream(test_name, stream::iter(histories))
|
|
139
121
|
}
|
|
140
|
-
pub fn init_core_replay_stream<I>(test_name: &str, histories: I) -> Arc<dyn CoreWorker>
|
|
122
|
+
pub(crate) fn init_core_replay_stream<I>(test_name: &str, histories: I) -> Arc<dyn CoreWorker>
|
|
141
123
|
where
|
|
142
124
|
I: Stream<Item = HistoryForReplay> + Send + 'static,
|
|
143
125
|
{
|
|
@@ -149,14 +131,14 @@ where
|
|
|
149
131
|
.expect("Replay worker must init properly");
|
|
150
132
|
Arc::new(worker)
|
|
151
133
|
}
|
|
152
|
-
pub fn replay_sdk_worker<I>(histories: I) -> Worker
|
|
134
|
+
pub(crate) fn replay_sdk_worker<I>(histories: I) -> Worker
|
|
153
135
|
where
|
|
154
136
|
I: IntoIterator<Item = HistoryForReplay> + 'static,
|
|
155
137
|
<I as IntoIterator>::IntoIter: Send,
|
|
156
138
|
{
|
|
157
139
|
replay_sdk_worker_stream(stream::iter(histories))
|
|
158
140
|
}
|
|
159
|
-
pub fn replay_sdk_worker_stream<I>(histories: I) -> Worker
|
|
141
|
+
pub(crate) fn replay_sdk_worker_stream<I>(histories: I) -> Worker
|
|
160
142
|
where
|
|
161
143
|
I: Stream<Item = HistoryForReplay> + Send + 'static,
|
|
162
144
|
{
|
|
@@ -167,7 +149,9 @@ where
|
|
|
167
149
|
}
|
|
168
150
|
|
|
169
151
|
/// Load history from a file containing the protobuf serialization of it
|
|
170
|
-
pub async fn history_from_proto_binary(
|
|
152
|
+
pub(crate) async fn history_from_proto_binary(
|
|
153
|
+
path_from_root: &str,
|
|
154
|
+
) -> Result<History, anyhow::Error> {
|
|
171
155
|
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
172
156
|
path.push("..");
|
|
173
157
|
path.push(path_from_root);
|
|
@@ -180,7 +164,7 @@ thread_local! {
|
|
|
180
164
|
pub static DONT_AUTO_INIT_INTEG_TELEM: Cell<bool> = const { Cell::new(false) };
|
|
181
165
|
}
|
|
182
166
|
static INTEG_TESTS_RT: std::sync::OnceLock<CoreRuntime> = std::sync::OnceLock::new();
|
|
183
|
-
pub fn init_integ_telem() -> Option<&'static CoreRuntime> {
|
|
167
|
+
pub(crate) fn init_integ_telem() -> Option<&'static CoreRuntime> {
|
|
184
168
|
if DONT_AUTO_INIT_INTEG_TELEM.get() {
|
|
185
169
|
return None;
|
|
186
170
|
}
|
|
@@ -195,7 +179,7 @@ pub fn init_integ_telem() -> Option<&'static CoreRuntime> {
|
|
|
195
179
|
}))
|
|
196
180
|
}
|
|
197
181
|
|
|
198
|
-
pub async fn get_cloud_client() -> RetryClient<Client> {
|
|
182
|
+
pub(crate) async fn get_cloud_client() -> RetryClient<Client> {
|
|
199
183
|
let cloud_addr = env::var("TEMPORAL_CLOUD_ADDRESS").unwrap();
|
|
200
184
|
let cloud_key = env::var("TEMPORAL_CLIENT_KEY").unwrap();
|
|
201
185
|
|
|
@@ -227,7 +211,7 @@ pub async fn get_cloud_client() -> RetryClient<Client> {
|
|
|
227
211
|
}
|
|
228
212
|
|
|
229
213
|
/// Implements a builder pattern to help integ tests initialize core and create workflows
|
|
230
|
-
pub struct CoreWfStarter {
|
|
214
|
+
pub(crate) struct CoreWfStarter {
|
|
231
215
|
/// Used for both the task queue and workflow id
|
|
232
216
|
task_queue_name: String,
|
|
233
217
|
pub worker_config: WorkerConfigBuilder,
|
|
@@ -244,25 +228,20 @@ struct InitializedWorker {
|
|
|
244
228
|
}
|
|
245
229
|
|
|
246
230
|
impl CoreWfStarter {
|
|
247
|
-
pub fn new(test_name: &str) -> Self {
|
|
231
|
+
pub(crate) fn new(test_name: &str) -> Self {
|
|
248
232
|
init_integ_telem();
|
|
249
233
|
Self::_new(test_name, None, None)
|
|
250
234
|
}
|
|
251
235
|
|
|
252
|
-
pub fn new_with_runtime(test_name: &str, runtime: CoreRuntime) -> Self {
|
|
236
|
+
pub(crate) fn new_with_runtime(test_name: &str, runtime: CoreRuntime) -> Self {
|
|
253
237
|
Self::_new(test_name, Some(runtime), None)
|
|
254
238
|
}
|
|
255
239
|
|
|
256
|
-
pub fn new_with_client(test_name: &str, client: RetryClient<Client>) -> Self {
|
|
257
|
-
init_integ_telem();
|
|
258
|
-
Self::_new(test_name, None, Some(client))
|
|
259
|
-
}
|
|
260
|
-
|
|
261
240
|
/// Targets cloud if the required env vars are present. Otherwise, local server (but only if
|
|
262
241
|
/// the minimum version requirement is met). Returns None if the local server is not new enough.
|
|
263
242
|
///
|
|
264
243
|
/// An empty string means to skip the version check.
|
|
265
|
-
pub async fn new_cloud_or_local(test_name: &str, version_req: &str) -> Option<Self> {
|
|
244
|
+
pub(crate) async fn new_cloud_or_local(test_name: &str, version_req: &str) -> Option<Self> {
|
|
266
245
|
init_integ_telem();
|
|
267
246
|
let mut check_mlsv = false;
|
|
268
247
|
let client = if env::var("TEMPORAL_CLOUD_ADDRESS").is_ok() {
|
|
@@ -278,8 +257,7 @@ impl CoreWfStarter {
|
|
|
278
257
|
.get_client()
|
|
279
258
|
.inner()
|
|
280
259
|
.workflow_svc()
|
|
281
|
-
.
|
|
282
|
-
.get_cluster_info(GetClusterInfoRequest::default())
|
|
260
|
+
.get_cluster_info(GetClusterInfoRequest::default().into_request())
|
|
283
261
|
.await;
|
|
284
262
|
let srv_ver = semver::Version::parse(
|
|
285
263
|
&clustinfo
|
|
@@ -327,7 +305,7 @@ impl CoreWfStarter {
|
|
|
327
305
|
|
|
328
306
|
/// Create a new starter with no initialized worker or runtime override. Useful for starting a
|
|
329
307
|
/// new worker on the same queue.
|
|
330
|
-
pub fn clone_no_worker(&self) -> Self {
|
|
308
|
+
pub(crate) fn clone_no_worker(&self) -> Self {
|
|
331
309
|
Self {
|
|
332
310
|
task_queue_name: self.task_queue_name.clone(),
|
|
333
311
|
worker_config: self.worker_config.clone(),
|
|
@@ -339,7 +317,7 @@ impl CoreWfStarter {
|
|
|
339
317
|
}
|
|
340
318
|
}
|
|
341
319
|
|
|
342
|
-
pub async fn worker(&mut self) -> TestWorker {
|
|
320
|
+
pub(crate) async fn worker(&mut self) -> TestWorker {
|
|
343
321
|
let w = self.get_worker().await;
|
|
344
322
|
let tq = w.get_config().task_queue.clone();
|
|
345
323
|
let mut w = TestWorker::new(w, tq);
|
|
@@ -348,25 +326,25 @@ impl CoreWfStarter {
|
|
|
348
326
|
w
|
|
349
327
|
}
|
|
350
328
|
|
|
351
|
-
pub async fn shutdown(&mut self) {
|
|
329
|
+
pub(crate) async fn shutdown(&mut self) {
|
|
352
330
|
self.get_worker().await.shutdown().await;
|
|
353
331
|
}
|
|
354
332
|
|
|
355
|
-
pub async fn get_worker(&mut self) -> Arc<dyn CoreWorker> {
|
|
333
|
+
pub(crate) async fn get_worker(&mut self) -> Arc<dyn CoreWorker> {
|
|
356
334
|
self.get_or_init().await.worker.clone()
|
|
357
335
|
}
|
|
358
336
|
|
|
359
|
-
pub async fn get_client(&mut self) -> Arc<RetryClient<Client>> {
|
|
337
|
+
pub(crate) async fn get_client(&mut self) -> Arc<RetryClient<Client>> {
|
|
360
338
|
self.get_or_init().await.client.clone()
|
|
361
339
|
}
|
|
362
340
|
|
|
363
341
|
/// Start the workflow defined by the builder and return run id
|
|
364
|
-
pub async fn start_wf(&mut self) -> String {
|
|
342
|
+
pub(crate) async fn start_wf(&mut self) -> String {
|
|
365
343
|
self.start_wf_with_id(self.get_wf_id().to_owned()).await
|
|
366
344
|
}
|
|
367
345
|
|
|
368
346
|
/// Starts the workflow using the worker
|
|
369
|
-
pub async fn start_with_worker(
|
|
347
|
+
pub(crate) async fn start_with_worker(
|
|
370
348
|
&self,
|
|
371
349
|
wf_name: impl Into<String>,
|
|
372
350
|
worker: &mut TestWorker,
|
|
@@ -387,7 +365,7 @@ impl CoreWfStarter {
|
|
|
387
365
|
.get_untyped_workflow_handle(&self.task_queue_name, run_id)
|
|
388
366
|
}
|
|
389
367
|
|
|
390
|
-
pub async fn eager_start_with_worker(
|
|
368
|
+
pub(crate) async fn eager_start_with_worker(
|
|
391
369
|
&self,
|
|
392
370
|
wf_name: impl Into<String>,
|
|
393
371
|
worker: &mut TestWorker,
|
|
@@ -404,7 +382,7 @@ impl CoreWfStarter {
|
|
|
404
382
|
.unwrap()
|
|
405
383
|
}
|
|
406
384
|
|
|
407
|
-
pub async fn start_wf_with_id(&self, workflow_id: String) -> String {
|
|
385
|
+
pub(crate) async fn start_wf_with_id(&self, workflow_id: String) -> String {
|
|
408
386
|
let iw = self.initted_worker.get().expect(
|
|
409
387
|
"Worker must be initted before starting a workflow.\
|
|
410
388
|
Tests must call `get_worker` first.",
|
|
@@ -423,17 +401,17 @@ impl CoreWfStarter {
|
|
|
423
401
|
.run_id
|
|
424
402
|
}
|
|
425
403
|
|
|
426
|
-
pub fn get_task_queue(&self) -> &str {
|
|
404
|
+
pub(crate) fn get_task_queue(&self) -> &str {
|
|
427
405
|
&self.task_queue_name
|
|
428
406
|
}
|
|
429
407
|
|
|
430
|
-
pub fn get_wf_id(&self) -> &str {
|
|
408
|
+
pub(crate) fn get_wf_id(&self) -> &str {
|
|
431
409
|
&self.task_queue_name
|
|
432
410
|
}
|
|
433
411
|
|
|
434
412
|
/// Fetch the history of the default workflow for this starter. IE: The one that would
|
|
435
413
|
/// be started by [CoreWfStarter::start_wf].
|
|
436
|
-
pub async fn get_history(&self) -> History {
|
|
414
|
+
pub(crate) async fn get_history(&self) -> History {
|
|
437
415
|
self.initted_worker
|
|
438
416
|
.get()
|
|
439
417
|
.expect("Starter must be initialized")
|
|
@@ -445,7 +423,7 @@ impl CoreWfStarter {
|
|
|
445
423
|
.unwrap()
|
|
446
424
|
}
|
|
447
425
|
|
|
448
|
-
pub async fn wait_for_default_wf_finish(
|
|
426
|
+
pub(crate) async fn wait_for_default_wf_finish(
|
|
449
427
|
&self,
|
|
450
428
|
) -> Result<WorkflowExecutionResult<Vec<Payload>>, Error> {
|
|
451
429
|
self.initted_worker
|
|
@@ -493,7 +471,7 @@ impl CoreWfStarter {
|
|
|
493
471
|
}
|
|
494
472
|
|
|
495
473
|
/// Provides conveniences for running integ tests with the SDK (against real server or mocks)
|
|
496
|
-
pub struct TestWorker {
|
|
474
|
+
pub(crate) struct TestWorker {
|
|
497
475
|
inner: Worker,
|
|
498
476
|
pub core_worker: Arc<dyn CoreWorker>,
|
|
499
477
|
client: Option<Arc<RetryClient<Client>>>,
|
|
@@ -504,7 +482,7 @@ pub struct TestWorker {
|
|
|
504
482
|
}
|
|
505
483
|
impl TestWorker {
|
|
506
484
|
/// Create a new test worker
|
|
507
|
-
pub fn new(core_worker: Arc<dyn CoreWorker>, task_queue: impl Into<String>) -> Self {
|
|
485
|
+
pub(crate) fn new(core_worker: Arc<dyn CoreWorker>, task_queue: impl Into<String>) -> Self {
|
|
508
486
|
let inner = Worker::new_from_core(core_worker.clone(), task_queue);
|
|
509
487
|
Self {
|
|
510
488
|
inner,
|
|
@@ -515,12 +493,12 @@ impl TestWorker {
|
|
|
515
493
|
}
|
|
516
494
|
}
|
|
517
495
|
|
|
518
|
-
pub fn inner_mut(&mut self) -> &mut Worker {
|
|
496
|
+
pub(crate) fn inner_mut(&mut self) -> &mut Worker {
|
|
519
497
|
&mut self.inner
|
|
520
498
|
}
|
|
521
499
|
|
|
522
500
|
// TODO: Maybe trait-ify?
|
|
523
|
-
pub fn register_wf<F: Into<WorkflowFunction>>(
|
|
501
|
+
pub(crate) fn register_wf<F: Into<WorkflowFunction>>(
|
|
524
502
|
&mut self,
|
|
525
503
|
workflow_type: impl Into<String>,
|
|
526
504
|
wf_function: F,
|
|
@@ -528,7 +506,7 @@ impl TestWorker {
|
|
|
528
506
|
self.inner.register_wf(workflow_type, wf_function)
|
|
529
507
|
}
|
|
530
508
|
|
|
531
|
-
pub fn register_activity<A, R, O>(
|
|
509
|
+
pub(crate) fn register_activity<A, R, O>(
|
|
532
510
|
&mut self,
|
|
533
511
|
activity_type: impl Into<String>,
|
|
534
512
|
act_function: impl IntoActivityFunc<A, R, O>,
|
|
@@ -538,7 +516,7 @@ impl TestWorker {
|
|
|
538
516
|
|
|
539
517
|
/// Create a handle that can be used to submit workflows. Useful when workflows need to be
|
|
540
518
|
/// started concurrently with running the worker.
|
|
541
|
-
pub fn get_submitter_handle(&self) -> TestWorkerSubmitterHandle {
|
|
519
|
+
pub(crate) fn get_submitter_handle(&self) -> TestWorkerSubmitterHandle {
|
|
542
520
|
TestWorkerSubmitterHandle {
|
|
543
521
|
client: self.client.clone().expect("client must be set"),
|
|
544
522
|
tq: self.inner.task_queue().to_string(),
|
|
@@ -552,7 +530,7 @@ impl TestWorker {
|
|
|
552
530
|
/// Increments the expected Workflow run count.
|
|
553
531
|
///
|
|
554
532
|
/// Returns the run id of the started workflow (if no client has initialized returns a fake id)
|
|
555
|
-
pub async fn submit_wf(
|
|
533
|
+
pub(crate) async fn submit_wf(
|
|
556
534
|
&self,
|
|
557
535
|
workflow_id: impl Into<String>,
|
|
558
536
|
workflow_type: impl Into<String>,
|
|
@@ -575,7 +553,7 @@ impl TestWorker {
|
|
|
575
553
|
/// Similar to `submit_wf` but checking that the server returns the first
|
|
576
554
|
/// workflow task in the client response.
|
|
577
555
|
/// Note that this does not guarantee that the worker will execute this task eagerly.
|
|
578
|
-
pub async fn eager_submit_wf(
|
|
556
|
+
pub(crate) async fn eager_submit_wf(
|
|
579
557
|
&self,
|
|
580
558
|
workflow_id: impl Into<String>,
|
|
581
559
|
workflow_type: impl Into<String>,
|
|
@@ -605,27 +583,30 @@ impl TestWorker {
|
|
|
605
583
|
Ok(res)
|
|
606
584
|
}
|
|
607
585
|
|
|
608
|
-
pub fn expect_workflow_completion(
|
|
586
|
+
pub(crate) fn expect_workflow_completion(
|
|
587
|
+
&self,
|
|
588
|
+
wf_id: impl Into<String>,
|
|
589
|
+
run_id: Option<String>,
|
|
590
|
+
) {
|
|
609
591
|
self.started_workflows.lock().push(WorkflowExecutionInfo {
|
|
610
592
|
namespace: self
|
|
611
593
|
.client
|
|
612
594
|
.as_ref()
|
|
613
595
|
.map(|c| c.namespace())
|
|
614
|
-
.unwrap_or(NAMESPACE)
|
|
615
|
-
.to_owned(),
|
|
596
|
+
.unwrap_or(NAMESPACE.to_owned()),
|
|
616
597
|
workflow_id: wf_id.into(),
|
|
617
598
|
run_id,
|
|
618
599
|
});
|
|
619
600
|
}
|
|
620
601
|
|
|
621
602
|
/// Runs until all expected workflows have completed and then shuts down the worker
|
|
622
|
-
pub async fn run_until_done(&mut self) -> Result<(), anyhow::Error> {
|
|
603
|
+
pub(crate) async fn run_until_done(&mut self) -> Result<(), anyhow::Error> {
|
|
623
604
|
self.run_until_done_intercepted(Option::<TestWorkerCompletionIceptor>::None)
|
|
624
605
|
.await
|
|
625
606
|
}
|
|
626
607
|
|
|
627
608
|
/// See [Self::run_until_done], but allows configuration of some low-level interception.
|
|
628
|
-
pub async fn run_until_done_intercepted(
|
|
609
|
+
pub(crate) async fn run_until_done_intercepted(
|
|
629
610
|
&mut self,
|
|
630
611
|
next_interceptor: Option<impl WorkerInterceptor + 'static>,
|
|
631
612
|
) -> Result<(), anyhow::Error> {
|
|
@@ -650,7 +631,7 @@ impl TestWorker {
|
|
|
650
631
|
}
|
|
651
632
|
}
|
|
652
633
|
|
|
653
|
-
pub struct TestWorkerSubmitterHandle {
|
|
634
|
+
pub(crate) struct TestWorkerSubmitterHandle {
|
|
654
635
|
client: Arc<RetryClient<Client>>,
|
|
655
636
|
tq: String,
|
|
656
637
|
started_workflows: Arc<Mutex<Vec<WorkflowExecutionInfo>>>,
|
|
@@ -662,7 +643,7 @@ impl TestWorkerSubmitterHandle {
|
|
|
662
643
|
/// Increments the expected Workflow run count.
|
|
663
644
|
///
|
|
664
645
|
/// Returns the run id of the started workflow
|
|
665
|
-
pub async fn submit_wf(
|
|
646
|
+
pub(crate) async fn submit_wf(
|
|
666
647
|
&self,
|
|
667
648
|
workflow_id: impl Into<String>,
|
|
668
649
|
workflow_type: impl Into<String>,
|
|
@@ -690,20 +671,18 @@ impl TestWorkerSubmitterHandle {
|
|
|
690
671
|
}
|
|
691
672
|
}
|
|
692
673
|
|
|
693
|
-
pub
|
|
694
|
-
|
|
695
|
-
pub enum TestWorkerShutdownCond {
|
|
674
|
+
pub(crate) enum TestWorkerShutdownCond {
|
|
696
675
|
GetResults(Vec<WorkflowExecutionInfo>, Arc<RetryClient<Client>>),
|
|
697
676
|
NoAutoShutdown,
|
|
698
677
|
}
|
|
699
678
|
/// Implements calling the shutdown handle when the expected number of test workflows has completed
|
|
700
|
-
pub struct TestWorkerCompletionIceptor {
|
|
679
|
+
pub(crate) struct TestWorkerCompletionIceptor {
|
|
701
680
|
condition: TestWorkerShutdownCond,
|
|
702
681
|
shutdown_handle: Arc<dyn Fn()>,
|
|
703
682
|
next: Option<Box<dyn WorkerInterceptor>>,
|
|
704
683
|
}
|
|
705
684
|
impl TestWorkerCompletionIceptor {
|
|
706
|
-
pub fn new(condition: TestWorkerShutdownCond, shutdown_handle: Arc<dyn Fn()>) -> Self {
|
|
685
|
+
pub(crate) fn new(condition: TestWorkerShutdownCond, shutdown_handle: Arc<dyn Fn()>) -> Self {
|
|
707
686
|
Self {
|
|
708
687
|
condition,
|
|
709
688
|
shutdown_handle,
|
|
@@ -761,15 +740,15 @@ impl WorkerInterceptor for TestWorkerCompletionIceptor {
|
|
|
761
740
|
}
|
|
762
741
|
|
|
763
742
|
/// Returns the client options used to connect to the server used for integration tests.
|
|
764
|
-
pub fn get_integ_server_options() -> ClientOptions {
|
|
743
|
+
pub(crate) fn get_integ_server_options() -> ClientOptions {
|
|
765
744
|
let temporal_server_address = env::var(INTEG_SERVER_TARGET_ENV_VAR)
|
|
766
745
|
.unwrap_or_else(|_| "http://localhost:7233".to_owned());
|
|
767
746
|
let url = Url::try_from(&*temporal_server_address).unwrap();
|
|
768
747
|
let mut cb = ClientOptionsBuilder::default();
|
|
769
|
-
cb.identity(
|
|
748
|
+
cb.identity(INTEG_CLIENT_IDENTITY.to_string())
|
|
770
749
|
.target_url(url)
|
|
771
|
-
.client_name(
|
|
772
|
-
.client_version(
|
|
750
|
+
.client_name(INTEG_CLIENT_NAME.to_string())
|
|
751
|
+
.client_version(INTEG_CLIENT_VERSION.to_string());
|
|
773
752
|
if let Ok(key_file) = env::var(INTEG_API_KEY) {
|
|
774
753
|
let content = std::fs::read_to_string(key_file).unwrap();
|
|
775
754
|
cb.api_key(Some(content));
|
|
@@ -780,7 +759,7 @@ pub fn get_integ_server_options() -> ClientOptions {
|
|
|
780
759
|
cb.build().unwrap()
|
|
781
760
|
}
|
|
782
761
|
|
|
783
|
-
pub fn get_integ_tls_config() -> Option<TlsConfig> {
|
|
762
|
+
pub(crate) fn get_integ_tls_config() -> Option<TlsConfig> {
|
|
784
763
|
if env::var(INTEG_USE_TLS_ENV_VAR).is_ok() {
|
|
785
764
|
let root = std::fs::read("../.cloud_certs/ca.pem").unwrap();
|
|
786
765
|
let client_cert = std::fs::read("../.cloud_certs/client.pem").unwrap();
|
|
@@ -798,7 +777,7 @@ pub fn get_integ_tls_config() -> Option<TlsConfig> {
|
|
|
798
777
|
}
|
|
799
778
|
}
|
|
800
779
|
|
|
801
|
-
pub fn get_integ_telem_options() -> TelemetryOptions {
|
|
780
|
+
pub(crate) fn get_integ_telem_options() -> TelemetryOptions {
|
|
802
781
|
let mut ob = TelemetryOptionsBuilder::default();
|
|
803
782
|
let filter_string =
|
|
804
783
|
env::var("RUST_LOG").unwrap_or_else(|_| "INFO,temporal_sdk_core=INFO".to_string());
|
|
@@ -832,154 +811,8 @@ pub fn get_integ_telem_options() -> TelemetryOptions {
|
|
|
832
811
|
.unwrap()
|
|
833
812
|
}
|
|
834
813
|
|
|
835
|
-
#[cfg(feature = "ephemeral-server")]
|
|
836
|
-
pub fn default_cached_download() -> EphemeralExe {
|
|
837
|
-
EphemeralExe::CachedDownload {
|
|
838
|
-
version: EphemeralExeVersion::SDKDefault {
|
|
839
|
-
sdk_name: "sdk-rust".to_string(),
|
|
840
|
-
sdk_version: "0.1.0".to_string(),
|
|
841
|
-
},
|
|
842
|
-
dest_dir: None,
|
|
843
|
-
// 15 days
|
|
844
|
-
ttl: Some(Duration::from_secs(60 * 60 * 24 * 15)),
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
pub fn schedule_activity_cmd(
|
|
849
|
-
seq: u32,
|
|
850
|
-
task_q: &str,
|
|
851
|
-
activity_id: &str,
|
|
852
|
-
cancellation_type: ActivityCancellationType,
|
|
853
|
-
activity_timeout: Duration,
|
|
854
|
-
heartbeat_timeout: Duration,
|
|
855
|
-
) -> workflow_command::Variant {
|
|
856
|
-
ScheduleActivity {
|
|
857
|
-
seq,
|
|
858
|
-
activity_id: activity_id.to_string(),
|
|
859
|
-
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
860
|
-
task_queue: task_q.to_owned(),
|
|
861
|
-
schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
862
|
-
start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
863
|
-
schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
864
|
-
heartbeat_timeout: Some(heartbeat_timeout.try_into().expect("duration fits")),
|
|
865
|
-
cancellation_type: cancellation_type as i32,
|
|
866
|
-
..Default::default()
|
|
867
|
-
}
|
|
868
|
-
.into()
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
pub fn schedule_local_activity_cmd(
|
|
872
|
-
seq: u32,
|
|
873
|
-
activity_id: &str,
|
|
874
|
-
cancellation_type: ActivityCancellationType,
|
|
875
|
-
activity_timeout: Duration,
|
|
876
|
-
) -> workflow_command::Variant {
|
|
877
|
-
ScheduleLocalActivity {
|
|
878
|
-
seq,
|
|
879
|
-
activity_id: activity_id.to_string(),
|
|
880
|
-
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
881
|
-
schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
882
|
-
start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
883
|
-
schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
884
|
-
cancellation_type: cancellation_type as i32,
|
|
885
|
-
..Default::default()
|
|
886
|
-
}
|
|
887
|
-
.into()
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
pub fn start_timer_cmd(seq: u32, duration: Duration) -> workflow_command::Variant {
|
|
891
|
-
StartTimer {
|
|
892
|
-
seq,
|
|
893
|
-
start_to_fire_timeout: Some(duration.try_into().expect("duration fits")),
|
|
894
|
-
}
|
|
895
|
-
.into()
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
pub fn query_ok(id: impl Into<String>, response: impl Into<Payload>) -> workflow_command::Variant {
|
|
899
|
-
QueryResult {
|
|
900
|
-
query_id: id.into(),
|
|
901
|
-
variant: Some(
|
|
902
|
-
QuerySuccess {
|
|
903
|
-
response: Some(response.into()),
|
|
904
|
-
}
|
|
905
|
-
.into(),
|
|
906
|
-
),
|
|
907
|
-
}
|
|
908
|
-
.into()
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
/// Given a desired number of concurrent executions and a provided function that produces a future,
|
|
912
|
-
/// run that many instances of the future concurrently.
|
|
913
|
-
///
|
|
914
|
-
/// Annoyingly, because of a sorta-bug in the way async blocks work, the async block produced by
|
|
915
|
-
/// the closure must be `async move` if it uses the provided iteration number. On the plus side,
|
|
916
|
-
/// since you're usually just accessing core in the closure, if core is a reference everything just
|
|
917
|
-
/// works. See <https://github.com/rust-lang/rust/issues/81653>
|
|
918
|
-
pub async fn fanout_tasks<FutureMaker, Fut>(num: usize, fm: FutureMaker)
|
|
919
|
-
where
|
|
920
|
-
FutureMaker: Fn(usize) -> Fut,
|
|
921
|
-
Fut: Future,
|
|
922
|
-
{
|
|
923
|
-
let mut tasks = FuturesUnordered::new();
|
|
924
|
-
for i in 0..num {
|
|
925
|
-
tasks.push(fm(i));
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
while tasks.next().await.is_some() {}
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
#[async_trait::async_trait]
|
|
932
|
-
pub trait WorkerTestHelpers {
|
|
933
|
-
async fn complete_execution(&self, run_id: &str);
|
|
934
|
-
async fn complete_timer(&self, run_id: &str, seq: u32, duration: Duration);
|
|
935
|
-
async fn handle_eviction(&self);
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
#[async_trait::async_trait]
|
|
939
|
-
impl<T> WorkerTestHelpers for T
|
|
940
|
-
where
|
|
941
|
-
T: CoreWorker + ?Sized,
|
|
942
|
-
{
|
|
943
|
-
async fn complete_execution(&self, run_id: &str) {
|
|
944
|
-
self.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
945
|
-
run_id.to_string(),
|
|
946
|
-
vec![CompleteWorkflowExecution { result: None }.into()],
|
|
947
|
-
))
|
|
948
|
-
.await
|
|
949
|
-
.unwrap();
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
async fn complete_timer(&self, run_id: &str, seq: u32, duration: Duration) {
|
|
953
|
-
self.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
|
954
|
-
run_id.to_string(),
|
|
955
|
-
vec![
|
|
956
|
-
StartTimer {
|
|
957
|
-
seq,
|
|
958
|
-
start_to_fire_timeout: Some(duration.try_into().expect("duration fits")),
|
|
959
|
-
}
|
|
960
|
-
.into(),
|
|
961
|
-
],
|
|
962
|
-
))
|
|
963
|
-
.await
|
|
964
|
-
.unwrap();
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
async fn handle_eviction(&self) {
|
|
968
|
-
let task = self.poll_workflow_activation().await.unwrap();
|
|
969
|
-
assert_matches!(
|
|
970
|
-
task.jobs.as_slice(),
|
|
971
|
-
[WorkflowActivationJob {
|
|
972
|
-
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
|
973
|
-
}]
|
|
974
|
-
);
|
|
975
|
-
self.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
|
|
976
|
-
.await
|
|
977
|
-
.unwrap();
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
|
|
981
814
|
#[async_trait::async_trait(?Send)]
|
|
982
|
-
pub trait WorkflowHandleExt {
|
|
815
|
+
pub(crate) trait WorkflowHandleExt {
|
|
983
816
|
async fn fetch_history_and_replay(
|
|
984
817
|
&self,
|
|
985
818
|
worker: &mut Worker,
|
|
@@ -1016,27 +849,7 @@ where
|
|
|
1016
849
|
}
|
|
1017
850
|
}
|
|
1018
851
|
|
|
1019
|
-
|
|
1020
|
-
pub async fn drain_pollers_and_shutdown(worker: &Arc<dyn CoreWorker>) {
|
|
1021
|
-
worker.initiate_shutdown();
|
|
1022
|
-
tokio::join!(
|
|
1023
|
-
async {
|
|
1024
|
-
assert!(matches!(
|
|
1025
|
-
worker.poll_activity_task().await.unwrap_err(),
|
|
1026
|
-
PollError::ShutDown
|
|
1027
|
-
));
|
|
1028
|
-
},
|
|
1029
|
-
async {
|
|
1030
|
-
assert!(matches!(
|
|
1031
|
-
worker.poll_workflow_activation().await.unwrap_err(),
|
|
1032
|
-
PollError::ShutDown,
|
|
1033
|
-
));
|
|
1034
|
-
}
|
|
1035
|
-
);
|
|
1036
|
-
worker.shutdown().await;
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
pub fn rand_6_chars() -> String {
|
|
852
|
+
pub(crate) fn rand_6_chars() -> String {
|
|
1040
853
|
rand::rng()
|
|
1041
854
|
.sample_iter(&rand::distr::Alphanumeric)
|
|
1042
855
|
.take(6)
|
|
@@ -1044,9 +857,9 @@ pub fn rand_6_chars() -> String {
|
|
|
1044
857
|
.collect()
|
|
1045
858
|
}
|
|
1046
859
|
|
|
1047
|
-
pub static ANY_PORT: &str = "127.0.0.1:0";
|
|
860
|
+
pub(crate) static ANY_PORT: &str = "127.0.0.1:0";
|
|
1048
861
|
|
|
1049
|
-
pub fn prom_metrics(
|
|
862
|
+
pub(crate) fn prom_metrics(
|
|
1050
863
|
options_override: Option<PrometheusExporterOptions>,
|
|
1051
864
|
) -> (TelemetryOptions, SocketAddr, AbortOnDrop) {
|
|
1052
865
|
let prom_exp_opts = options_override.unwrap_or_else(|| {
|
|
@@ -1067,7 +880,7 @@ pub fn prom_metrics(
|
|
|
1067
880
|
)
|
|
1068
881
|
}
|
|
1069
882
|
|
|
1070
|
-
pub struct AbortOnDrop {
|
|
883
|
+
pub(crate) struct AbortOnDrop {
|
|
1071
884
|
ah: AbortHandle,
|
|
1072
885
|
}
|
|
1073
886
|
|
|
@@ -1077,7 +890,7 @@ impl Drop for AbortOnDrop {
|
|
|
1077
890
|
}
|
|
1078
891
|
}
|
|
1079
892
|
|
|
1080
|
-
pub async fn eventually<F, Fut, T, E>(func: F, timeout: Duration) -> Result<T, anyhow::Error>
|
|
893
|
+
pub(crate) async fn eventually<F, Fut, T, E>(func: F, timeout: Duration) -> Result<T, anyhow::Error>
|
|
1081
894
|
where
|
|
1082
895
|
F: Fn() -> Fut,
|
|
1083
896
|
Fut: Future<Output = Result<T, E>>,
|
|
@@ -1093,3 +906,123 @@ where
|
|
|
1093
906
|
tokio::time::sleep(Duration::from_millis(50)).await;
|
|
1094
907
|
}
|
|
1095
908
|
}
|
|
909
|
+
|
|
910
|
+
use temporal_sdk_core::{
|
|
911
|
+
WorkerConfig,
|
|
912
|
+
test_help::{MockPollCfg, build_mock_pollers, mock_worker},
|
|
913
|
+
};
|
|
914
|
+
|
|
915
|
+
pub(crate) fn build_fake_sdk(mock_cfg: MockPollCfg) -> temporal_sdk::Worker {
|
|
916
|
+
let mut mock = build_mock_pollers(mock_cfg);
|
|
917
|
+
mock.worker_cfg(|c| {
|
|
918
|
+
c.max_cached_workflows = 1;
|
|
919
|
+
c.ignore_evicts_on_shutdown = false;
|
|
920
|
+
});
|
|
921
|
+
let core = mock_worker(mock);
|
|
922
|
+
let mut worker = temporal_sdk::Worker::new_from_core(Arc::new(core), "replay_q".to_string());
|
|
923
|
+
worker.set_worker_interceptor(FailOnNondeterminismInterceptor {});
|
|
924
|
+
worker
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
pub(crate) fn mock_sdk(poll_cfg: MockPollCfg) -> TestWorker {
|
|
928
|
+
mock_sdk_cfg(poll_cfg, |_| {})
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
pub(crate) fn mock_sdk_cfg(
|
|
932
|
+
mut poll_cfg: MockPollCfg,
|
|
933
|
+
mutator: impl FnOnce(&mut WorkerConfig),
|
|
934
|
+
) -> TestWorker {
|
|
935
|
+
poll_cfg.using_rust_sdk = true;
|
|
936
|
+
let mut mock = build_mock_pollers(poll_cfg);
|
|
937
|
+
mock.worker_cfg(mutator);
|
|
938
|
+
let core = mock_worker(mock);
|
|
939
|
+
TestWorker::new(
|
|
940
|
+
Arc::new(core),
|
|
941
|
+
temporal_sdk_core::test_help::TEST_Q.to_string(),
|
|
942
|
+
)
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
#[derive(Default)]
|
|
946
|
+
pub(crate) struct ActivationAssertionsInterceptor {
|
|
947
|
+
#[allow(clippy::type_complexity)]
|
|
948
|
+
assertions: Mutex<VecDeque<Box<dyn FnOnce(&WorkflowActivation)>>>,
|
|
949
|
+
used: AtomicBool,
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
impl ActivationAssertionsInterceptor {
|
|
953
|
+
pub(crate) fn skip_one(&mut self) -> &mut Self {
|
|
954
|
+
self.assertions.lock().push_back(Box::new(|_| {}));
|
|
955
|
+
self
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
pub(crate) fn then(&mut self, assert: impl FnOnce(&WorkflowActivation) + 'static) -> &mut Self {
|
|
959
|
+
self.assertions.lock().push_back(Box::new(assert));
|
|
960
|
+
self
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
#[async_trait::async_trait(?Send)]
|
|
965
|
+
impl WorkerInterceptor for ActivationAssertionsInterceptor {
|
|
966
|
+
async fn on_workflow_activation(&self, act: &WorkflowActivation) -> Result<(), anyhow::Error> {
|
|
967
|
+
self.used.store(true, Ordering::Relaxed);
|
|
968
|
+
if let Some(fun) = self.assertions.lock().pop_front() {
|
|
969
|
+
fun(act);
|
|
970
|
+
}
|
|
971
|
+
Ok(())
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
#[cfg(test)]
|
|
976
|
+
impl Drop for ActivationAssertionsInterceptor {
|
|
977
|
+
fn drop(&mut self) {
|
|
978
|
+
if !self.used.load(Ordering::Relaxed) {
|
|
979
|
+
panic!("Activation assertions interceptor was never used!")
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
#[cfg(feature = "ephemeral-server")]
|
|
985
|
+
use temporal_sdk_core::ephemeral_server::{
|
|
986
|
+
EphemeralExe, EphemeralExeVersion, TemporalDevServerConfigBuilder, default_cached_download,
|
|
987
|
+
};
|
|
988
|
+
|
|
989
|
+
#[cfg(feature = "ephemeral-server")]
|
|
990
|
+
pub(crate) fn integ_dev_server_config(
|
|
991
|
+
mut extra_args: Vec<String>,
|
|
992
|
+
) -> TemporalDevServerConfigBuilder {
|
|
993
|
+
let cli_version = if let Ok(ver_override) = env::var(CLI_VERSION_OVERRIDE_ENV_VAR) {
|
|
994
|
+
EphemeralExe::CachedDownload {
|
|
995
|
+
version: EphemeralExeVersion::Fixed(ver_override.to_owned()),
|
|
996
|
+
dest_dir: None,
|
|
997
|
+
ttl: None,
|
|
998
|
+
}
|
|
999
|
+
} else {
|
|
1000
|
+
default_cached_download()
|
|
1001
|
+
};
|
|
1002
|
+
extra_args.extend(
|
|
1003
|
+
[
|
|
1004
|
+
// TODO: Delete when temporalCLI enables it by default.
|
|
1005
|
+
"--dynamic-config-value".to_string(),
|
|
1006
|
+
"system.enableEagerWorkflowStart=true".to_string(),
|
|
1007
|
+
"--dynamic-config-value".to_string(),
|
|
1008
|
+
"system.enableNexus=true".to_string(),
|
|
1009
|
+
"--dynamic-config-value".to_owned(),
|
|
1010
|
+
"frontend.workerVersioningWorkflowAPIs=true".to_owned(),
|
|
1011
|
+
"--dynamic-config-value".to_owned(),
|
|
1012
|
+
"frontend.workerVersioningDataAPIs=true".to_owned(),
|
|
1013
|
+
"--dynamic-config-value".to_owned(),
|
|
1014
|
+
"system.enableDeploymentVersions=true".to_owned(),
|
|
1015
|
+
"--dynamic-config-value".to_owned(),
|
|
1016
|
+
"component.nexusoperations.recordCancelRequestCompletionEvents=true".to_owned(),
|
|
1017
|
+
"--search-attribute".to_string(),
|
|
1018
|
+
format!("{SEARCH_ATTR_TXT}=Text"),
|
|
1019
|
+
"--search-attribute".to_string(),
|
|
1020
|
+
format!("{SEARCH_ATTR_INT}=Int"),
|
|
1021
|
+
]
|
|
1022
|
+
.map(Into::into),
|
|
1023
|
+
);
|
|
1024
|
+
|
|
1025
|
+
let mut config = TemporalDevServerConfigBuilder::default();
|
|
1026
|
+
config.exe(cli_version).extra_args(extra_args);
|
|
1027
|
+
config
|
|
1028
|
+
}
|