@temporalio/core-bridge 1.9.2 → 1.10.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 +754 -473
- package/Cargo.toml +3 -3
- package/lib/index.d.ts +33 -2
- package/lib/index.js.map +1 -1
- 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/scripts/build.js +4 -3
- package/sdk-core/.cargo/config.toml +2 -4
- package/sdk-core/.github/workflows/heavy.yml +1 -1
- package/sdk-core/.github/workflows/per-pr.yml +6 -4
- package/sdk-core/Cargo.toml +10 -3
- package/sdk-core/README.md +4 -6
- package/sdk-core/client/Cargo.toml +13 -5
- package/sdk-core/client/src/lib.rs +123 -34
- package/sdk-core/client/src/metrics.rs +70 -18
- package/sdk-core/client/src/proxy.rs +85 -0
- package/sdk-core/client/src/raw.rs +67 -5
- package/sdk-core/client/src/worker_registry/mod.rs +5 -3
- package/sdk-core/client/src/workflow_handle/mod.rs +3 -1
- package/sdk-core/core/Cargo.toml +31 -37
- package/sdk-core/core/src/abstractions/take_cell.rs +3 -3
- package/sdk-core/core/src/abstractions.rs +176 -108
- package/sdk-core/core/src/core_tests/activity_tasks.rs +4 -13
- package/sdk-core/core/src/core_tests/determinism.rs +2 -1
- package/sdk-core/core/src/core_tests/local_activities.rs +3 -3
- package/sdk-core/core/src/core_tests/mod.rs +3 -3
- package/sdk-core/core/src/core_tests/queries.rs +42 -5
- package/sdk-core/core/src/core_tests/workers.rs +2 -3
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +115 -15
- package/sdk-core/core/src/ephemeral_server/mod.rs +109 -136
- package/sdk-core/core/src/internal_flags.rs +8 -8
- package/sdk-core/core/src/lib.rs +16 -11
- package/sdk-core/core/src/pollers/mod.rs +11 -5
- package/sdk-core/core/src/pollers/poll_buffer.rs +48 -29
- package/sdk-core/core/src/protosext/mod.rs +32 -32
- package/sdk-core/core/src/protosext/protocol_messages.rs +14 -24
- package/sdk-core/core/src/retry_logic.rs +2 -2
- package/sdk-core/core/src/telemetry/log_export.rs +10 -9
- package/sdk-core/core/src/telemetry/metrics.rs +233 -330
- package/sdk-core/core/src/telemetry/mod.rs +11 -38
- package/sdk-core/core/src/telemetry/otel.rs +355 -0
- package/sdk-core/core/src/telemetry/prometheus_server.rs +36 -23
- package/sdk-core/core/src/test_help/mod.rs +80 -59
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +6 -6
- package/sdk-core/core/src/worker/activities/local_activities.rs +46 -43
- package/sdk-core/core/src/worker/activities.rs +45 -46
- package/sdk-core/core/src/worker/client/mocks.rs +8 -7
- package/sdk-core/core/src/worker/client.rs +40 -39
- package/sdk-core/core/src/worker/mod.rs +72 -42
- package/sdk-core/core/src/worker/slot_provider.rs +28 -28
- package/sdk-core/core/src/worker/slot_supplier.rs +1 -0
- package/sdk-core/core/src/worker/tuner/fixed_size.rs +52 -0
- package/sdk-core/core/src/worker/tuner/resource_based.rs +561 -0
- package/sdk-core/core/src/worker/tuner.rs +122 -0
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +6 -6
- package/sdk-core/core/src/worker/workflow/history_update.rs +27 -53
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +4 -17
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -10
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +4 -11
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +17 -35
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +0 -8
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +0 -5
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +0 -5
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +0 -14
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -5
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +0 -5
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -10
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +3 -10
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +12 -8
- package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +0 -10
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +6 -13
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +27 -37
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +3 -14
- package/sdk-core/core/src/worker/workflow/managed_run.rs +84 -54
- package/sdk-core/core/src/worker/workflow/mod.rs +63 -160
- package/sdk-core/core/src/worker/workflow/run_cache.rs +22 -13
- package/sdk-core/core/src/worker/workflow/wft_extraction.rs +16 -3
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +15 -12
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +39 -78
- package/sdk-core/core-api/Cargo.toml +6 -5
- package/sdk-core/core-api/src/errors.rs +8 -0
- package/sdk-core/core-api/src/telemetry/metrics.rs +75 -4
- package/sdk-core/core-api/src/telemetry.rs +7 -1
- package/sdk-core/core-api/src/worker.rs +212 -56
- package/sdk-core/fsm/Cargo.toml +3 -0
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
- package/sdk-core/sdk/Cargo.toml +5 -7
- package/sdk-core/sdk/src/app_data.rs +3 -3
- package/sdk-core/sdk/src/lib.rs +5 -3
- package/sdk-core/sdk/src/workflow_context/options.rs +1 -1
- package/sdk-core/sdk/src/workflow_context.rs +10 -9
- package/sdk-core/sdk/src/workflow_future.rs +1 -1
- package/sdk-core/sdk-core-protos/Cargo.toml +8 -6
- package/sdk-core/sdk-core-protos/build.rs +1 -10
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +3 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/ci.yml +26 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +42 -20
- package/sdk-core/sdk-core-protos/protos/api_upstream/README.md +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/api-linter.yaml +36 -26
- package/sdk-core/sdk-core-protos/protos/api_upstream/buf.lock +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/struct.proto +95 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +9632 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +7337 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/payload_description.txt +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +45 -11
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +22 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/command_type.proto +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/common.proto +44 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +18 -3
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +20 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +30 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/update.proto +7 -8
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/workflow.proto +23 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/errordetails/v1/message.proto +20 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +25 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +141 -15
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +12 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +193 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +73 -6
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +46 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/schedule/v1/message.proto +4 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +2 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +116 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +134 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +274 -29
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +57 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +10 -12
- package/sdk-core/sdk-core-protos/src/history_builder.rs +1 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +54 -51
- package/sdk-core/sdk-core-protos/src/task_token.rs +11 -2
- package/sdk-core/test-utils/Cargo.toml +7 -4
- package/sdk-core/test-utils/src/histfetch.rs +1 -1
- package/sdk-core/test-utils/src/lib.rs +44 -62
- package/sdk-core/tests/fuzzy_workflow.rs +5 -2
- package/sdk-core/tests/heavy_tests.rs +114 -17
- package/sdk-core/tests/integ_tests/activity_functions.rs +1 -1
- package/sdk-core/tests/integ_tests/client_tests.rs +2 -2
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +38 -26
- package/sdk-core/tests/integ_tests/metrics_tests.rs +126 -17
- package/sdk-core/tests/integ_tests/polling_tests.rs +118 -2
- package/sdk-core/tests/integ_tests/update_tests.rs +3 -5
- package/sdk-core/tests/integ_tests/visibility_tests.rs +3 -3
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +3 -3
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +5 -4
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -2
- package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +6 -10
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +9 -7
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +14 -9
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +6 -13
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +9 -6
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +5 -5
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests.rs +115 -11
- package/sdk-core/tests/main.rs +2 -2
- package/src/conversions.rs +57 -0
- package/src/lib.rs +1 -0
- package/src/runtime.rs +51 -35
- package/ts/index.ts +67 -3
- package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +0 -117
- package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +0 -24
- package/sdk-core/sdk/src/payload_converter.rs +0 -11
- package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/Dockerfile +0 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/docker-compose.yml +0 -15
- package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/pipeline.yml +0 -10
- package/sdk-core/test-utils/src/wf_input_saver.rs +0 -50
- package/sdk-core/tests/wf_input_replay.rs +0 -32
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
use futures::{future::join_all, sink, stream::FuturesUnordered, StreamExt};
|
|
2
|
-
use std::
|
|
2
|
+
use std::{
|
|
3
|
+
sync::Arc,
|
|
4
|
+
time::{Duration, Instant},
|
|
5
|
+
};
|
|
3
6
|
use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowOptions};
|
|
4
7
|
use temporal_sdk::{ActContext, ActivityOptions, WfContext, WorkflowResult};
|
|
5
|
-
use
|
|
6
|
-
|
|
8
|
+
use temporal_sdk_core::{ResourceBasedSlots, ResourceBasedTuner, ResourceSlotOptions};
|
|
9
|
+
use temporal_sdk_core_protos::{
|
|
10
|
+
coresdk::{workflow_commands::ActivityCancellationType, AsJsonPayloadExt},
|
|
11
|
+
temporal::api::enums::v1::WorkflowIdReusePolicy,
|
|
7
12
|
};
|
|
8
13
|
use temporal_sdk_core_test_utils::{workflows::la_problem_workflow, CoreWfStarter};
|
|
9
14
|
|
|
@@ -15,10 +20,11 @@ async fn activity_load() {
|
|
|
15
20
|
|
|
16
21
|
let mut starter = CoreWfStarter::new("activity_load");
|
|
17
22
|
starter
|
|
18
|
-
.
|
|
23
|
+
.worker_config
|
|
24
|
+
.max_outstanding_workflow_tasks(CONCURRENCY)
|
|
19
25
|
.max_cached_workflows(CONCURRENCY)
|
|
20
|
-
.
|
|
21
|
-
.
|
|
26
|
+
.max_concurrent_at_polls(10_usize)
|
|
27
|
+
.max_outstanding_activities(CONCURRENCY);
|
|
22
28
|
let mut worker = starter.worker().await;
|
|
23
29
|
|
|
24
30
|
let activity_id = "act-1";
|
|
@@ -78,24 +84,111 @@ async fn activity_load() {
|
|
|
78
84
|
dbg!(running.elapsed());
|
|
79
85
|
}
|
|
80
86
|
|
|
87
|
+
#[tokio::test]
|
|
88
|
+
async fn chunky_activities_resource_based() {
|
|
89
|
+
const WORKFLOWS: usize = 100;
|
|
90
|
+
|
|
91
|
+
let mut starter = CoreWfStarter::new("chunky_activities_resource_based");
|
|
92
|
+
starter
|
|
93
|
+
.worker_config
|
|
94
|
+
.clear_max_outstanding_opts()
|
|
95
|
+
.max_concurrent_wft_polls(10_usize)
|
|
96
|
+
.max_concurrent_at_polls(10_usize);
|
|
97
|
+
let mut tuner = ResourceBasedTuner::new(ResourceBasedSlots::new(0.7, 0.7));
|
|
98
|
+
tuner
|
|
99
|
+
.with_workflow_slots_options(ResourceSlotOptions::new(
|
|
100
|
+
25,
|
|
101
|
+
WORKFLOWS,
|
|
102
|
+
Duration::from_millis(0),
|
|
103
|
+
))
|
|
104
|
+
.with_activity_slots_options(ResourceSlotOptions::new(5, 1000, Duration::from_millis(50)));
|
|
105
|
+
starter.worker_config.tuner(Arc::new(tuner));
|
|
106
|
+
let mut worker = starter.worker().await;
|
|
107
|
+
|
|
108
|
+
let activity_id = "act-1";
|
|
109
|
+
let activity_timeout = Duration::from_secs(30);
|
|
110
|
+
|
|
111
|
+
let wf_fn = move |ctx: WfContext| {
|
|
112
|
+
let payload = "yo".as_json_payload().unwrap();
|
|
113
|
+
async move {
|
|
114
|
+
let activity = ActivityOptions {
|
|
115
|
+
activity_id: Some(activity_id.to_string()),
|
|
116
|
+
activity_type: "test_activity".to_string(),
|
|
117
|
+
input: payload.clone(),
|
|
118
|
+
start_to_close_timeout: Some(activity_timeout),
|
|
119
|
+
..Default::default()
|
|
120
|
+
};
|
|
121
|
+
let res = ctx.activity(activity).await.unwrap_ok_payload();
|
|
122
|
+
assert_eq!(res.data, payload.data);
|
|
123
|
+
Ok(().into())
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
let starting = Instant::now();
|
|
128
|
+
let wf_type = "chunky_activity_wf";
|
|
129
|
+
worker.register_wf(wf_type.to_owned(), wf_fn);
|
|
130
|
+
worker.register_activity(
|
|
131
|
+
"test_activity",
|
|
132
|
+
|_ctx: ActContext, echo: String| async move {
|
|
133
|
+
tokio::task::spawn_blocking(move || {
|
|
134
|
+
// Allocate a gig and then do some CPU stuff on it
|
|
135
|
+
let mut mem = vec![0_u8; 1000 * 1024 * 1024];
|
|
136
|
+
for _ in 1..10 {
|
|
137
|
+
for i in 0..mem.len() {
|
|
138
|
+
mem[i] &= mem[mem.len() - 1 - i]
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
Ok(echo)
|
|
142
|
+
})
|
|
143
|
+
.await?
|
|
144
|
+
},
|
|
145
|
+
);
|
|
146
|
+
join_all((0..WORKFLOWS).map(|i| {
|
|
147
|
+
let worker = &worker;
|
|
148
|
+
let wf_id = format!("chunk_activity_{i}");
|
|
149
|
+
async move {
|
|
150
|
+
worker
|
|
151
|
+
.submit_wf(
|
|
152
|
+
wf_id,
|
|
153
|
+
wf_type.to_owned(),
|
|
154
|
+
vec![],
|
|
155
|
+
WorkflowOptions {
|
|
156
|
+
id_reuse_policy: WorkflowIdReusePolicy::TerminateIfRunning,
|
|
157
|
+
..Default::default()
|
|
158
|
+
},
|
|
159
|
+
)
|
|
160
|
+
.await
|
|
161
|
+
.unwrap();
|
|
162
|
+
}
|
|
163
|
+
}))
|
|
164
|
+
.await;
|
|
165
|
+
dbg!(starting.elapsed());
|
|
166
|
+
|
|
167
|
+
let running = Instant::now();
|
|
168
|
+
|
|
169
|
+
worker.run_until_done().await.unwrap();
|
|
170
|
+
dbg!(running.elapsed());
|
|
171
|
+
}
|
|
172
|
+
|
|
81
173
|
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
|
|
82
174
|
async fn workflow_load() {
|
|
83
175
|
const SIGNAME: &str = "signame";
|
|
84
|
-
let num_workflows =
|
|
176
|
+
let num_workflows = 500;
|
|
85
177
|
let wf_name = "workflow_load";
|
|
86
178
|
let mut starter = CoreWfStarter::new("workflow_load");
|
|
87
179
|
starter
|
|
88
|
-
.
|
|
89
|
-
.
|
|
90
|
-
.
|
|
91
|
-
.
|
|
180
|
+
.worker_config
|
|
181
|
+
.max_outstanding_workflow_tasks(5_usize)
|
|
182
|
+
.max_cached_workflows(200_usize)
|
|
183
|
+
.max_concurrent_at_polls(10_usize)
|
|
184
|
+
.max_outstanding_activities(100_usize);
|
|
92
185
|
let mut worker = starter.worker().await;
|
|
93
186
|
worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
|
|
94
187
|
let sigchan = ctx.make_signal_channel(SIGNAME).map(Ok);
|
|
95
188
|
let drained_fut = sigchan.forward(sink::drain());
|
|
96
189
|
|
|
97
190
|
let real_stuff = async move {
|
|
98
|
-
for _ in 0..
|
|
191
|
+
for _ in 0..5 {
|
|
99
192
|
ctx.activity(ActivityOptions {
|
|
100
193
|
activity_type: "echo_activity".to_string(),
|
|
101
194
|
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
@@ -162,8 +255,10 @@ async fn workflow_load() {
|
|
|
162
255
|
async fn evict_while_la_running_no_interference() {
|
|
163
256
|
let wf_name = "evict_while_la_running_no_interference";
|
|
164
257
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
165
|
-
starter
|
|
166
|
-
|
|
258
|
+
starter
|
|
259
|
+
.worker_config
|
|
260
|
+
.max_outstanding_local_activities(20_usize)
|
|
261
|
+
.max_cached_workflows(20_usize);
|
|
167
262
|
// Though it doesn't make sense to set wft higher than cached workflows, leaving this commented
|
|
168
263
|
// introduces more instability that can be useful in the test.
|
|
169
264
|
// starter.max_wft(20);
|
|
@@ -228,9 +323,11 @@ pub async fn many_parallel_timers_longhist(ctx: WfContext) -> WorkflowResult<()>
|
|
|
228
323
|
async fn can_paginate_long_history() {
|
|
229
324
|
let wf_name = "can_paginate_long_history";
|
|
230
325
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
231
|
-
starter
|
|
232
|
-
|
|
233
|
-
|
|
326
|
+
starter
|
|
327
|
+
.worker_config
|
|
328
|
+
.no_remote_activities(true)
|
|
329
|
+
// Do not use sticky queues so we are forced to paginate once history gets long
|
|
330
|
+
.max_cached_workflows(0_usize);
|
|
234
331
|
|
|
235
332
|
let mut worker = starter.worker().await;
|
|
236
333
|
worker.register_wf(wf_name.to_owned(), many_parallel_timers_longhist);
|
|
@@ -17,7 +17,7 @@ async fn can_use_retry_client() {
|
|
|
17
17
|
#[tokio::test]
|
|
18
18
|
async fn can_use_retry_raw_client() {
|
|
19
19
|
let opts = get_integ_server_options();
|
|
20
|
-
let raw_client = opts.connect_no_namespace(None
|
|
20
|
+
let raw_client = opts.connect_no_namespace(None).await.unwrap();
|
|
21
21
|
let mut retry_client = RetryClient::new(raw_client, opts.retry_config);
|
|
22
22
|
retry_client
|
|
23
23
|
.describe_namespace(DescribeNamespaceRequest {
|
|
@@ -31,6 +31,6 @@ async fn can_use_retry_raw_client() {
|
|
|
31
31
|
#[tokio::test]
|
|
32
32
|
async fn calls_get_system_info() {
|
|
33
33
|
let opts = get_integ_server_options();
|
|
34
|
-
let raw_client = opts.connect_no_namespace(None
|
|
34
|
+
let raw_client = opts.connect_no_namespace(None).await.unwrap();
|
|
35
35
|
assert!(raw_client.get_client().capabilities().is_some());
|
|
36
36
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
use futures::stream;
|
|
2
|
+
use futures::TryStreamExt;
|
|
1
3
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
2
4
|
use temporal_client::{ClientOptionsBuilder, TestService, WorkflowService};
|
|
3
5
|
use temporal_sdk_core::ephemeral_server::{
|
|
4
6
|
EphemeralExe, EphemeralExeVersion, EphemeralServer, TemporalDevServerConfigBuilder,
|
|
5
|
-
|
|
7
|
+
TestServerConfigBuilder,
|
|
6
8
|
};
|
|
7
9
|
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::DescribeNamespaceRequest;
|
|
8
10
|
use temporal_sdk_core_test_utils::{default_cached_download, NAMESPACE};
|
|
@@ -16,7 +18,12 @@ async fn temporal_cli_default() {
|
|
|
16
18
|
.unwrap();
|
|
17
19
|
let mut server = config.start_server().await.unwrap();
|
|
18
20
|
assert_ephemeral_server(&server).await;
|
|
21
|
+
|
|
22
|
+
// Make sure process is there on start and not there after shutdown
|
|
23
|
+
let pid = sysinfo::Pid::from_u32(server.child_process_id().unwrap());
|
|
24
|
+
assert!(sysinfo::System::new_all().process(pid).is_some());
|
|
19
25
|
server.shutdown().await.unwrap();
|
|
26
|
+
assert!(sysinfo::System::new_all().process(pid).is_none());
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
#[tokio::test]
|
|
@@ -31,32 +38,10 @@ async fn temporal_cli_fixed() {
|
|
|
31
38
|
}
|
|
32
39
|
|
|
33
40
|
#[tokio::test]
|
|
34
|
-
async fn
|
|
35
|
-
let config = TemporaliteConfigBuilder::default()
|
|
36
|
-
.exe(default_cached_download())
|
|
37
|
-
.build()
|
|
38
|
-
.unwrap();
|
|
39
|
-
let mut server = config.start_server().await.unwrap();
|
|
40
|
-
assert_ephemeral_server(&server).await;
|
|
41
|
-
server.shutdown().await.unwrap();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
#[tokio::test]
|
|
45
|
-
async fn temporalite_fixed() {
|
|
46
|
-
let config = TemporaliteConfigBuilder::default()
|
|
47
|
-
.exe(fixed_cached_download("v0.2.0"))
|
|
48
|
-
.build()
|
|
49
|
-
.unwrap();
|
|
50
|
-
let mut server = config.start_server().await.unwrap();
|
|
51
|
-
assert_ephemeral_server(&server).await;
|
|
52
|
-
server.shutdown().await.unwrap();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
#[tokio::test]
|
|
56
|
-
async fn temporalite_shutdown_port_reuse() {
|
|
41
|
+
async fn temporal_cli_shutdown_port_reuse() {
|
|
57
42
|
// Start, test shutdown, do again immediately on same port to ensure we can
|
|
58
43
|
// reuse after shutdown
|
|
59
|
-
let config =
|
|
44
|
+
let config = TemporalDevServerConfigBuilder::default()
|
|
60
45
|
.exe(default_cached_download())
|
|
61
46
|
.port(Some(10123))
|
|
62
47
|
.build()
|
|
@@ -69,6 +54,33 @@ async fn temporalite_shutdown_port_reuse() {
|
|
|
69
54
|
server.shutdown().await.unwrap();
|
|
70
55
|
}
|
|
71
56
|
|
|
57
|
+
// This test will fail on Linux until https://github.com/temporalio/cli/pull/564
|
|
58
|
+
// gets released (presumably in 0.12.1). To test locally, build CLI manually
|
|
59
|
+
// and use that specific binary instead:
|
|
60
|
+
// ```
|
|
61
|
+
// .exe(EphemeralExe::ExistingPath(
|
|
62
|
+
// "/usr/local/bin/temporal".to_string(),
|
|
63
|
+
// ))
|
|
64
|
+
// ```
|
|
65
|
+
#[tokio::test]
|
|
66
|
+
#[ignore]
|
|
67
|
+
async fn temporal_cli_concurrent_starts() -> Result<(), Box<dyn std::error::Error>> {
|
|
68
|
+
stream::iter((0..80).map(|_| {
|
|
69
|
+
TemporalDevServerConfigBuilder::default()
|
|
70
|
+
.exe(default_cached_download())
|
|
71
|
+
.build()
|
|
72
|
+
.map_err(anyhow::Error::from)
|
|
73
|
+
}))
|
|
74
|
+
.try_for_each_concurrent(8, |config| async move {
|
|
75
|
+
let mut server = config.start_server().await?;
|
|
76
|
+
server.shutdown().await?;
|
|
77
|
+
Ok(())
|
|
78
|
+
})
|
|
79
|
+
.await?;
|
|
80
|
+
|
|
81
|
+
Ok(())
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
#[tokio::test]
|
|
73
85
|
async fn test_server_default() {
|
|
74
86
|
let config = TestServerConfigBuilder::default()
|
|
@@ -124,7 +136,7 @@ async fn assert_ephemeral_server(server: &EphemeralServer) {
|
|
|
124
136
|
.client_version("0.1.0".to_string())
|
|
125
137
|
.build()
|
|
126
138
|
.unwrap()
|
|
127
|
-
.connect_no_namespace(None
|
|
139
|
+
.connect_no_namespace(None)
|
|
128
140
|
.await
|
|
129
141
|
.unwrap();
|
|
130
142
|
let resp = client
|
|
@@ -23,8 +23,10 @@ use temporal_sdk_core_protos::{
|
|
|
23
23
|
ActivityTaskCompletion,
|
|
24
24
|
},
|
|
25
25
|
temporal::api::{
|
|
26
|
-
enums::v1::WorkflowIdReusePolicy,
|
|
27
|
-
|
|
26
|
+
enums::v1::WorkflowIdReusePolicy,
|
|
27
|
+
failure::v1::Failure,
|
|
28
|
+
query::v1::WorkflowQuery,
|
|
29
|
+
workflowservice::v1::{DescribeNamespaceRequest, ListNamespacesRequest},
|
|
28
30
|
},
|
|
29
31
|
};
|
|
30
32
|
use temporal_sdk_core_test_utils::{
|
|
@@ -34,24 +36,30 @@ use tokio::{join, sync::Barrier, task::AbortHandle};
|
|
|
34
36
|
|
|
35
37
|
static ANY_PORT: &str = "127.0.0.1:0";
|
|
36
38
|
|
|
37
|
-
async fn get_text(endpoint: String) -> String {
|
|
39
|
+
pub(crate) async fn get_text(endpoint: String) -> String {
|
|
38
40
|
reqwest::get(endpoint).await.unwrap().text().await.unwrap()
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
struct AbortOnDrop {
|
|
43
|
+
pub(crate) struct AbortOnDrop {
|
|
42
44
|
ah: AbortHandle,
|
|
43
45
|
}
|
|
46
|
+
|
|
44
47
|
impl Drop for AbortOnDrop {
|
|
45
48
|
fn drop(&mut self) {
|
|
46
49
|
self.ah.abort();
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
pub(crate) fn prom_metrics(
|
|
54
|
+
use_seconds: bool,
|
|
55
|
+
show_units: bool,
|
|
56
|
+
) -> (TelemetryOptions, SocketAddr, AbortOnDrop) {
|
|
51
57
|
let mut telemopts = get_integ_telem_options();
|
|
52
58
|
let prom_info = start_prometheus_metric_exporter(
|
|
53
59
|
PrometheusExporterOptionsBuilder::default()
|
|
54
60
|
.socket_addr(ANY_PORT.parse().unwrap())
|
|
61
|
+
.use_seconds_for_durations(use_seconds)
|
|
62
|
+
.unit_suffix(show_units)
|
|
55
63
|
.build()
|
|
56
64
|
.unwrap(),
|
|
57
65
|
)
|
|
@@ -66,13 +74,14 @@ fn prom_metrics() -> (TelemetryOptions, SocketAddr, AbortOnDrop) {
|
|
|
66
74
|
)
|
|
67
75
|
}
|
|
68
76
|
|
|
77
|
+
#[rstest::rstest]
|
|
69
78
|
#[tokio::test]
|
|
70
|
-
async fn prometheus_metrics_exported() {
|
|
71
|
-
let (telemopts, addr, _aborter) = prom_metrics();
|
|
79
|
+
async fn prometheus_metrics_exported(#[values(true, false)] use_seconds_latency: bool) {
|
|
80
|
+
let (telemopts, addr, _aborter) = prom_metrics(use_seconds_latency, false);
|
|
72
81
|
let rt = CoreRuntime::new_assume_tokio(telemopts).unwrap();
|
|
73
82
|
let opts = get_integ_server_options();
|
|
74
83
|
let mut raw_client = opts
|
|
75
|
-
.connect_no_namespace(rt.telemetry().get_temporal_metric_meter()
|
|
84
|
+
.connect_no_namespace(rt.telemetry().get_temporal_metric_meter())
|
|
76
85
|
.await
|
|
77
86
|
.unwrap();
|
|
78
87
|
assert!(raw_client.get_client().capabilities().is_some());
|
|
@@ -89,6 +98,17 @@ async fn prometheus_metrics_exported() {
|
|
|
89
98
|
assert!(body.contains(
|
|
90
99
|
"temporal_request_latency_count{operation=\"GetSystemInfo\",service_name=\"temporal-core-sdk\"} 1"
|
|
91
100
|
));
|
|
101
|
+
if use_seconds_latency {
|
|
102
|
+
assert!(body.contains(
|
|
103
|
+
"temporal_request_latency_bucket{\
|
|
104
|
+
operation=\"GetSystemInfo\",service_name=\"temporal-core-sdk\",le=\"0.05\"}"
|
|
105
|
+
));
|
|
106
|
+
} else {
|
|
107
|
+
assert!(body.contains(
|
|
108
|
+
"temporal_request_latency_bucket{\
|
|
109
|
+
operation=\"GetSystemInfo\",service_name=\"temporal-core-sdk\",le=\"50\"}"
|
|
110
|
+
));
|
|
111
|
+
}
|
|
92
112
|
// Verify counter names are appropriate (don't end w/ '_total')
|
|
93
113
|
assert!(body.contains("temporal_request{"));
|
|
94
114
|
// Verify non-temporal metrics meter does not prefix
|
|
@@ -106,7 +126,7 @@ async fn prometheus_metrics_exported() {
|
|
|
106
126
|
|
|
107
127
|
#[tokio::test]
|
|
108
128
|
async fn one_slot_worker_reports_available_slot() {
|
|
109
|
-
let (telemopts, addr, _aborter) = prom_metrics();
|
|
129
|
+
let (telemopts, addr, _aborter) = prom_metrics(false, false);
|
|
110
130
|
let tq = "one_slot_worker_tq";
|
|
111
131
|
let rt = CoreRuntime::new_assume_tokio(telemopts).unwrap();
|
|
112
132
|
|
|
@@ -125,7 +145,7 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
125
145
|
|
|
126
146
|
let client = Arc::new(
|
|
127
147
|
get_integ_server_options()
|
|
128
|
-
.connect(worker_cfg.namespace.clone(), None
|
|
148
|
+
.connect(worker_cfg.namespace.clone(), None)
|
|
129
149
|
.await
|
|
130
150
|
.expect("Must connect"),
|
|
131
151
|
);
|
|
@@ -235,8 +255,7 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
235
255
|
|
|
236
256
|
wf_task_barr.wait().await;
|
|
237
257
|
|
|
238
|
-
// At this point the workflow task is outstanding
|
|
239
|
-
// the activities haven't started, so there should still be 1 each.
|
|
258
|
+
// At this point the workflow task is outstanding and the activities haven't started
|
|
240
259
|
let body = get_text(format!("http://{addr}/metrics")).await;
|
|
241
260
|
assert!(body.contains(&format!(
|
|
242
261
|
"temporal_worker_task_slots_available{{namespace=\"{NAMESPACE}\",\
|
|
@@ -253,8 +272,23 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
253
272
|
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
254
273
|
worker_type=\"LocalActivityWorker\"}} 1"
|
|
255
274
|
)));
|
|
275
|
+
assert!(body.contains(&format!(
|
|
276
|
+
"temporal_worker_task_slots_used{{namespace=\"{NAMESPACE}\",\
|
|
277
|
+
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
278
|
+
worker_type=\"WorkflowWorker\"}} 1"
|
|
279
|
+
)));
|
|
280
|
+
assert!(body.contains(&format!(
|
|
281
|
+
"temporal_worker_task_slots_used{{namespace=\"{NAMESPACE}\",\
|
|
282
|
+
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
283
|
+
worker_type=\"ActivityWorker\"}} 0"
|
|
284
|
+
)));
|
|
285
|
+
assert!(body.contains(&format!(
|
|
286
|
+
"temporal_worker_task_slots_used{{namespace=\"{NAMESPACE}\",\
|
|
287
|
+
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
288
|
+
worker_type=\"LocalActivityWorker\"}} 0"
|
|
289
|
+
)));
|
|
256
290
|
|
|
257
|
-
// Now we allow the complete to proceed. Once it goes through, there should be
|
|
291
|
+
// Now we allow the complete to proceed. Once it goes through, there should be 2 WFT slot
|
|
258
292
|
// open but 0 activity slots
|
|
259
293
|
wf_task_barr.wait().await;
|
|
260
294
|
wf_task_barr.wait().await;
|
|
@@ -271,6 +305,11 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
271
305
|
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
272
306
|
worker_type=\"ActivityWorker\"}} 0"
|
|
273
307
|
)));
|
|
308
|
+
assert!(body.contains(&format!(
|
|
309
|
+
"temporal_worker_task_slots_used{{namespace=\"{NAMESPACE}\",\
|
|
310
|
+
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
311
|
+
worker_type=\"ActivityWorker\"}} 1"
|
|
312
|
+
)));
|
|
274
313
|
|
|
275
314
|
// Now complete the activity and watch it go up
|
|
276
315
|
act_task_barr.wait().await;
|
|
@@ -292,6 +331,11 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
292
331
|
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
293
332
|
worker_type=\"LocalActivityWorker\"}} 0"
|
|
294
333
|
)));
|
|
334
|
+
assert!(body.contains(&format!(
|
|
335
|
+
"temporal_worker_task_slots_used{{namespace=\"{NAMESPACE}\",\
|
|
336
|
+
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
337
|
+
worker_type=\"LocalActivityWorker\"}} 1"
|
|
338
|
+
)));
|
|
295
339
|
// When completion is done, we have 1 again
|
|
296
340
|
act_task_barr.wait().await;
|
|
297
341
|
act_task_barr.wait().await;
|
|
@@ -318,12 +362,12 @@ async fn query_of_closed_workflow_doesnt_tick_terminal_metric(
|
|
|
318
362
|
)]
|
|
319
363
|
completion: workflow_command::Variant,
|
|
320
364
|
) {
|
|
321
|
-
let (telemopts, addr, _aborter) = prom_metrics();
|
|
365
|
+
let (telemopts, addr, _aborter) = prom_metrics(false, false);
|
|
322
366
|
let rt = CoreRuntime::new_assume_tokio(telemopts).unwrap();
|
|
323
367
|
let mut starter =
|
|
324
368
|
CoreWfStarter::new_with_runtime("query_of_closed_workflow_doesnt_tick_terminal_metric", rt);
|
|
325
369
|
// Disable cache to ensure replay happens completely
|
|
326
|
-
starter.max_cached_workflows(
|
|
370
|
+
starter.worker_config.max_cached_workflows(0_usize);
|
|
327
371
|
let worker = starter.get_worker().await;
|
|
328
372
|
let run_id = starter.start_wf().await;
|
|
329
373
|
let task = worker.poll_workflow_activation().await.unwrap();
|
|
@@ -447,13 +491,13 @@ fn runtime_new() {
|
|
|
447
491
|
.unwrap();
|
|
448
492
|
let handle = rt.tokio_handle();
|
|
449
493
|
let _rt = handle.enter();
|
|
450
|
-
let (telemopts, addr, _aborter) = prom_metrics();
|
|
494
|
+
let (telemopts, addr, _aborter) = prom_metrics(false, false);
|
|
451
495
|
rt.telemetry_mut()
|
|
452
496
|
.attach_late_init_metrics(telemopts.metrics.unwrap());
|
|
453
497
|
let opts = get_integ_server_options();
|
|
454
498
|
handle.block_on(async {
|
|
455
499
|
let mut raw_client = opts
|
|
456
|
-
.connect_no_namespace(rt.telemetry().get_temporal_metric_meter()
|
|
500
|
+
.connect_no_namespace(rt.telemetry().get_temporal_metric_meter())
|
|
457
501
|
.await
|
|
458
502
|
.unwrap();
|
|
459
503
|
assert!(raw_client.get_client().capabilities().is_some());
|
|
@@ -465,3 +509,68 @@ fn runtime_new() {
|
|
|
465
509
|
assert!(body.contains("temporal_request"));
|
|
466
510
|
});
|
|
467
511
|
}
|
|
512
|
+
|
|
513
|
+
#[rstest::rstest]
|
|
514
|
+
#[tokio::test]
|
|
515
|
+
async fn latency_metrics(
|
|
516
|
+
#[values(true, false)] use_seconds_latency: bool,
|
|
517
|
+
#[values(true, false)] show_units: bool,
|
|
518
|
+
) {
|
|
519
|
+
let (telemopts, addr, _aborter) = prom_metrics(use_seconds_latency, show_units);
|
|
520
|
+
let rt = CoreRuntime::new_assume_tokio(telemopts).unwrap();
|
|
521
|
+
let mut starter = CoreWfStarter::new_with_runtime("latency_metrics", rt);
|
|
522
|
+
let worker = starter.get_worker().await;
|
|
523
|
+
starter.start_wf().await;
|
|
524
|
+
// Immediately finish workflow
|
|
525
|
+
let task = worker.poll_workflow_activation().await.unwrap();
|
|
526
|
+
worker
|
|
527
|
+
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
528
|
+
task.run_id,
|
|
529
|
+
CompleteWorkflowExecution { result: None }.into(),
|
|
530
|
+
))
|
|
531
|
+
.await
|
|
532
|
+
.unwrap();
|
|
533
|
+
|
|
534
|
+
let body = get_text(format!("http://{addr}/metrics")).await;
|
|
535
|
+
let matching_line = body
|
|
536
|
+
.lines()
|
|
537
|
+
.find(|l| l.starts_with("temporal_workflow_endtoend_latency"))
|
|
538
|
+
.unwrap();
|
|
539
|
+
|
|
540
|
+
if use_seconds_latency {
|
|
541
|
+
if show_units {
|
|
542
|
+
assert!(matching_line.contains("temporal_workflow_endtoend_latency_seconds"));
|
|
543
|
+
}
|
|
544
|
+
assert!(matching_line.contains("le=\"0.1\""));
|
|
545
|
+
} else {
|
|
546
|
+
if show_units {
|
|
547
|
+
assert!(matching_line.contains("temporal_workflow_endtoend_latency_milliseconds"));
|
|
548
|
+
}
|
|
549
|
+
assert!(matching_line.contains("le=\"100\""));
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
#[tokio::test]
|
|
554
|
+
async fn request_fail_codes() {
|
|
555
|
+
let (telemopts, addr, _aborter) = prom_metrics(false, false);
|
|
556
|
+
let rt = CoreRuntime::new_assume_tokio(telemopts).unwrap();
|
|
557
|
+
let opts = get_integ_server_options();
|
|
558
|
+
let mut client = opts
|
|
559
|
+
.connect(NAMESPACE, rt.telemetry().get_temporal_metric_meter())
|
|
560
|
+
.await
|
|
561
|
+
.unwrap();
|
|
562
|
+
|
|
563
|
+
// Describe namespace w/ invalid argument (unset namespace field)
|
|
564
|
+
WorkflowService::describe_namespace(&mut client, DescribeNamespaceRequest::default())
|
|
565
|
+
.await
|
|
566
|
+
.unwrap_err();
|
|
567
|
+
|
|
568
|
+
let body = get_text(format!("http://{addr}/metrics")).await;
|
|
569
|
+
let matching_line = body
|
|
570
|
+
.lines()
|
|
571
|
+
.find(|l| l.starts_with("temporal_request_failure"))
|
|
572
|
+
.unwrap();
|
|
573
|
+
assert!(matching_line.contains("operation=\"DescribeNamespace\""));
|
|
574
|
+
assert!(matching_line.contains("status_code=\"INVALID_ARGUMENT\""));
|
|
575
|
+
assert!(matching_line.contains("} 1"));
|
|
576
|
+
}
|