@temporalio/core-bridge 1.14.2-canary-release-testing.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +794 -650
- package/bridge-macros/src/derive_tryintojs.rs +40 -0
- package/lib/native.d.ts +24 -3
- package/package.json +4 -4
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.github/workflows/per-pr.yml +6 -6
- package/sdk-core/AGENTS.md +42 -31
- package/sdk-core/Cargo.toml +4 -1
- package/sdk-core/README.md +19 -13
- package/sdk-core/crates/client/Cargo.toml +4 -0
- package/sdk-core/crates/client/README.md +139 -0
- package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
- package/sdk-core/crates/client/src/callback_based.rs +7 -0
- package/sdk-core/crates/client/src/errors.rs +294 -0
- package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +370 -159
- package/sdk-core/crates/client/src/lib.rs +920 -1326
- package/sdk-core/crates/client/src/metrics.rs +24 -33
- package/sdk-core/crates/client/src/options_structs.rs +457 -0
- package/sdk-core/crates/client/src/replaceable.rs +5 -4
- package/sdk-core/crates/client/src/request_extensions.rs +8 -9
- package/sdk-core/crates/client/src/retry.rs +99 -54
- package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +104 -29
- package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
- package/sdk-core/crates/common/Cargo.toml +62 -3
- package/sdk-core/crates/common/build.rs +742 -12
- package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
- package/sdk-core/crates/common/protos/api_upstream/.github/workflows/create-release.yml +0 -5
- package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
- package/sdk-core/crates/common/protos/api_upstream/README.md +8 -0
- package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
- package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +3329 -2647
- package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +2734 -708
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/activity/v1/message.proto +155 -3
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/common/v1/message.proto +8 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +27 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/activity.proto +81 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/event_type.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +15 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +63 -15
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/errordetails/v1/message.proto +8 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +111 -17
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +21 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +20 -1
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +4 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -0
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/worker/v1/message.proto +4 -7
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflow/v1/message.proto +80 -22
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +347 -23
- package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +242 -43
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/core_interface.proto +15 -0
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +9 -2
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +8 -0
- package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +22 -5
- package/sdk-core/crates/common/src/activity_definition.rs +20 -0
- package/sdk-core/crates/common/src/data_converters.rs +770 -0
- package/sdk-core/crates/common/src/envconfig.rs +5 -0
- package/sdk-core/crates/common/src/lib.rs +15 -211
- package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
- package/sdk-core/crates/common/src/priority.rs +110 -0
- package/sdk-core/crates/common/src/protos/canned_histories.rs +19 -0
- package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
- package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
- package/sdk-core/crates/common/src/protos/mod.rs +134 -27
- package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
- package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +11 -16
- package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
- package/sdk-core/crates/common/src/telemetry/metrics.rs +272 -225
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
- package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
- package/sdk-core/crates/common/src/telemetry.rs +278 -19
- package/sdk-core/crates/common/src/worker.rs +68 -636
- package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
- package/sdk-core/crates/macros/Cargo.toml +5 -1
- package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
- package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
- package/sdk-core/crates/macros/src/lib.rs +138 -512
- package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
- package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
- package/sdk-core/crates/sdk/Cargo.toml +19 -6
- package/sdk-core/crates/sdk/README.md +415 -0
- package/sdk-core/crates/sdk/src/activities.rs +417 -0
- package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
- package/sdk-core/crates/sdk/src/lib.rs +759 -442
- package/sdk-core/crates/sdk/src/workflow_context/options.rs +64 -35
- package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
- package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
- package/sdk-core/crates/sdk/src/workflows.rs +711 -0
- package/sdk-core/crates/sdk-core/Cargo.toml +59 -65
- package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +45 -54
- package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
- package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
- package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
- package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +22 -21
- package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
- package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
- package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
- package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +647 -27
- package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +46 -41
- package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +13 -16
- package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
- package/sdk-core/crates/sdk-core/src/lib.rs +60 -123
- package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
- package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +411 -32
- package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
- package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
- package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +183 -198
- package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -281
- package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +35 -16
- package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
- package/sdk-core/crates/sdk-core/src/worker/activities/activity_heartbeat_manager.rs +1 -0
- package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
- package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
- package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +11 -5
- package/sdk-core/crates/sdk-core/src/worker/client.rs +104 -86
- package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +10 -14
- package/sdk-core/crates/sdk-core/src/worker/mod.rs +1175 -241
- package/sdk-core/crates/sdk-core/src/worker/nexus.rs +150 -23
- package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
- package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
- package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +25 -27
- package/sdk-core/crates/sdk-core/src/worker/tuner.rs +64 -44
- package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/patch_state_machine.rs +5 -8
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
- package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +28 -4
- package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +20 -41
- package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +50 -9
- package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
- package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
- package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
- package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
- package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
- package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
- package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
- package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
- package/sdk-core/crates/sdk-core/tests/common/mod.rs +281 -236
- package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
- package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +9 -14
- package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -66
- package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +306 -268
- package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
- package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +37 -38
- package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +49 -40
- package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +447 -300
- package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
- package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +157 -157
- package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
- package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -463
- package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +389 -265
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +250 -185
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -49
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +437 -327
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -58
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -30
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -251
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +110 -46
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -149
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -32
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1040
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -43
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +402 -245
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +343 -207
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +155 -140
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -113
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -44
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -48
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -56
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +365 -242
- package/sdk-core/crates/sdk-core/tests/main.rs +22 -16
- package/sdk-core/crates/sdk-core/tests/manual_tests.rs +233 -187
- package/sdk-core/crates/sdk-core/tests/runner.rs +4 -6
- package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +73 -27
- package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
- package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
- package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
- package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +8 -1
- package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +37 -26
- package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +180 -87
- package/sdk-core/crates/sdk-core-c-bridge/src/lib.rs +89 -5
- package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +10 -16
- package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +59 -67
- package/sdk-core/crates/sdk-core-c-bridge/src/testing.rs +10 -10
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +57 -22
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +108 -12
- package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +9 -52
- package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +74 -91
- package/sdk-core/rustfmt.toml +2 -1
- package/src/client.rs +206 -289
- package/src/helpers/try_into_js.rs +88 -2
- package/src/metrics.rs +277 -35
- package/src/runtime.rs +94 -45
- package/src/testing.rs +9 -16
- package/src/worker.rs +86 -68
- package/ts/native.ts +39 -3
- package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
- package/sdk-core/crates/common/src/errors.rs +0 -85
- package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
- package/sdk-core/crates/macros/LICENSE.txt +0 -21
- package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
- package/sdk-core/crates/sdk/src/app_data.rs +0 -37
- package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
- package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
use crate::{
|
|
2
2
|
common::{
|
|
3
|
-
ANY_PORT, CoreWfStarter, NAMESPACE, OTEL_URL_ENV_VAR, PROMETHEUS_QUERY_API,
|
|
4
|
-
|
|
3
|
+
ANY_PORT, CoreWfStarter, NAMESPACE, OTEL_URL_ENV_VAR, PROMETHEUS_QUERY_API, eventually,
|
|
4
|
+
get_integ_client, get_integ_connection, get_integ_runtime_options,
|
|
5
|
+
get_integ_server_options, get_integ_telem_options, prom_metrics,
|
|
5
6
|
},
|
|
6
7
|
integ_tests::mk_nexus_endpoint,
|
|
7
8
|
};
|
|
8
|
-
use anyhow::anyhow;
|
|
9
|
+
use anyhow::{anyhow, bail};
|
|
9
10
|
use assert_matches::assert_matches;
|
|
10
11
|
use std::{
|
|
11
12
|
collections::HashMap,
|
|
@@ -15,15 +16,15 @@ use std::{
|
|
|
15
16
|
time::Duration,
|
|
16
17
|
};
|
|
17
18
|
use temporalio_client::{
|
|
18
|
-
|
|
19
|
+
Connection, NamespacedClient, REQUEST_LATENCY_HISTOGRAM_NAME, UntypedQuery, UntypedWorkflow,
|
|
20
|
+
WorkflowExecutionInfo, WorkflowQueryOptions, WorkflowStartOptions, grpc::WorkflowService,
|
|
19
21
|
};
|
|
20
22
|
use temporalio_common::{
|
|
21
|
-
|
|
22
|
-
errors::PollError,
|
|
23
|
+
data_converters::RawValue,
|
|
23
24
|
prost_dur,
|
|
24
25
|
protos::{
|
|
25
26
|
coresdk::{
|
|
26
|
-
ActivityTaskCompletion,
|
|
27
|
+
ActivityTaskCompletion,
|
|
27
28
|
activity_result::ActivityExecutionResult,
|
|
28
29
|
nexus::{NexusTaskCompletion, nexus_task, nexus_task_completion},
|
|
29
30
|
workflow_activation::{WorkflowActivationJob, workflow_activation_job},
|
|
@@ -36,38 +37,47 @@ use temporalio_common::{
|
|
|
36
37
|
},
|
|
37
38
|
temporal::api::{
|
|
38
39
|
common::v1::RetryPolicy,
|
|
39
|
-
enums::v1::{
|
|
40
|
+
enums::v1::{
|
|
41
|
+
NexusHandlerErrorRetryBehavior, WorkflowIdConflictPolicy, WorkflowIdReusePolicy,
|
|
42
|
+
},
|
|
40
43
|
failure::v1::Failure,
|
|
41
|
-
nexus
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
nexus::{
|
|
45
|
+
self,
|
|
46
|
+
v1::{
|
|
47
|
+
HandlerError, StartOperationResponse, UnsuccessfulOperationError,
|
|
48
|
+
request::Variant, start_operation_response,
|
|
49
|
+
},
|
|
45
50
|
},
|
|
46
|
-
query::v1::WorkflowQuery,
|
|
47
51
|
workflowservice::v1::{DescribeNamespaceRequest, ListNamespacesRequest},
|
|
48
52
|
},
|
|
49
53
|
},
|
|
50
54
|
telemetry::{
|
|
51
|
-
HistogramBucketOverrides,
|
|
52
|
-
|
|
55
|
+
HistogramBucketOverrides, OtelCollectorOptions, OtlpProtocol, PrometheusExporterOptions,
|
|
56
|
+
TaskQueueLabelStrategy, TelemetryOptions, build_otlp_metric_exporter,
|
|
53
57
|
metrics::{
|
|
54
58
|
CoreMeter, CounterBase, Gauge, GaugeBase, HistogramBase, MetricKeyValue,
|
|
55
|
-
MetricParameters,
|
|
59
|
+
MetricParameters, NewAttributes, WORKFLOW_TASK_EXECUTION_LATENCY_HISTOGRAM_NAME,
|
|
56
60
|
},
|
|
61
|
+
start_prometheus_metric_exporter,
|
|
57
62
|
},
|
|
58
|
-
worker::
|
|
59
|
-
PollerBehavior, SlotKind, SlotMarkUsedContext, SlotReleaseContext, SlotReservationContext,
|
|
60
|
-
SlotSupplier, SlotSupplierPermit, WorkerConfigBuilder, WorkerTaskTypes,
|
|
61
|
-
WorkerVersioningStrategy, WorkflowSlotKind,
|
|
62
|
-
},
|
|
63
|
+
worker::WorkerTaskTypes,
|
|
63
64
|
};
|
|
65
|
+
use temporalio_macros::{activities, workflow, workflow_methods};
|
|
64
66
|
use temporalio_sdk::{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
ActivityOptions, CancellableFuture, LocalActivityOptions, NexusOperationOptions,
|
|
68
|
+
WorkflowContext, WorkflowResult,
|
|
69
|
+
activities::{ActivityContext, ActivityError},
|
|
67
70
|
};
|
|
68
71
|
use temporalio_sdk_core::{
|
|
69
|
-
CoreRuntime, FixedSizeSlotSupplier,
|
|
70
|
-
|
|
72
|
+
CoreRuntime, FixedSizeSlotSupplier, PollError, PollerBehavior, SlotKind, SlotMarkUsedContext,
|
|
73
|
+
SlotReleaseContext, SlotReservationContext, SlotSupplier, SlotSupplierPermit,
|
|
74
|
+
TokioRuntimeBuilder, TunerBuilder, WorkerConfig, WorkerVersioningStrategy, WorkflowSlotKind,
|
|
75
|
+
init_worker,
|
|
76
|
+
replay::TestHistoryBuilder,
|
|
77
|
+
test_help::{
|
|
78
|
+
MockPollCfg, ResponseType, TemporalMeter, WorkerExt, WorkerTestHelpers, build_mock_pollers,
|
|
79
|
+
mock_worker, mock_worker_client,
|
|
80
|
+
},
|
|
71
81
|
};
|
|
72
82
|
use tokio::{join, sync::Barrier};
|
|
73
83
|
use tonic::IntoRequest;
|
|
@@ -83,30 +93,30 @@ async fn prometheus_metrics_exported(
|
|
|
83
93
|
#[values(true, false)] use_seconds_latency: bool,
|
|
84
94
|
#[values(true, false)] custom_buckets: bool,
|
|
85
95
|
) {
|
|
86
|
-
let
|
|
87
|
-
opts_builder
|
|
96
|
+
let opts = PrometheusExporterOptions::builder()
|
|
88
97
|
.global_tags(HashMap::from([("global".to_string(), "hi!".to_string())]))
|
|
89
98
|
.socket_addr(ANY_PORT.parse().unwrap())
|
|
90
|
-
.use_seconds_for_durations(use_seconds_latency)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
.use_seconds_for_durations(use_seconds_latency)
|
|
100
|
+
.histogram_bucket_overrides(if custom_buckets {
|
|
101
|
+
HistogramBucketOverrides {
|
|
102
|
+
overrides: {
|
|
103
|
+
let mut hm = HashMap::new();
|
|
104
|
+
hm.insert(REQUEST_LATENCY_HISTOGRAM_NAME.to_string(), vec![1337.0]);
|
|
105
|
+
hm
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
Default::default()
|
|
110
|
+
})
|
|
111
|
+
.build();
|
|
112
|
+
let (telemopts, addr, _aborter) = prom_metrics(Some(opts));
|
|
101
113
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
102
|
-
let opts = get_integ_server_options();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
.unwrap();
|
|
107
|
-
assert!(raw_client.get_client().capabilities().is_some());
|
|
114
|
+
let mut opts = get_integ_server_options();
|
|
115
|
+
opts.metrics_meter = rt.telemetry().get_temporal_metric_meter();
|
|
116
|
+
let mut connection = Connection::connect(opts).await.unwrap();
|
|
117
|
+
assert!(connection.capabilities().is_some());
|
|
108
118
|
|
|
109
|
-
let _ =
|
|
119
|
+
let _ = connection
|
|
110
120
|
.list_namespaces(ListNamespacesRequest::default().into_request())
|
|
111
121
|
.await
|
|
112
122
|
.unwrap();
|
|
@@ -138,8 +148,8 @@ async fn prometheus_metrics_exported(
|
|
|
138
148
|
assert!(body.contains("temporal_request{"));
|
|
139
149
|
// Verify non-temporal metrics meter does not prefix
|
|
140
150
|
let mm = rt.telemetry().get_metric_meter().unwrap();
|
|
141
|
-
let g = mm.
|
|
142
|
-
let attrs = mm.
|
|
151
|
+
let g = mm.gauge(MetricParameters::from("mygauge"));
|
|
152
|
+
let attrs = mm.new_attributes(NewAttributes::new(vec![]));
|
|
143
153
|
g.record(42, &attrs);
|
|
144
154
|
let body = get_text(format!("http://{addr}/metrics")).await;
|
|
145
155
|
assert!(body.contains("\nmygauge{global=\"hi!\"} 42"));
|
|
@@ -151,7 +161,7 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
151
161
|
let tq = "one_slot_worker_tq";
|
|
152
162
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
153
163
|
|
|
154
|
-
let worker_cfg =
|
|
164
|
+
let worker_cfg = WorkerConfig::builder()
|
|
155
165
|
.namespace(NAMESPACE)
|
|
156
166
|
.task_queue(tq)
|
|
157
167
|
.versioning_strategy(WorkerVersioningStrategy::None {
|
|
@@ -168,13 +178,9 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
168
178
|
.build()
|
|
169
179
|
.unwrap();
|
|
170
180
|
|
|
171
|
-
let
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
.await
|
|
175
|
-
.expect("Must connect"),
|
|
176
|
-
);
|
|
177
|
-
let worker = init_worker(&rt, worker_cfg, client.clone()).expect("Worker inits cleanly");
|
|
181
|
+
let connection = get_integ_connection(None).await;
|
|
182
|
+
let client = Arc::new(get_integ_client(worker_cfg.namespace.clone(), None).await);
|
|
183
|
+
let worker = init_worker(&rt, worker_cfg, connection).expect("Worker inits cleanly");
|
|
178
184
|
let wf_task_barr = Barrier::new(2);
|
|
179
185
|
let act_task_barr = Barrier::new(2);
|
|
180
186
|
|
|
@@ -273,16 +279,13 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
273
279
|
// Start a workflow so that a task will get delivered
|
|
274
280
|
client
|
|
275
281
|
.start_workflow(
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
"one_slot_metric_test".to_owned()
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
execution_timeout: Some(Duration::from_secs(5)),
|
|
284
|
-
..Default::default()
|
|
285
|
-
},
|
|
282
|
+
UntypedWorkflow::new("whatever"),
|
|
283
|
+
RawValue::default(),
|
|
284
|
+
WorkflowStartOptions::new(tq.to_owned(), "one_slot_metric_test".to_owned())
|
|
285
|
+
.id_conflict_policy(WorkflowIdConflictPolicy::TerminateExisting)
|
|
286
|
+
.id_reuse_policy(WorkflowIdReusePolicy::AllowDuplicate)
|
|
287
|
+
.execution_timeout(Duration::from_secs(5))
|
|
288
|
+
.build(),
|
|
286
289
|
)
|
|
287
290
|
.await
|
|
288
291
|
.unwrap();
|
|
@@ -407,7 +410,7 @@ async fn query_of_closed_workflow_doesnt_tick_terminal_metric(
|
|
|
407
410
|
let mut starter =
|
|
408
411
|
CoreWfStarter::new_with_runtime("query_of_closed_workflow_doesnt_tick_terminal_metric", rt);
|
|
409
412
|
// Disable cache to ensure replay happens completely
|
|
410
|
-
starter.
|
|
413
|
+
starter.sdk_config.max_cached_workflows = 0_usize;
|
|
411
414
|
let worker = starter.get_worker().await;
|
|
412
415
|
let run_id = starter.start_wf().await;
|
|
413
416
|
let task = worker.poll_workflow_activation().await.unwrap();
|
|
@@ -464,18 +467,20 @@ async fn query_of_closed_workflow_doesnt_tick_terminal_metric(
|
|
|
464
467
|
// Query the now-closed workflow
|
|
465
468
|
let client = starter.get_client().await;
|
|
466
469
|
let queryer = async {
|
|
467
|
-
|
|
468
|
-
.
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
|
|
470
|
+
WorkflowExecutionInfo {
|
|
471
|
+
namespace: client.namespace(),
|
|
472
|
+
workflow_id: starter.get_wf_id().to_string(),
|
|
473
|
+
run_id: Some(run_id),
|
|
474
|
+
first_execution_run_id: None,
|
|
475
|
+
}
|
|
476
|
+
.bind_untyped(client.clone())
|
|
477
|
+
.query(
|
|
478
|
+
UntypedQuery::new("fake_query"),
|
|
479
|
+
RawValue::empty(),
|
|
480
|
+
WorkflowQueryOptions::default(),
|
|
481
|
+
)
|
|
482
|
+
.await
|
|
483
|
+
.unwrap();
|
|
479
484
|
};
|
|
480
485
|
let query_reply = async {
|
|
481
486
|
// Need to re-complete b/c replay
|
|
@@ -535,13 +540,11 @@ fn runtime_new() {
|
|
|
535
540
|
let (telemopts, addr, _aborter) = prom_metrics(None);
|
|
536
541
|
rt.telemetry_mut()
|
|
537
542
|
.attach_late_init_metrics(telemopts.metrics.unwrap());
|
|
538
|
-
let opts = get_integ_server_options();
|
|
543
|
+
let mut opts = get_integ_server_options();
|
|
544
|
+
opts.metrics_meter = rt.telemetry().get_temporal_metric_meter();
|
|
539
545
|
handle.block_on(async {
|
|
540
|
-
let mut raw_client = opts
|
|
541
|
-
|
|
542
|
-
.await
|
|
543
|
-
.unwrap();
|
|
544
|
-
assert!(raw_client.get_client().capabilities().is_some());
|
|
546
|
+
let mut raw_client = Connection::connect(opts).await.unwrap();
|
|
547
|
+
assert!(raw_client.capabilities().is_some());
|
|
545
548
|
let _ = raw_client
|
|
546
549
|
.list_namespaces(ListNamespacesRequest::default().into_request())
|
|
547
550
|
.await
|
|
@@ -558,7 +561,7 @@ async fn latency_metrics(
|
|
|
558
561
|
#[values(true, false)] show_units: bool,
|
|
559
562
|
) {
|
|
560
563
|
let (telemopts, addr, _aborter) = prom_metrics(Some(
|
|
561
|
-
|
|
564
|
+
PrometheusExporterOptions::builder()
|
|
562
565
|
.socket_addr(ANY_PORT.parse().unwrap())
|
|
563
566
|
.use_seconds_for_durations(use_seconds_latency)
|
|
564
567
|
.unit_suffix(show_units)
|
|
@@ -572,8 +575,7 @@ async fn latency_metrics(
|
|
|
572
575
|
hm
|
|
573
576
|
},
|
|
574
577
|
})
|
|
575
|
-
.build()
|
|
576
|
-
.unwrap(),
|
|
578
|
+
.build(),
|
|
577
579
|
));
|
|
578
580
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
579
581
|
let mut starter = CoreWfStarter::new_with_runtime("latency_metrics", rt);
|
|
@@ -630,11 +632,11 @@ async fn latency_metrics(
|
|
|
630
632
|
async fn request_fail_codes() {
|
|
631
633
|
let (telemopts, addr, _aborter) = prom_metrics(None);
|
|
632
634
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
633
|
-
let
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
635
|
+
let mut client = get_integ_client(
|
|
636
|
+
NAMESPACE.to_string(),
|
|
637
|
+
rt.telemetry().get_temporal_metric_meter(),
|
|
638
|
+
)
|
|
639
|
+
.await;
|
|
638
640
|
|
|
639
641
|
// Describe namespace w/ invalid argument (unset namespace field)
|
|
640
642
|
WorkflowService::describe_namespace(
|
|
@@ -663,25 +665,20 @@ async fn request_fail_codes_otel() {
|
|
|
663
665
|
.ok()
|
|
664
666
|
.map(|x| x.parse::<Url>().unwrap())
|
|
665
667
|
{
|
|
666
|
-
let opts =
|
|
667
|
-
.url(url)
|
|
668
|
-
.build()
|
|
669
|
-
.unwrap();
|
|
668
|
+
let opts = OtelCollectorOptions::builder().url(url).build();
|
|
670
669
|
build_otlp_metric_exporter(opts).unwrap()
|
|
671
670
|
} else {
|
|
672
671
|
// skip
|
|
673
672
|
return;
|
|
674
673
|
};
|
|
675
|
-
let mut telemopts = TelemetryOptionsBuilder::default();
|
|
676
674
|
let exporter = Arc::new(exporter);
|
|
677
|
-
telemopts.metrics(exporter as Arc<dyn CoreMeter>);
|
|
678
|
-
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts.build().unwrap()
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
.unwrap();
|
|
675
|
+
let telemopts = TelemetryOptions::builder().metrics(exporter as Arc<dyn CoreMeter>);
|
|
676
|
+
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts.build())).unwrap();
|
|
677
|
+
let mut client = get_integ_client(
|
|
678
|
+
NAMESPACE.to_string(),
|
|
679
|
+
rt.telemetry().get_temporal_metric_meter(),
|
|
680
|
+
)
|
|
681
|
+
.await;
|
|
685
682
|
|
|
686
683
|
for _ in 0..10 {
|
|
687
684
|
// Describe namespace w/ invalid argument (unset namespace field)
|
|
@@ -717,18 +714,16 @@ async fn docker_metrics_with_prometheus(
|
|
|
717
714
|
);
|
|
718
715
|
|
|
719
716
|
// Configure the OTLP exporter with HTTP
|
|
720
|
-
let opts =
|
|
717
|
+
let opts = OtelCollectorOptions::builder()
|
|
721
718
|
.url(otel_collector_addr.parse().unwrap())
|
|
722
719
|
.protocol(otel_protocol)
|
|
723
720
|
.global_tags(HashMap::from([("test_id".to_string(), test_uid.clone())]))
|
|
724
|
-
.build()
|
|
725
|
-
.unwrap();
|
|
721
|
+
.build();
|
|
726
722
|
let exporter = Arc::new(build_otlp_metric_exporter(opts).unwrap());
|
|
727
|
-
let telemopts =
|
|
723
|
+
let telemopts = TelemetryOptions::builder()
|
|
728
724
|
.metrics(exporter as Arc<dyn CoreMeter>)
|
|
729
725
|
.metric_prefix(test_uid.clone())
|
|
730
|
-
.build()
|
|
731
|
-
.unwrap();
|
|
726
|
+
.build();
|
|
732
727
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
733
728
|
let test_name = "docker_metrics_with_prometheus";
|
|
734
729
|
let mut starter = CoreWfStarter::new_with_runtime(test_name, rt);
|
|
@@ -746,38 +741,48 @@ async fn docker_metrics_with_prometheus(
|
|
|
746
741
|
.unwrap();
|
|
747
742
|
|
|
748
743
|
let client = starter.get_client().await;
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
let client = reqwest::Client::new();
|
|
756
|
-
let query = format!("temporal_sdk_{}num_pollers", test_uid.clone());
|
|
757
|
-
let response = client
|
|
758
|
-
.get(PROMETHEUS_QUERY_API)
|
|
759
|
-
.query(&[("query", query)])
|
|
760
|
-
.send()
|
|
761
|
-
.await
|
|
762
|
-
.unwrap()
|
|
763
|
-
.json::<serde_json::Value>()
|
|
764
|
-
.await
|
|
765
|
-
.unwrap();
|
|
744
|
+
WorkflowService::list_namespaces(
|
|
745
|
+
&mut client.clone(),
|
|
746
|
+
ListNamespacesRequest::default().into_request(),
|
|
747
|
+
)
|
|
748
|
+
.await
|
|
749
|
+
.unwrap();
|
|
766
750
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
.
|
|
775
|
-
.
|
|
776
|
-
.
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
751
|
+
eventually(
|
|
752
|
+
|| async {
|
|
753
|
+
// Query Prometheus API for metrics
|
|
754
|
+
let client = reqwest::Client::new();
|
|
755
|
+
let query = format!("temporal_sdk_{}num_pollers", test_uid.clone());
|
|
756
|
+
let response = client
|
|
757
|
+
.get(PROMETHEUS_QUERY_API)
|
|
758
|
+
.query(&[("query", query.clone())])
|
|
759
|
+
.send()
|
|
760
|
+
.await?
|
|
761
|
+
.json::<serde_json::Value>()
|
|
762
|
+
.await?;
|
|
763
|
+
|
|
764
|
+
// Validate the Prometheus response
|
|
765
|
+
if let Some(data) = response["data"]["result"].as_array() {
|
|
766
|
+
if data.is_empty() {
|
|
767
|
+
bail!("No metrics found for query: {query}");
|
|
768
|
+
}
|
|
769
|
+
assert_eq!(data[0]["metric"]["exported_job"], "temporal-core-sdk");
|
|
770
|
+
assert_eq!(data[0]["metric"]["job"], "otel-collector");
|
|
771
|
+
assert!(
|
|
772
|
+
data[0]["metric"]["task_queue"]
|
|
773
|
+
.as_str()
|
|
774
|
+
.unwrap()
|
|
775
|
+
.starts_with(test_name)
|
|
776
|
+
);
|
|
777
|
+
} else {
|
|
778
|
+
bail!("Invalid Prometheus response: {response:?}");
|
|
779
|
+
}
|
|
780
|
+
Ok(())
|
|
781
|
+
},
|
|
782
|
+
Duration::from_secs(45),
|
|
783
|
+
)
|
|
784
|
+
.await
|
|
785
|
+
.unwrap();
|
|
781
786
|
}
|
|
782
787
|
|
|
783
788
|
#[tokio::test]
|
|
@@ -786,86 +791,110 @@ async fn activity_metrics() {
|
|
|
786
791
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
787
792
|
let wf_name = "activity_metrics";
|
|
788
793
|
let mut starter = CoreWfStarter::new_with_runtime(wf_name, rt);
|
|
789
|
-
starter
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
794
|
+
starter.sdk_config.graceful_shutdown_period = Some(Duration::from_secs(1));
|
|
795
|
+
|
|
796
|
+
struct PassFailActivities;
|
|
797
|
+
#[activities]
|
|
798
|
+
impl PassFailActivities {
|
|
799
|
+
#[activity(name = "pass_fail_act")]
|
|
800
|
+
async fn pass_fail_act(ctx: ActivityContext, i: String) -> Result<String, ActivityError> {
|
|
801
|
+
match i.as_str() {
|
|
802
|
+
"pass" => Ok("pass".to_string()),
|
|
803
|
+
"cancel" => {
|
|
804
|
+
ctx.cancelled().await;
|
|
805
|
+
Err(ActivityError::cancelled())
|
|
806
|
+
}
|
|
807
|
+
_ => Err(anyhow!("fail").into()),
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
starter.sdk_config.register_activities(PassFailActivities);
|
|
793
813
|
let mut worker = starter.worker().await;
|
|
794
814
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
815
|
+
#[workflow]
|
|
816
|
+
#[derive(Default)]
|
|
817
|
+
struct ActivityMetricsWf;
|
|
818
|
+
|
|
819
|
+
#[workflow_methods]
|
|
820
|
+
impl ActivityMetricsWf {
|
|
821
|
+
#[run]
|
|
822
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
823
|
+
let normal_act_pass = ctx.start_activity(
|
|
824
|
+
PassFailActivities::pass_fail_act,
|
|
825
|
+
"pass".to_string(),
|
|
826
|
+
ActivityOptions {
|
|
827
|
+
start_to_close_timeout: Some(Duration::from_secs(1)),
|
|
828
|
+
..Default::default()
|
|
829
|
+
},
|
|
830
|
+
);
|
|
831
|
+
let normal_act_fail = ctx.start_activity(
|
|
832
|
+
PassFailActivities::pass_fail_act,
|
|
833
|
+
"fail".to_string(),
|
|
834
|
+
ActivityOptions {
|
|
835
|
+
start_to_close_timeout: Some(Duration::from_secs(1)),
|
|
836
|
+
retry_policy: Some(RetryPolicy {
|
|
837
|
+
maximum_attempts: 1,
|
|
838
|
+
..Default::default()
|
|
839
|
+
}),
|
|
840
|
+
..Default::default()
|
|
841
|
+
},
|
|
842
|
+
);
|
|
843
|
+
let _ = join!(normal_act_pass, normal_act_fail);
|
|
844
|
+
let local_act_pass = ctx.start_local_activity(
|
|
845
|
+
PassFailActivities::pass_fail_act,
|
|
846
|
+
"pass".to_string(),
|
|
847
|
+
LocalActivityOptions::default(),
|
|
848
|
+
);
|
|
849
|
+
let local_act_fail = ctx.start_local_activity(
|
|
850
|
+
PassFailActivities::pass_fail_act,
|
|
851
|
+
"fail".to_string(),
|
|
852
|
+
LocalActivityOptions {
|
|
853
|
+
retry_policy: RetryPolicy {
|
|
854
|
+
maximum_attempts: 1,
|
|
855
|
+
..Default::default()
|
|
856
|
+
},
|
|
857
|
+
..Default::default()
|
|
858
|
+
},
|
|
859
|
+
);
|
|
860
|
+
let local_act_cancel = ctx.start_local_activity(
|
|
861
|
+
PassFailActivities::pass_fail_act,
|
|
862
|
+
"cancel".to_string(),
|
|
863
|
+
LocalActivityOptions {
|
|
864
|
+
retry_policy: RetryPolicy {
|
|
865
|
+
maximum_attempts: 1,
|
|
866
|
+
..Default::default()
|
|
867
|
+
},
|
|
868
|
+
..Default::default()
|
|
869
|
+
},
|
|
870
|
+
);
|
|
871
|
+
let _ = join!(local_act_pass, local_act_fail);
|
|
872
|
+
// TODO: Currently takes a WFT b/c of https://github.com/temporalio/sdk-core/issues/856
|
|
873
|
+
local_act_cancel.cancel();
|
|
874
|
+
let _ = local_act_cancel.await;
|
|
875
|
+
Ok(())
|
|
850
876
|
}
|
|
851
|
-
}
|
|
877
|
+
}
|
|
852
878
|
|
|
879
|
+
worker.register_workflow::<ActivityMetricsWf>();
|
|
880
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
881
|
+
let workflow_id = wf_name.to_owned();
|
|
853
882
|
worker
|
|
854
|
-
.
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
WorkflowOptions::default(),
|
|
883
|
+
.submit_workflow(
|
|
884
|
+
ActivityMetricsWf::run,
|
|
885
|
+
(),
|
|
886
|
+
WorkflowStartOptions::new(task_queue.clone(), workflow_id).build(),
|
|
859
887
|
)
|
|
860
888
|
.await
|
|
861
889
|
.unwrap();
|
|
862
890
|
worker.run_until_done().await.unwrap();
|
|
863
891
|
|
|
864
892
|
let body = get_text(format!("http://{addr}/metrics")).await;
|
|
893
|
+
let wf_type = ActivityMetricsWf::name();
|
|
865
894
|
assert!(body.contains(&format!(
|
|
866
895
|
"temporal_activity_execution_failed{{activity_type=\"pass_fail_act\",\
|
|
867
896
|
namespace=\"{NAMESPACE}\",service_name=\"temporal-core-sdk\",\
|
|
868
|
-
task_queue=\"{task_queue}\",workflow_type=\"{
|
|
897
|
+
task_queue=\"{task_queue}\",workflow_type=\"{wf_type}\"}} 1"
|
|
869
898
|
)));
|
|
870
899
|
assert!(body.contains(&format!(
|
|
871
900
|
"temporal_activity_schedule_to_start_latency_count{{\
|
|
@@ -875,42 +904,42 @@ async fn activity_metrics() {
|
|
|
875
904
|
assert!(body.contains(&format!(
|
|
876
905
|
"temporal_activity_execution_latency_count{{activity_type=\"pass_fail_act\",\
|
|
877
906
|
namespace=\"{NAMESPACE}\",service_name=\"temporal-core-sdk\",\
|
|
878
|
-
task_queue=\"{task_queue}\",workflow_type=\"{
|
|
907
|
+
task_queue=\"{task_queue}\",workflow_type=\"{wf_type}\"}} 2"
|
|
879
908
|
)));
|
|
880
909
|
assert!(body.contains(&format!(
|
|
881
910
|
"temporal_activity_succeed_endtoend_latency_count{{activity_type=\"pass_fail_act\",\
|
|
882
911
|
namespace=\"{NAMESPACE}\",service_name=\"temporal-core-sdk\",\
|
|
883
|
-
task_queue=\"{task_queue}\",workflow_type=\"{
|
|
912
|
+
task_queue=\"{task_queue}\",workflow_type=\"{wf_type}\"}} 1"
|
|
884
913
|
)));
|
|
885
914
|
|
|
886
915
|
assert!(body.contains(&format!(
|
|
887
916
|
"temporal_local_activity_total{{activity_type=\"pass_fail_act\",namespace=\"{NAMESPACE}\",\
|
|
888
917
|
service_name=\"temporal-core-sdk\",task_queue=\"{task_queue}\",\
|
|
889
|
-
workflow_type=\"{
|
|
918
|
+
workflow_type=\"{wf_type}\"}} 3"
|
|
890
919
|
)));
|
|
891
920
|
assert!(body.contains(&format!(
|
|
892
921
|
"temporal_local_activity_execution_failed{{activity_type=\"pass_fail_act\",\
|
|
893
922
|
namespace=\"{NAMESPACE}\",service_name=\"temporal-core-sdk\",\
|
|
894
923
|
task_queue=\"{task_queue}\",\
|
|
895
|
-
workflow_type=\"{
|
|
924
|
+
workflow_type=\"{wf_type}\"}} 1"
|
|
896
925
|
)));
|
|
897
926
|
assert!(body.contains(&format!(
|
|
898
927
|
"temporal_local_activity_execution_cancelled{{activity_type=\"pass_fail_act\",\
|
|
899
928
|
namespace=\"{NAMESPACE}\",service_name=\"temporal-core-sdk\",\
|
|
900
929
|
task_queue=\"{task_queue}\",\
|
|
901
|
-
workflow_type=\"{
|
|
930
|
+
workflow_type=\"{wf_type}\"}} 1"
|
|
902
931
|
)));
|
|
903
932
|
assert!(body.contains(&format!(
|
|
904
933
|
"temporal_local_activity_execution_latency_count{{activity_type=\"pass_fail_act\",\
|
|
905
934
|
namespace=\"{NAMESPACE}\",service_name=\"temporal-core-sdk\",\
|
|
906
935
|
task_queue=\"{task_queue}\",\
|
|
907
|
-
workflow_type=\"{
|
|
936
|
+
workflow_type=\"{wf_type}\"}} 3"
|
|
908
937
|
)));
|
|
909
938
|
assert!(body.contains(&format!(
|
|
910
939
|
"temporal_local_activity_succeed_endtoend_latency_count{{activity_type=\"pass_fail_act\",\
|
|
911
940
|
namespace=\"{NAMESPACE}\",service_name=\"temporal-core-sdk\",\
|
|
912
941
|
task_queue=\"{task_queue}\",\
|
|
913
|
-
workflow_type=\"{
|
|
942
|
+
workflow_type=\"{wf_type}\"}} 1"
|
|
914
943
|
)));
|
|
915
944
|
}
|
|
916
945
|
|
|
@@ -920,25 +949,30 @@ async fn nexus_metrics() {
|
|
|
920
949
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
921
950
|
let wf_name = "nexus_metrics";
|
|
922
951
|
let mut starter = CoreWfStarter::new_with_runtime(wf_name, rt);
|
|
923
|
-
starter.
|
|
952
|
+
starter.sdk_config.task_types = WorkerTaskTypes {
|
|
924
953
|
enable_workflows: true,
|
|
925
954
|
enable_local_activities: false,
|
|
926
955
|
enable_remote_activities: false,
|
|
927
956
|
enable_nexus: true,
|
|
928
|
-
}
|
|
929
|
-
let task_queue = starter.get_task_queue().to_owned();
|
|
957
|
+
};
|
|
930
958
|
let mut worker = starter.worker().await;
|
|
931
959
|
let core_worker = starter.get_worker().await;
|
|
932
960
|
let endpoint = mk_nexus_endpoint(&mut starter).await;
|
|
933
961
|
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
async
|
|
962
|
+
#[workflow]
|
|
963
|
+
#[derive(Default)]
|
|
964
|
+
struct NexusMetricsWf;
|
|
965
|
+
|
|
966
|
+
#[workflow_methods]
|
|
967
|
+
impl NexusMetricsWf {
|
|
968
|
+
#[run]
|
|
969
|
+
async fn run(ctx: &mut WorkflowContext<Self>, endpoint: String) -> WorkflowResult<()> {
|
|
970
|
+
let partial_op = NexusOperationOptions {
|
|
971
|
+
endpoint: endpoint.clone(),
|
|
972
|
+
service: "mysvc".to_string(),
|
|
973
|
+
operation: "myop".to_string(),
|
|
974
|
+
..Default::default()
|
|
975
|
+
};
|
|
942
976
|
join!(
|
|
943
977
|
async {
|
|
944
978
|
ctx.start_nexus_operation(partial_op.clone())
|
|
@@ -973,11 +1007,21 @@ async fn nexus_metrics() {
|
|
|
973
1007
|
.await;
|
|
974
1008
|
}
|
|
975
1009
|
);
|
|
976
|
-
Ok(()
|
|
1010
|
+
Ok(())
|
|
977
1011
|
}
|
|
978
|
-
}
|
|
1012
|
+
}
|
|
979
1013
|
|
|
980
|
-
|
|
1014
|
+
worker.register_workflow::<NexusMetricsWf>();
|
|
1015
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
1016
|
+
let workflow_id = wf_name.to_owned();
|
|
1017
|
+
worker
|
|
1018
|
+
.submit_workflow(
|
|
1019
|
+
NexusMetricsWf::run,
|
|
1020
|
+
endpoint,
|
|
1021
|
+
WorkflowStartOptions::new(task_queue.clone(), workflow_id).build(),
|
|
1022
|
+
)
|
|
1023
|
+
.await
|
|
1024
|
+
.unwrap();
|
|
981
1025
|
|
|
982
1026
|
let nexus_polling = async {
|
|
983
1027
|
for _ in 0..5 {
|
|
@@ -1010,6 +1054,7 @@ async fn nexus_metrics() {
|
|
|
1010
1054
|
variant: Some(nexus::v1::response::Variant::StartOperation(
|
|
1011
1055
|
StartOperationResponse {
|
|
1012
1056
|
variant: Some(
|
|
1057
|
+
#[allow(deprecated)]
|
|
1013
1058
|
start_operation_response::Variant::OperationError(
|
|
1014
1059
|
UnsuccessfulOperationError {
|
|
1015
1060
|
operation_state: "failed".to_string(),
|
|
@@ -1024,7 +1069,9 @@ async fn nexus_metrics() {
|
|
|
1024
1069
|
)),
|
|
1025
1070
|
})
|
|
1026
1071
|
}
|
|
1027
|
-
Some(p) if p == "handler-fail".into() =>
|
|
1072
|
+
Some(p) if p == "handler-fail".into() =>
|
|
1073
|
+
{
|
|
1074
|
+
#[allow(deprecated)]
|
|
1028
1075
|
nexus_task_completion::Status::Error(HandlerError {
|
|
1029
1076
|
error_type: "BAD_REQUEST".to_string(),
|
|
1030
1077
|
failure: Some(nexus::v1::Failure {
|
|
@@ -1102,22 +1149,29 @@ async fn evict_on_complete_does_not_count_as_forced_eviction() {
|
|
|
1102
1149
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
1103
1150
|
let wf_name = "evict_on_complete_does_not_count_as_forced_eviction";
|
|
1104
1151
|
let mut starter = CoreWfStarter::new_with_runtime(wf_name, rt);
|
|
1105
|
-
starter
|
|
1106
|
-
.worker_config
|
|
1107
|
-
.task_types(WorkerTaskTypes::workflow_only());
|
|
1152
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
1108
1153
|
let mut worker = starter.worker().await;
|
|
1109
1154
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1155
|
+
#[workflow]
|
|
1156
|
+
#[derive(Default)]
|
|
1157
|
+
struct EvictOnCompleteWf;
|
|
1158
|
+
|
|
1159
|
+
#[workflow_methods]
|
|
1160
|
+
impl EvictOnCompleteWf {
|
|
1161
|
+
#[run]
|
|
1162
|
+
async fn run(_ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
1163
|
+
Ok(())
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1114
1166
|
|
|
1167
|
+
worker.register_workflow::<EvictOnCompleteWf>();
|
|
1168
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
1169
|
+
let workflow_id = wf_name.to_owned();
|
|
1115
1170
|
worker
|
|
1116
|
-
.
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
WorkflowOptions::default(),
|
|
1171
|
+
.submit_workflow(
|
|
1172
|
+
EvictOnCompleteWf::run,
|
|
1173
|
+
(),
|
|
1174
|
+
WorkflowStartOptions::new(task_queue, workflow_id).build(),
|
|
1121
1175
|
)
|
|
1122
1176
|
.await
|
|
1123
1177
|
.unwrap();
|
|
@@ -1187,29 +1241,34 @@ async fn metrics_available_from_custom_slot_supplier() {
|
|
|
1187
1241
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
1188
1242
|
let mut starter =
|
|
1189
1243
|
CoreWfStarter::new_with_runtime("metrics_available_from_custom_slot_supplier", rt);
|
|
1190
|
-
starter
|
|
1191
|
-
.worker_config
|
|
1192
|
-
.task_types(WorkerTaskTypes::workflow_only());
|
|
1193
|
-
starter.worker_config.clear_max_outstanding_opts();
|
|
1244
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
1194
1245
|
let mut tb = TunerBuilder::default();
|
|
1195
1246
|
tb.workflow_slot_supplier(Arc::new(MetricRecordingSlotSupplier::<WorkflowSlotKind> {
|
|
1196
1247
|
inner: FixedSizeSlotSupplier::new(5),
|
|
1197
1248
|
metrics: OnceLock::new(),
|
|
1198
1249
|
}));
|
|
1199
|
-
starter.
|
|
1250
|
+
starter.sdk_config.tuner = Arc::new(tb.build());
|
|
1200
1251
|
let mut worker = starter.worker().await;
|
|
1201
1252
|
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1253
|
+
#[workflow]
|
|
1254
|
+
#[derive(Default)]
|
|
1255
|
+
struct CustomSlotSupplierWf;
|
|
1256
|
+
|
|
1257
|
+
#[workflow_methods]
|
|
1258
|
+
impl CustomSlotSupplierWf {
|
|
1259
|
+
#[run]
|
|
1260
|
+
async fn run(_ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
1261
|
+
Ok(())
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1206
1264
|
|
|
1265
|
+
worker.register_workflow::<CustomSlotSupplierWf>();
|
|
1266
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
1207
1267
|
worker
|
|
1208
|
-
.
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
WorkflowOptions::default(),
|
|
1268
|
+
.submit_workflow(
|
|
1269
|
+
CustomSlotSupplierWf::run,
|
|
1270
|
+
(),
|
|
1271
|
+
WorkflowStartOptions::new(task_queue, "s_wf".to_owned()).build(),
|
|
1213
1272
|
)
|
|
1214
1273
|
.await
|
|
1215
1274
|
.unwrap();
|
|
@@ -1314,17 +1373,11 @@ async fn test_prometheus_metric_format_consistency() {
|
|
|
1314
1373
|
|
|
1315
1374
|
#[tokio::test]
|
|
1316
1375
|
async fn prometheus_label_nonsense() {
|
|
1317
|
-
let
|
|
1318
|
-
|
|
1319
|
-
let (telemopts, addr, _aborter) = prom_metrics(Some(opts_builder.build().unwrap()));
|
|
1376
|
+
let opts_builder = PrometheusExporterOptions::builder().socket_addr(ANY_PORT.parse().unwrap());
|
|
1377
|
+
let (telemopts, addr, _aborter) = prom_metrics(Some(opts_builder.build()));
|
|
1320
1378
|
let meter = telemopts.metrics.clone().unwrap();
|
|
1321
1379
|
|
|
1322
|
-
let ctr = meter.counter(
|
|
1323
|
-
MetricParametersBuilder::default()
|
|
1324
|
-
.name("some_counter")
|
|
1325
|
-
.build()
|
|
1326
|
-
.unwrap(),
|
|
1327
|
-
);
|
|
1380
|
+
let ctr = meter.counter(MetricParameters::builder().name("some_counter").build());
|
|
1328
1381
|
let a1 = meter.new_attributes(NewAttributes::from([MetricKeyValue::new("thing", "foo")]));
|
|
1329
1382
|
let a2 = meter.new_attributes(NewAttributes::from([MetricKeyValue::new("blerp", "baz")]));
|
|
1330
1383
|
ctr.add(1, &a1);
|
|
@@ -1347,36 +1400,41 @@ async fn sticky_queue_label_strategy(
|
|
|
1347
1400
|
strategy: TaskQueueLabelStrategy,
|
|
1348
1401
|
) {
|
|
1349
1402
|
let (mut telemopts, addr, _aborter) = prom_metrics(Some(
|
|
1350
|
-
|
|
1403
|
+
PrometheusExporterOptions::builder()
|
|
1351
1404
|
.socket_addr(ANY_PORT.parse().unwrap())
|
|
1352
|
-
.build()
|
|
1353
|
-
.unwrap(),
|
|
1405
|
+
.build(),
|
|
1354
1406
|
));
|
|
1355
1407
|
telemopts.task_queue_label_strategy = strategy;
|
|
1356
1408
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
1357
1409
|
let wf_name = format!("sticky_queue_label_strategy_{strategy:?}");
|
|
1358
1410
|
let mut starter = CoreWfStarter::new_with_runtime(&wf_name, rt);
|
|
1359
1411
|
// Enable sticky queues by setting a reasonable cache size
|
|
1360
|
-
starter.
|
|
1361
|
-
starter
|
|
1362
|
-
.worker_config
|
|
1363
|
-
.task_types(WorkerTaskTypes::workflow_only());
|
|
1364
|
-
let task_queue = starter.get_task_queue().to_owned();
|
|
1412
|
+
starter.sdk_config.max_cached_workflows = 10_usize;
|
|
1413
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
1365
1414
|
let mut worker = starter.worker().await;
|
|
1366
1415
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1416
|
+
#[workflow]
|
|
1417
|
+
#[derive(Default)]
|
|
1418
|
+
struct StickyQueueLabelStrategyWf;
|
|
1419
|
+
|
|
1420
|
+
#[workflow_methods]
|
|
1421
|
+
impl StickyQueueLabelStrategyWf {
|
|
1422
|
+
#[run]
|
|
1423
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
1424
|
+
ctx.timer(Duration::from_millis(1)).await;
|
|
1425
|
+
Ok(())
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
worker.register_workflow::<StickyQueueLabelStrategyWf>();
|
|
1430
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
1371
1431
|
worker
|
|
1372
|
-
.
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
..Default::default()
|
|
1379
|
-
},
|
|
1432
|
+
.submit_workflow(
|
|
1433
|
+
StickyQueueLabelStrategyWf::run,
|
|
1434
|
+
(),
|
|
1435
|
+
WorkflowStartOptions::new(task_queue.clone(), wf_name.clone())
|
|
1436
|
+
.enable_eager_workflow_start(false)
|
|
1437
|
+
.build(),
|
|
1380
1438
|
)
|
|
1381
1439
|
.await
|
|
1382
1440
|
.unwrap();
|
|
@@ -1436,28 +1494,34 @@ async fn resource_based_tuner_metrics() {
|
|
|
1436
1494
|
let rt = CoreRuntime::new_assume_tokio(get_integ_runtime_options(telemopts)).unwrap();
|
|
1437
1495
|
let wf_name = "resource_based_tuner_metrics";
|
|
1438
1496
|
let mut starter = CoreWfStarter::new_with_runtime(wf_name, rt);
|
|
1439
|
-
starter
|
|
1440
|
-
.worker_config
|
|
1441
|
-
.task_types(WorkerTaskTypes::workflow_only());
|
|
1442
|
-
starter.worker_config.clear_max_outstanding_opts();
|
|
1443
|
-
|
|
1497
|
+
starter.sdk_config.task_types = WorkerTaskTypes::workflow_only();
|
|
1444
1498
|
// Create a resource-based tuner with reasonable thresholds
|
|
1445
1499
|
let tuner = ResourceBasedTuner::new(0.8, 0.8);
|
|
1446
|
-
starter.
|
|
1500
|
+
starter.sdk_config.tuner = Arc::new(tuner);
|
|
1447
1501
|
|
|
1448
1502
|
let mut worker = starter.worker().await;
|
|
1449
1503
|
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
});
|
|
1504
|
+
#[workflow]
|
|
1505
|
+
#[derive(Default)]
|
|
1506
|
+
struct ResourceBasedTunerMetricsWf;
|
|
1454
1507
|
|
|
1508
|
+
#[workflow_methods]
|
|
1509
|
+
impl ResourceBasedTunerMetricsWf {
|
|
1510
|
+
#[run]
|
|
1511
|
+
async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<()> {
|
|
1512
|
+
ctx.timer(Duration::from_millis(100)).await;
|
|
1513
|
+
Ok(())
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
worker.register_workflow::<ResourceBasedTunerMetricsWf>();
|
|
1518
|
+
let task_queue = starter.get_task_queue().to_owned();
|
|
1519
|
+
let workflow_id = wf_name.to_owned();
|
|
1455
1520
|
worker
|
|
1456
|
-
.
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
WorkflowOptions::default(),
|
|
1521
|
+
.submit_workflow(
|
|
1522
|
+
ResourceBasedTunerMetricsWf::run,
|
|
1523
|
+
(),
|
|
1524
|
+
WorkflowStartOptions::new(task_queue, workflow_id).build(),
|
|
1461
1525
|
)
|
|
1462
1526
|
.await
|
|
1463
1527
|
.unwrap();
|
|
@@ -1487,3 +1551,86 @@ async fn resource_based_tuner_metrics() {
|
|
|
1487
1551
|
"CPU PID output metric should be present"
|
|
1488
1552
|
);
|
|
1489
1553
|
}
|
|
1554
|
+
|
|
1555
|
+
#[tokio::test]
|
|
1556
|
+
async fn terminal_metric_not_recorded_on_rejected_completion() {
|
|
1557
|
+
let prom_info = start_prometheus_metric_exporter(
|
|
1558
|
+
PrometheusExporterOptions::builder()
|
|
1559
|
+
.socket_addr(ANY_PORT.parse().unwrap())
|
|
1560
|
+
.build(),
|
|
1561
|
+
)
|
|
1562
|
+
.unwrap();
|
|
1563
|
+
let addr = prom_info.bound_addr;
|
|
1564
|
+
let _abort = prom_info.abort_handle;
|
|
1565
|
+
let meter = TemporalMeter::new(
|
|
1566
|
+
prom_info.meter as Arc<dyn CoreMeter>,
|
|
1567
|
+
NewAttributes { attributes: vec![] },
|
|
1568
|
+
TaskQueueLabelStrategy::UseNormal,
|
|
1569
|
+
);
|
|
1570
|
+
|
|
1571
|
+
// Build a simple workflow history: start + WFT
|
|
1572
|
+
let mut t = TestHistoryBuilder::default();
|
|
1573
|
+
t.add_by_type(
|
|
1574
|
+
temporalio_common::protos::temporal::api::enums::v1::EventType::WorkflowExecutionStarted,
|
|
1575
|
+
);
|
|
1576
|
+
t.add_workflow_task_scheduled_and_started();
|
|
1577
|
+
|
|
1578
|
+
// First WFT completion is rejected by server, second succeeds
|
|
1579
|
+
let mut call_count = 0;
|
|
1580
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
1581
|
+
"fake_wf_id",
|
|
1582
|
+
t,
|
|
1583
|
+
[ResponseType::AllHistory, ResponseType::AllHistory],
|
|
1584
|
+
mock_worker_client(),
|
|
1585
|
+
);
|
|
1586
|
+
mh.completion_mock_fn = Some(Box::new(move |_| {
|
|
1587
|
+
call_count += 1;
|
|
1588
|
+
if call_count == 1 {
|
|
1589
|
+
Err(tonic::Status::not_found("Workflow task not found"))
|
|
1590
|
+
} else {
|
|
1591
|
+
Ok(Default::default())
|
|
1592
|
+
}
|
|
1593
|
+
}));
|
|
1594
|
+
|
|
1595
|
+
let mut mock = build_mock_pollers(mh);
|
|
1596
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
|
|
1597
|
+
mock.set_temporal_meter(meter);
|
|
1598
|
+
let core = mock_worker(mock);
|
|
1599
|
+
|
|
1600
|
+
// First attempt: get WFT activation and complete the workflow
|
|
1601
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
1602
|
+
core.complete_execution(&act.run_id).await;
|
|
1603
|
+
|
|
1604
|
+
// Handle eviction (triggered by NotFound error from server)
|
|
1605
|
+
core.handle_eviction().await;
|
|
1606
|
+
|
|
1607
|
+
// Second attempt (replay after eviction): complete workflow again
|
|
1608
|
+
let act = core.poll_workflow_activation().await.unwrap();
|
|
1609
|
+
core.complete_execution(&act.run_id).await;
|
|
1610
|
+
|
|
1611
|
+
core.drain_pollers_and_shutdown().await;
|
|
1612
|
+
|
|
1613
|
+
// The workflow_completed metric should be recorded exactly once — only for
|
|
1614
|
+
// the successful server response, not for the rejected first attempt.
|
|
1615
|
+
let body = get_text(format!("http://{addr}/metrics")).await;
|
|
1616
|
+
let matching_line = body.lines().find(|l| l.starts_with("workflow_completed{"));
|
|
1617
|
+
match matching_line {
|
|
1618
|
+
Some(line) => {
|
|
1619
|
+
assert!(
|
|
1620
|
+
line.ends_with(" 1"),
|
|
1621
|
+
"Expected workflow_completed count of 1, got: {line}"
|
|
1622
|
+
);
|
|
1623
|
+
assert!(
|
|
1624
|
+
line.contains("workflow_type=\"default_wf_type\""),
|
|
1625
|
+
"Expected workflow_type label on metric, got: {line}"
|
|
1626
|
+
);
|
|
1627
|
+
}
|
|
1628
|
+
None => panic!(
|
|
1629
|
+
"workflow_completed metric not found. Available metrics:\n{}",
|
|
1630
|
+
body.lines()
|
|
1631
|
+
.filter(|l| l.contains("workflow"))
|
|
1632
|
+
.collect::<Vec<_>>()
|
|
1633
|
+
.join("\n")
|
|
1634
|
+
),
|
|
1635
|
+
}
|
|
1636
|
+
}
|