@temporalio/core-bridge 1.13.2 → 1.14.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 +135 -100
- package/Cargo.toml +3 -2
- package/{sdk-core/fsm/rustfsm_trait/LICENSE.txt → LICENSE} +5 -5
- package/README.md +0 -1
- package/bridge-macros/Cargo.toml +16 -0
- package/bridge-macros/src/derive_js_function.rs +126 -0
- package/bridge-macros/src/derive_tryfromjs.rs +138 -0
- package/bridge-macros/src/derive_tryintojs.rs +151 -0
- package/bridge-macros/src/lib.rs +42 -0
- package/lib/native.d.ts +13 -6
- package/package.json +6 -5
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.cargo/config.toml +9 -3
- package/sdk-core/.github/workflows/per-pr.yml +42 -5
- package/sdk-core/AGENTS.md +17 -19
- package/sdk-core/Cargo.toml +6 -7
- package/sdk-core/README.md +12 -15
- package/sdk-core/arch_docs/diagrams/deps.svg +102 -0
- package/sdk-core/{client → crates/client}/Cargo.toml +7 -9
- package/sdk-core/{client → crates/client}/src/lib.rs +110 -159
- package/sdk-core/{client → crates/client}/src/metrics.rs +1 -1
- package/sdk-core/{client → crates/client}/src/raw.rs +73 -44
- package/sdk-core/crates/client/src/request_extensions.rs +40 -0
- package/sdk-core/{client → crates/client}/src/retry.rs +24 -17
- package/sdk-core/crates/client/src/worker/mod.rs +1468 -0
- package/sdk-core/{client → crates/client}/src/workflow_handle/mod.rs +4 -4
- package/sdk-core/{core-api → crates/common}/Cargo.toml +17 -8
- package/sdk-core/crates/common/protos/api_cloud_upstream/VERSION +1 -0
- package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/account/v1/message.proto +18 -0
- package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +38 -11
- package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +21 -4
- package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +6 -6
- package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/sink/v1/message.proto +22 -0
- package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/create-release.yml +5 -0
- package/sdk-core/{core-api → crates/common}/src/envconfig.rs +2 -2
- package/sdk-core/{core-api → crates/common}/src/errors.rs +8 -1
- package/sdk-core/{fsm/rustfsm_trait/src/lib.rs → crates/common/src/fsm_trait.rs} +1 -27
- package/sdk-core/{core-api → crates/common}/src/lib.rs +24 -9
- package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/canned_histories.rs +1 -1
- package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/history_builder.rs +1 -1
- package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/history_info.rs +2 -2
- package/sdk-core/{sdk-core-protos/src/lib.rs → crates/common/src/protos/mod.rs} +18 -17
- package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/test_utils.rs +1 -1
- package/sdk-core/{core-api → crates/common}/src/telemetry/metrics.rs +447 -50
- package/sdk-core/{core-api → crates/common}/src/telemetry.rs +3 -1
- package/sdk-core/{core-api → crates/common}/src/worker.rs +112 -18
- package/sdk-core/crates/common/tests/worker_task_types_test.rs +129 -0
- package/sdk-core/crates/macros/Cargo.toml +23 -0
- package/sdk-core/{fsm/rustfsm_procmacro → crates/macros}/src/lib.rs +6 -11
- package/sdk-core/{sdk → crates/sdk}/Cargo.toml +10 -10
- package/sdk-core/{sdk → crates/sdk}/src/activity_context.rs +8 -6
- package/sdk-core/{sdk → crates/sdk}/src/interceptors.rs +1 -1
- package/sdk-core/{sdk → crates/sdk}/src/lib.rs +42 -37
- package/sdk-core/{sdk → crates/sdk}/src/workflow_context/options.rs +2 -2
- package/sdk-core/{sdk → crates/sdk}/src/workflow_context.rs +21 -19
- package/sdk-core/{sdk → crates/sdk}/src/workflow_future.rs +1 -1
- package/sdk-core/{core → crates/sdk-core}/Cargo.toml +32 -25
- package/sdk-core/{tests → crates/sdk-core/benches}/workflow_replay_bench.rs +10 -10
- package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +32 -0
- package/sdk-core/crates/sdk-core/machine_coverage/CancelExternalMachine_Coverage.puml +9 -0
- package/sdk-core/crates/sdk-core/machine_coverage/CancelWorkflowMachine_Coverage.puml +6 -0
- package/sdk-core/crates/sdk-core/machine_coverage/ChildWorkflowMachine_Coverage.puml +27 -0
- package/sdk-core/crates/sdk-core/machine_coverage/CompleteWorkflowMachine_Coverage.puml +6 -0
- package/sdk-core/crates/sdk-core/machine_coverage/ContinueAsNewWorkflowMachine_Coverage.puml +6 -0
- package/sdk-core/crates/sdk-core/machine_coverage/FailWorkflowMachine_Coverage.puml +6 -0
- package/sdk-core/crates/sdk-core/machine_coverage/LocalActivityMachine_Coverage.puml +23 -0
- package/sdk-core/crates/sdk-core/machine_coverage/ModifyWorkflowPropertiesMachine_Coverage.puml +5 -0
- package/sdk-core/crates/sdk-core/machine_coverage/PatchMachine_Coverage.puml +8 -0
- package/sdk-core/crates/sdk-core/machine_coverage/SignalExternalMachine_Coverage.puml +12 -0
- package/sdk-core/crates/sdk-core/machine_coverage/TimerMachine_Coverage.puml +13 -0
- package/sdk-core/crates/sdk-core/machine_coverage/UpdateMachine_Coverage.puml +19 -0
- package/sdk-core/crates/sdk-core/machine_coverage/UpsertSearchAttributesMachine_Coverage.puml +5 -0
- package/sdk-core/crates/sdk-core/machine_coverage/WorkflowTaskMachine_Coverage.puml +11 -0
- package/sdk-core/{core → crates/sdk-core}/src/abstractions.rs +62 -6
- package/sdk-core/crates/sdk-core/src/antithesis.rs +60 -0
- package/sdk-core/{core → crates/sdk-core}/src/core_tests/activity_tasks.rs +36 -31
- package/sdk-core/{core → crates/sdk-core}/src/core_tests/mod.rs +12 -9
- package/sdk-core/{core → crates/sdk-core}/src/core_tests/queries.rs +24 -21
- package/sdk-core/{core → crates/sdk-core}/src/core_tests/replay_flag.rs +10 -8
- package/sdk-core/{core → crates/sdk-core}/src/core_tests/updates.rs +17 -15
- package/sdk-core/{core → crates/sdk-core}/src/core_tests/workers.rs +242 -17
- package/sdk-core/{core → crates/sdk-core}/src/core_tests/workflow_cancels.rs +1 -1
- package/sdk-core/{core → crates/sdk-core}/src/core_tests/workflow_tasks.rs +126 -39
- package/sdk-core/{core → crates/sdk-core}/src/debug_client.rs +1 -1
- package/sdk-core/{core → crates/sdk-core}/src/ephemeral_server/mod.rs +3 -3
- package/sdk-core/crates/sdk-core/src/histfetch.rs +33 -0
- package/sdk-core/{core → crates/sdk-core}/src/internal_flags.rs +4 -3
- package/sdk-core/{core → crates/sdk-core}/src/lib.rs +85 -43
- package/sdk-core/{core → crates/sdk-core}/src/pollers/mod.rs +8 -6
- package/sdk-core/{core → crates/sdk-core}/src/pollers/poll_buffer.rs +51 -16
- package/sdk-core/{core → crates/sdk-core}/src/protosext/mod.rs +1 -1
- package/sdk-core/{core → crates/sdk-core}/src/protosext/protocol_messages.rs +1 -1
- package/sdk-core/{core → crates/sdk-core}/src/replay/mod.rs +14 -11
- package/sdk-core/{core → crates/sdk-core}/src/retry_logic.rs +19 -1
- package/sdk-core/{core → crates/sdk-core}/src/telemetry/log_export.rs +2 -2
- package/sdk-core/{core → crates/sdk-core}/src/telemetry/metrics.rs +80 -34
- package/sdk-core/{core → crates/sdk-core}/src/telemetry/mod.rs +4 -4
- package/sdk-core/{core → crates/sdk-core}/src/telemetry/otel.rs +1 -1
- package/sdk-core/{core → crates/sdk-core}/src/telemetry/prometheus_meter.rs +13 -13
- package/sdk-core/{core → crates/sdk-core}/src/telemetry/prometheus_server.rs +2 -2
- package/sdk-core/{core → crates/sdk-core}/src/test_help/integ_helpers.rs +127 -40
- package/sdk-core/{core → crates/sdk-core}/src/test_help/unit_helpers.rs +13 -11
- package/sdk-core/{core → crates/sdk-core}/src/worker/activities/activity_heartbeat_manager.rs +2 -2
- package/sdk-core/{core → crates/sdk-core}/src/worker/activities/local_activities.rs +14 -12
- package/sdk-core/{core → crates/sdk-core}/src/worker/activities.rs +21 -12
- package/sdk-core/{core → crates/sdk-core}/src/worker/client/mocks.rs +25 -12
- package/sdk-core/{core → crates/sdk-core}/src/worker/client.rs +164 -71
- package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +246 -0
- package/sdk-core/crates/sdk-core/src/worker/mod.rs +1462 -0
- package/sdk-core/{core → crates/sdk-core}/src/worker/nexus.rs +15 -14
- package/sdk-core/{core → crates/sdk-core}/src/worker/slot_provider.rs +12 -13
- package/sdk-core/{core → crates/sdk-core}/src/worker/tuner/fixed_size.rs +5 -1
- package/sdk-core/{core → crates/sdk-core}/src/worker/tuner/resource_based.rs +453 -57
- package/sdk-core/{core → crates/sdk-core}/src/worker/tuner.rs +21 -4
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/driven_workflow.rs +1 -1
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/history_update.rs +2 -2
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/activity_state_machine.rs +147 -37
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/cancel_external_state_machine.rs +8 -9
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/cancel_nexus_op_state_machine.rs +14 -12
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/cancel_workflow_state_machine.rs +6 -7
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/child_workflow_state_machine.rs +31 -37
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/complete_workflow_state_machine.rs +13 -8
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +6 -7
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/fail_workflow_state_machine.rs +6 -7
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/local_activity_state_machine.rs +33 -30
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/mod.rs +22 -17
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +4 -3
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/nexus_operation_state_machine.rs +20 -22
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/patch_state_machine.rs +12 -11
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/signal_external_state_machine.rs +9 -12
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/timer_state_machine.rs +26 -13
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/transition_coverage.rs +1 -2
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/update_state_machine.rs +19 -13
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +20 -18
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/workflow_machines/local_acts.rs +1 -1
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/workflow_machines.rs +61 -70
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/workflow_task_state_machine.rs +13 -15
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/managed_run.rs +55 -37
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/mod.rs +166 -60
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/run_cache.rs +10 -7
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/wft_extraction.rs +4 -2
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/wft_poller.rs +15 -4
- package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/workflow_stream.rs +30 -16
- package/sdk-core/{tests → crates/sdk-core/tests}/c_bridge_smoke_test.c +1 -1
- package/sdk-core/{tests → crates/sdk-core/tests}/cloud_tests.rs +1 -1
- package/sdk-core/crates/sdk-core/tests/common/fake_grpc_server.rs +106 -0
- package/sdk-core/{tests → crates/sdk-core/tests}/common/http_proxy.rs +1 -1
- package/sdk-core/{tests → crates/sdk-core/tests}/common/mod.rs +93 -74
- package/sdk-core/{tests → crates/sdk-core/tests}/common/workflows.rs +4 -3
- package/sdk-core/crates/sdk-core/tests/fsm_procmacro.rs +6 -0
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/dupe_transitions_fail.rs +1 -3
- package/sdk-core/crates/sdk-core/tests/fsm_trybuild/dupe_transitions_fail.stderr +12 -0
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/dynamic_dest_pass.rs +2 -4
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/forgot_name_fail.rs +1 -3
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/forgot_name_fail.stderr +4 -4
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/handler_arg_pass.rs +2 -4
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/handler_pass.rs +2 -4
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/medium_complex_pass.rs +2 -4
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/no_handle_conversions_require_into_fail.rs +2 -4
- package/sdk-core/crates/sdk-core/tests/fsm_trybuild/no_handle_conversions_require_into_fail.stderr +15 -0
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/simple_pass.rs +2 -4
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/struct_event_variant_fail.rs +1 -3
- package/sdk-core/crates/sdk-core/tests/fsm_trybuild/struct_event_variant_fail.stderr +5 -0
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/tuple_more_item_event_variant_fail.rs +1 -3
- package/sdk-core/crates/sdk-core/tests/fsm_trybuild/tuple_more_item_event_variant_fail.stderr +5 -0
- package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/tuple_zero_item_event_variant_fail.rs +1 -3
- package/sdk-core/crates/sdk-core/tests/fsm_trybuild/tuple_zero_item_event_variant_fail.stderr +5 -0
- package/sdk-core/{tests → crates/sdk-core/tests}/global_metric_tests.rs +14 -15
- package/sdk-core/{tests → crates/sdk-core/tests/heavy_tests}/fuzzy_workflow.rs +3 -3
- package/sdk-core/{tests → crates/sdk-core/tests}/heavy_tests.rs +19 -12
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/activity_functions.rs +1 -1
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/client_tests.rs +16 -111
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/ephemeral_server_tests.rs +5 -6
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/heartbeat_tests.rs +23 -19
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/metrics_tests.rs +134 -60
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/pagination_tests.rs +4 -4
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/polling_tests.rs +37 -36
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/queries_tests.rs +12 -10
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/update_tests.rs +41 -29
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/visibility_tests.rs +24 -19
- package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +1061 -0
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/worker_tests.rs +113 -51
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/worker_versioning_tests.rs +19 -17
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/activities.rs +35 -30
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/appdata_propagation.rs +3 -3
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/cancel_external.rs +14 -9
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/cancel_wf.rs +13 -8
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/child_workflows.rs +48 -35
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/continue_as_new.rs +14 -9
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/determinism.rs +24 -15
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/eager.rs +9 -4
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/local_activities.rs +47 -47
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/modify_wf_properties.rs +16 -11
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/nexus.rs +51 -23
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/patches.rs +22 -10
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/replay.rs +19 -17
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/resets.rs +14 -5
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/signals.rs +24 -15
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/stickyness.rs +8 -6
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/timers.rs +28 -18
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/upsert_search_attrs.rs +18 -13
- package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests.rs +46 -41
- package/sdk-core/{tests → crates/sdk-core/tests}/main.rs +15 -9
- package/sdk-core/{tests → crates/sdk-core/tests}/manual_tests.rs +20 -14
- package/sdk-core/{tests → crates/sdk-core/tests}/runner.rs +2 -2
- package/sdk-core/{tests → crates/sdk-core/tests}/shared_tests/mod.rs +10 -5
- package/sdk-core/{tests → crates/sdk-core/tests}/shared_tests/priority.rs +5 -5
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/Cargo.toml +13 -10
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/include/temporal-sdk-core-c-bridge.h +32 -23
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/client.rs +55 -32
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/envconfig.rs +1 -1
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/lib.rs +1 -1
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/metric.rs +1 -1
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/runtime.rs +24 -9
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/testing.rs +1 -1
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/tests/context.rs +11 -10
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/tests/mod.rs +7 -7
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/tests/utils.rs +3 -4
- package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/worker.rs +111 -58
- package/sdk-core/docker-cgroup-tests.sh +24 -0
- package/sdk-core/{docker → etc/docker}/docker-compose-ci.yaml +9 -9
- package/sdk-core/{docker → etc/docker}/docker-compose-telem.yaml +11 -11
- package/sdk-core/{docker → etc/docker}/docker-compose.yaml +8 -8
- package/sdk-core/{integ-with-otel.sh → etc/integ-with-otel.sh} +1 -1
- package/sdk-core/etc/regen-depgraph.sh +2 -2
- package/src/client.rs +24 -33
- package/src/helpers/try_from_js.rs +1 -1
- package/src/logs.rs +1 -1
- package/src/metrics.rs +3 -3
- package/src/runtime.rs +42 -28
- package/src/testing.rs +3 -3
- package/src/worker.rs +70 -36
- package/ts/native.ts +13 -6
- package/LICENSE.md +0 -23
- package/sdk-core/client/src/worker_registry/mod.rs +0 -282
- package/sdk-core/core/src/worker/heartbeat.rs +0 -230
- package/sdk-core/core/src/worker/mod.rs +0 -990
- package/sdk-core/etc/deps.svg +0 -162
- package/sdk-core/fsm/Cargo.toml +0 -21
- package/sdk-core/fsm/README.md +0 -3
- package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +0 -27
- package/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +0 -21
- package/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +0 -8
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +0 -12
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +0 -15
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +0 -5
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +0 -5
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +0 -5
- package/sdk-core/fsm/rustfsm_trait/Cargo.toml +0 -14
- package/sdk-core/fsm/src/lib.rs +0 -2
- package/sdk-core/sdk-core-protos/Cargo.toml +0 -37
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +0 -1
- /package/sdk-core/{client → crates/client}/src/callback_based.rs +0 -0
- /package/sdk-core/{client → crates/client}/src/proxy.rs +0 -0
- /package/sdk-core/{client → crates/client}/src/replaceable.rs +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/build.rs +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/.github/workflows/build.yaml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/.github/workflows/push-to-buf.yml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/CODEOWNERS +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/LICENSE +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/Makefile +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/README.md +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/buf.gen.yaml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/buf.lock +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/buf.yaml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/connectivityrule/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/nexus/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/resource/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/usage/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/CODEOWNERS +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/ci.yml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/publish-docs.yml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/push-to-buf.yml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/trigger-api-go-delete-release.yml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/trigger-api-go-publish-release.yml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/LICENSE +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/Makefile +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/README.md +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/api-linter.yaml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/buf.gen.yaml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/buf.lock +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/buf.yaml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/api/annotations.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/api/http.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/any.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/descriptor.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/duration.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/empty.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/struct.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/timestamp.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/wrappers.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/openapi/openapiv2.json +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/openapi/openapiv3.yaml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/openapi/payload_description.txt +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/activity/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/batch/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/command/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/common/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/deployment/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/command_type.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/common.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/deployment.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/event_type.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/namespace.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/nexus.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/query.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/reset.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/schedule.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/update.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/workflow.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/errordetails/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/export/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/failure/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/filter/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/history/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/namespace/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/nexus/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/protocol/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/query/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/replication/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/rules/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/schedule/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/enhanced_stack_trace.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/user_metadata.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/worker_config.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/update/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/version/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/worker/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/workflow/v1/message.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/google/rpc/status.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/grpc/health/v1/health.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/activity_result/activity_result.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/activity_task/activity_task.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/common/common.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/core_interface.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/external_data/external_data.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/nexus/nexus.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/Makefile +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/api-linter.yaml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/buf.yaml +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -0
- /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -0
- /package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/constants.rs +0 -0
- /package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/task_token.rs +0 -0
- /package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/utilities.rs +0 -0
- /package/sdk-core/{fsm → crates/macros}/LICENSE.txt +0 -0
- /package/sdk-core/{sdk → crates/sdk}/src/app_data.rs +0 -0
- /package/sdk-core/{core → crates/sdk-core}/src/abstractions/take_cell.rs +0 -0
- /package/sdk-core/{core → crates/sdk-core}/src/test_help/mod.rs +0 -0
- /package/sdk-core/{core → crates/sdk-core}/src/worker/slot_supplier.rs +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/ends_empty_wft_complete.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/evict_while_la_running_no_interference-16_history.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/evict_while_la_running_no_interference-23_history.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/evict_while_la_running_no_interference-85_history.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/fail_wf_task.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-0_history.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-1_history.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-2_history.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-3_history.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/old_change_marker_format.bin +0 -0
- /package/sdk-core/{histories → crates/sdk-core/tests/histories}/timer_workflow_history.bin +0 -0
- /package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/priority.rs +0 -0
- /package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/build.rs +0 -0
- /package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/random.rs +0 -0
- /package/sdk-core/{cargo-tokio-console.sh → etc/cargo-tokio-console.sh} +0 -0
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
use crossbeam_utils::atomic::AtomicCell;
|
|
2
2
|
use parking_lot::Mutex;
|
|
3
3
|
use std::{
|
|
4
|
+
fs,
|
|
4
5
|
marker::PhantomData,
|
|
6
|
+
path::PathBuf,
|
|
5
7
|
sync::{
|
|
6
8
|
Arc, OnceLock,
|
|
7
9
|
atomic::{AtomicU64, AtomicUsize, Ordering},
|
|
10
|
+
mpsc,
|
|
8
11
|
},
|
|
12
|
+
thread,
|
|
9
13
|
time::{Duration, Instant},
|
|
10
14
|
};
|
|
11
|
-
use
|
|
15
|
+
use temporalio_common::{
|
|
12
16
|
telemetry::metrics::{CoreMeter, GaugeF64, MetricAttributes, TemporalMeter},
|
|
13
17
|
worker::{
|
|
14
18
|
ActivitySlotKind, LocalActivitySlotKind, NexusSlotKind, SlotInfo, SlotInfoTrait, SlotKind,
|
|
@@ -31,6 +35,8 @@ pub struct ResourceBasedTuner<MI> {
|
|
|
31
35
|
act_opts: Option<ResourceSlotOptions>,
|
|
32
36
|
la_opts: Option<ResourceSlotOptions>,
|
|
33
37
|
nexus_opts: Option<ResourceSlotOptions>,
|
|
38
|
+
|
|
39
|
+
sys_info: Arc<MI>,
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
impl ResourceBasedTuner<RealSysInfo> {
|
|
@@ -42,25 +48,28 @@ impl ResourceBasedTuner<RealSysInfo> {
|
|
|
42
48
|
.target_cpu_usage(target_cpu_usage)
|
|
43
49
|
.build()
|
|
44
50
|
.expect("default resource based slot options can't fail to build");
|
|
45
|
-
let controller = ResourceController::new_with_sysinfo(opts, RealSysInfo::new());
|
|
51
|
+
let controller = ResourceController::new_with_sysinfo(opts, Arc::new(RealSysInfo::new()));
|
|
46
52
|
Self::new_from_controller(controller)
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
/// Create an instance using the fully configurable set of PID controller options
|
|
50
56
|
pub fn new_from_options(options: ResourceBasedSlotsOptions) -> Self {
|
|
51
|
-
let controller =
|
|
57
|
+
let controller =
|
|
58
|
+
ResourceController::new_with_sysinfo(options, Arc::new(RealSysInfo::new()));
|
|
52
59
|
Self::new_from_controller(controller)
|
|
53
60
|
}
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
impl<MI> ResourceBasedTuner<MI> {
|
|
57
64
|
fn new_from_controller(controller: ResourceController<MI>) -> Self {
|
|
65
|
+
let sys_info = controller.sys_info_supplier.clone();
|
|
58
66
|
Self {
|
|
59
67
|
slots: Arc::new(controller),
|
|
60
68
|
wf_opts: None,
|
|
61
69
|
act_opts: None,
|
|
62
70
|
la_opts: None,
|
|
63
71
|
nexus_opts: None,
|
|
72
|
+
sys_info,
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
75
|
|
|
@@ -87,6 +96,11 @@ impl<MI> ResourceBasedTuner<MI> {
|
|
|
87
96
|
self.nexus_opts = Some(opts);
|
|
88
97
|
self
|
|
89
98
|
}
|
|
99
|
+
|
|
100
|
+
/// Get sys info
|
|
101
|
+
pub fn sys_info(&self) -> Arc<MI> {
|
|
102
|
+
self.sys_info.clone()
|
|
103
|
+
}
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
const DEFAULT_WF_SLOT_OPTS: ResourceSlotOptions = ResourceSlotOptions {
|
|
@@ -121,7 +135,7 @@ pub struct ResourceSlotOptions {
|
|
|
121
135
|
|
|
122
136
|
struct ResourceController<MI> {
|
|
123
137
|
options: ResourceBasedSlotsOptions,
|
|
124
|
-
sys_info_supplier: MI
|
|
138
|
+
sys_info_supplier: Arc<MI>,
|
|
125
139
|
metrics: OnceLock<JoinHandle<()>>,
|
|
126
140
|
pids: Mutex<PidControllers>,
|
|
127
141
|
last_metric_vals: Arc<AtomicCell<LastMetricVals>>,
|
|
@@ -219,14 +233,10 @@ impl PidControllers {
|
|
|
219
233
|
|
|
220
234
|
impl MetricInstruments {
|
|
221
235
|
fn new(meter: TemporalMeter) -> Self {
|
|
222
|
-
let mem_usage = meter.
|
|
223
|
-
let cpu_usage = meter.
|
|
224
|
-
let mem_pid_output = meter
|
|
225
|
-
|
|
226
|
-
.gauge_f64("resource_slots_mem_pid_output".into());
|
|
227
|
-
let cpu_pid_output = meter
|
|
228
|
-
.inner
|
|
229
|
-
.gauge_f64("resource_slots_cpu_pid_output".into());
|
|
236
|
+
let mem_usage = meter.gauge_f64("resource_slots_mem_usage".into());
|
|
237
|
+
let cpu_usage = meter.gauge_f64("resource_slots_cpu_usage".into());
|
|
238
|
+
let mem_pid_output = meter.gauge_f64("resource_slots_mem_pid_output".into());
|
|
239
|
+
let cpu_pid_output = meter.gauge_f64("resource_slots_cpu_pid_output".into());
|
|
230
240
|
let attribs = meter.inner.new_attributes(meter.default_attribs);
|
|
231
241
|
Self {
|
|
232
242
|
attribs,
|
|
@@ -314,6 +324,10 @@ where
|
|
|
314
324
|
}
|
|
315
325
|
}
|
|
316
326
|
}
|
|
327
|
+
|
|
328
|
+
fn slot_supplier_kind(&self) -> String {
|
|
329
|
+
"ResourceBased".to_string()
|
|
330
|
+
}
|
|
317
331
|
}
|
|
318
332
|
|
|
319
333
|
impl<MI, SK> ResourceBasedSlotsForType<MI, SK>
|
|
@@ -421,7 +435,7 @@ impl<MI: SystemResourceInfo + Sync + Send> ResourceController<MI> {
|
|
|
421
435
|
Arc::new(ResourceBasedSlotsForType::new(self.clone(), opts))
|
|
422
436
|
}
|
|
423
437
|
|
|
424
|
-
fn new_with_sysinfo(options: ResourceBasedSlotsOptions, sys_info: MI) -> Self {
|
|
438
|
+
fn new_with_sysinfo(options: ResourceBasedSlotsOptions, sys_info: Arc<MI>) -> Self {
|
|
425
439
|
Self {
|
|
426
440
|
pids: Mutex::new(PidControllers::new(&options)),
|
|
427
441
|
options,
|
|
@@ -474,42 +488,18 @@ impl<MI: SystemResourceInfo + Sync + Send> ResourceController<MI> {
|
|
|
474
488
|
|
|
475
489
|
/// Implements [SystemResourceInfo] using the [sysinfo] crate
|
|
476
490
|
#[derive(Debug)]
|
|
477
|
-
|
|
491
|
+
struct RealSysInfoInner {
|
|
478
492
|
sys: Mutex<sysinfo::System>,
|
|
479
493
|
total_mem: AtomicU64,
|
|
480
494
|
cur_mem_usage: AtomicU64,
|
|
481
495
|
cur_cpu_usage: AtomicU64,
|
|
482
|
-
|
|
496
|
+
cgroup_cpu_info: CGroupCpuInfo<CgroupV2CpuFileSystem>,
|
|
483
497
|
}
|
|
484
|
-
impl RealSysInfo {
|
|
485
|
-
fn new() -> Self {
|
|
486
|
-
let mut sys = sysinfo::System::new();
|
|
487
|
-
sys.refresh_memory();
|
|
488
|
-
let total_mem = sys.total_memory();
|
|
489
|
-
let s = Self {
|
|
490
|
-
sys: Mutex::new(sys),
|
|
491
|
-
last_refresh: AtomicCell::new(Instant::now()),
|
|
492
|
-
cur_mem_usage: AtomicU64::new(0),
|
|
493
|
-
cur_cpu_usage: AtomicU64::new(0),
|
|
494
|
-
total_mem: AtomicU64::new(total_mem),
|
|
495
|
-
};
|
|
496
|
-
s.refresh();
|
|
497
|
-
s
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
fn refresh_if_needed(&self) {
|
|
501
|
-
// This is all quite expensive and meaningfully slows everything down if it's allowed to
|
|
502
|
-
// happen more often. A better approach than a lock would be needed to go faster.
|
|
503
|
-
if (Instant::now() - self.last_refresh.load()) > Duration::from_millis(100) {
|
|
504
|
-
self.refresh();
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
498
|
|
|
499
|
+
impl RealSysInfoInner {
|
|
508
500
|
fn refresh(&self) {
|
|
509
501
|
let mut lock = self.sys.lock();
|
|
510
502
|
lock.refresh_memory();
|
|
511
|
-
lock.refresh_cpu_usage();
|
|
512
|
-
let cpu = lock.global_cpu_usage() as f64 / 100.;
|
|
513
503
|
if let Some(cgroup_limits) = lock.cgroup_limits() {
|
|
514
504
|
self.total_mem
|
|
515
505
|
.store(cgroup_limits.total_memory, Ordering::Release);
|
|
@@ -517,30 +507,220 @@ impl RealSysInfo {
|
|
|
517
507
|
cgroup_limits.total_memory - cgroup_limits.free_memory,
|
|
518
508
|
Ordering::Release,
|
|
519
509
|
);
|
|
510
|
+
|
|
511
|
+
let cpu = self.cgroup_cpu_info.calc_cpu_percent().unwrap_or_else(|| {
|
|
512
|
+
// There won't be a cgroup cpu usage if there is no limit applied to the cgroup
|
|
513
|
+
// or if an error is encountered when reading cpu.stat or cpu.max.
|
|
514
|
+
// In these cases, fallback to global cpu usage.
|
|
515
|
+
lock.refresh_cpu_usage();
|
|
516
|
+
lock.global_cpu_usage() as f64 / 100.
|
|
517
|
+
});
|
|
518
|
+
self.cur_cpu_usage.store(cpu.to_bits(), Ordering::Release);
|
|
520
519
|
} else {
|
|
521
|
-
|
|
522
|
-
|
|
520
|
+
// Always update the total_mem b/c we could transiently fall to host if
|
|
521
|
+
// lock.cgroup_limits() returns None.
|
|
522
|
+
self.total_mem.store(lock.total_memory(), Ordering::Release);
|
|
523
|
+
self.cur_mem_usage
|
|
524
|
+
.store(lock.used_memory(), Ordering::Release);
|
|
525
|
+
|
|
526
|
+
lock.refresh_cpu_usage();
|
|
527
|
+
let cpu = lock.global_cpu_usage() as f64 / 100.;
|
|
528
|
+
self.cur_cpu_usage.store(cpu.to_bits(), Ordering::Release);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/// Tracks host resource usage by refreshing metrics on a background thread.
|
|
534
|
+
pub struct RealSysInfo {
|
|
535
|
+
inner: Arc<RealSysInfoInner>,
|
|
536
|
+
shutdown_tx: mpsc::Sender<()>,
|
|
537
|
+
shutdown_handle: Mutex<Option<thread::JoinHandle<()>>>,
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
impl RealSysInfo {
|
|
541
|
+
pub(crate) fn new() -> Self {
|
|
542
|
+
let mut sys = sysinfo::System::new();
|
|
543
|
+
sys.refresh_memory();
|
|
544
|
+
let total_mem = sys.total_memory();
|
|
545
|
+
let inner = Arc::new(RealSysInfoInner {
|
|
546
|
+
sys: Mutex::new(sys),
|
|
547
|
+
cur_mem_usage: AtomicU64::new(0),
|
|
548
|
+
cur_cpu_usage: AtomicU64::new(0),
|
|
549
|
+
total_mem: AtomicU64::new(total_mem),
|
|
550
|
+
cgroup_cpu_info: CGroupCpuInfo::new(CgroupV2CpuFileSystem),
|
|
551
|
+
});
|
|
552
|
+
inner.refresh();
|
|
553
|
+
|
|
554
|
+
let thread_clone = inner.clone();
|
|
555
|
+
let (tx, rx) = mpsc::channel::<()>();
|
|
556
|
+
let handle = thread::Builder::new()
|
|
557
|
+
.name("temporal-real-sysinfo".to_string())
|
|
558
|
+
.spawn(move || {
|
|
559
|
+
const REFRESH_INTERVAL: Duration = Duration::from_millis(100);
|
|
560
|
+
loop {
|
|
561
|
+
thread_clone.refresh();
|
|
562
|
+
let r = rx.recv_timeout(REFRESH_INTERVAL);
|
|
563
|
+
if matches!(r, Err(mpsc::RecvTimeoutError::Disconnected)) || r.is_ok() {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
})
|
|
568
|
+
.expect("failed to spawn RealSysInfo refresh thread");
|
|
569
|
+
|
|
570
|
+
Self {
|
|
571
|
+
inner,
|
|
572
|
+
shutdown_tx: tx,
|
|
573
|
+
shutdown_handle: Mutex::new(Some(handle)),
|
|
523
574
|
}
|
|
524
|
-
self.cur_cpu_usage.store(cpu.to_bits(), Ordering::Release);
|
|
525
|
-
self.last_refresh.store(Instant::now());
|
|
526
575
|
}
|
|
527
576
|
}
|
|
528
577
|
|
|
529
578
|
impl SystemResourceInfo for RealSysInfo {
|
|
530
579
|
fn total_mem(&self) -> u64 {
|
|
531
|
-
self.total_mem.load(Ordering::Acquire)
|
|
580
|
+
self.inner.total_mem.load(Ordering::Acquire)
|
|
532
581
|
}
|
|
533
582
|
|
|
534
583
|
fn used_mem(&self) -> u64 {
|
|
535
|
-
|
|
536
|
-
// the async reserve
|
|
537
|
-
self.refresh_if_needed();
|
|
538
|
-
self.cur_mem_usage.load(Ordering::Acquire)
|
|
584
|
+
self.inner.cur_mem_usage.load(Ordering::Acquire)
|
|
539
585
|
}
|
|
540
586
|
|
|
541
587
|
fn used_cpu_percent(&self) -> f64 {
|
|
542
|
-
self.
|
|
543
|
-
|
|
588
|
+
f64::from_bits(self.inner.cur_cpu_usage.load(Ordering::Acquire))
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
impl Drop for RealSysInfo {
|
|
593
|
+
fn drop(&mut self) {
|
|
594
|
+
let _res = self.shutdown_tx.send(());
|
|
595
|
+
if let Some(handle) = self.shutdown_handle.lock().take() {
|
|
596
|
+
let _ = handle.join();
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/// Parsed representation of the CPU quota and slice period exposed by the
|
|
602
|
+
/// cgroup `cpu.max` control file.
|
|
603
|
+
#[derive(Debug)]
|
|
604
|
+
struct CGroupCpuLimits {
|
|
605
|
+
quota: CpuQuota,
|
|
606
|
+
period: u64,
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/// Enumerates whether a cgroup enforces a specific CPU quota or allows
|
|
610
|
+
/// unlimited usage.
|
|
611
|
+
#[derive(Debug)]
|
|
612
|
+
enum CpuQuota {
|
|
613
|
+
Unlimited,
|
|
614
|
+
Limited(u64),
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
trait CGroupCpuFileSystem {
|
|
618
|
+
fn read_cpu_stat_file(&self) -> Option<String>;
|
|
619
|
+
fn read_cpu_limit_file(&self) -> Option<String>;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/// Tracks recent cgroup CPU usage statistics while abstracting the backing
|
|
623
|
+
/// filesystem access for ease of testing.
|
|
624
|
+
#[derive(Debug)]
|
|
625
|
+
struct CGroupCpuInfo<T: CGroupCpuFileSystem> {
|
|
626
|
+
prev_cpu_usage: AtomicU64,
|
|
627
|
+
last_refresh: AtomicCell<Option<Instant>>,
|
|
628
|
+
fs: T,
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
impl<T: CGroupCpuFileSystem> CGroupCpuInfo<T> {
|
|
632
|
+
/// Creates a new tracker and immediately primes it by reading the current
|
|
633
|
+
/// CPU usage so future percentage calculations have baseline data.
|
|
634
|
+
fn new(fs: T) -> Self {
|
|
635
|
+
let s = Self {
|
|
636
|
+
last_refresh: AtomicCell::new(None),
|
|
637
|
+
prev_cpu_usage: AtomicU64::new(0),
|
|
638
|
+
fs,
|
|
639
|
+
};
|
|
640
|
+
s.calc_cpu_percent();
|
|
641
|
+
s
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/// Reads the current CPU usage and limits for the cgroup and calculates the usage percentage based on the
|
|
645
|
+
/// limits and the elapsed time from the last calculation. Returns `None` until enough data has been collected
|
|
646
|
+
/// to determine a delta or when quotas are unlimited.
|
|
647
|
+
fn calc_cpu_percent(&self) -> Option<f64> {
|
|
648
|
+
let usage = self.read_cpu_usage()?;
|
|
649
|
+
let limits = self.read_cpus_limit()?;
|
|
650
|
+
|
|
651
|
+
let previous_usage = self.prev_cpu_usage.swap(usage, Ordering::AcqRel);
|
|
652
|
+
let now = Instant::now();
|
|
653
|
+
let last_updated = self.last_refresh.swap(Some(now));
|
|
654
|
+
|
|
655
|
+
if previous_usage > 0
|
|
656
|
+
&& let Some(last_updated) = last_updated
|
|
657
|
+
&& let CpuQuota::Limited(quota) = limits.quota
|
|
658
|
+
&& quota > 0
|
|
659
|
+
{
|
|
660
|
+
let elapsed_us = (now - last_updated).as_micros() as f64;
|
|
661
|
+
let usage_delta = usage.saturating_sub(previous_usage) as f64;
|
|
662
|
+
|
|
663
|
+
let cpu_percent = usage_delta * limits.period as f64 / (quota as f64 * elapsed_us);
|
|
664
|
+
Some(cpu_percent)
|
|
665
|
+
} else {
|
|
666
|
+
None
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/// Reads the usage_usec value from the cpu.stat file as a u64.
|
|
671
|
+
/// Returns None if the file cannot be read or if the value cannot be parsed into u64.
|
|
672
|
+
///
|
|
673
|
+
/// The cpu.stat file is expected to be a multiline file where each line is `key value`
|
|
674
|
+
fn read_cpu_usage(&self) -> Option<u64> {
|
|
675
|
+
let stat = self.fs.read_cpu_stat_file()?;
|
|
676
|
+
stat.lines().find_map(|line| {
|
|
677
|
+
let mut parts = line.split_whitespace();
|
|
678
|
+
match (parts.next(), parts.next()) {
|
|
679
|
+
(Some("usage_usec"), Some(value)) => value.parse::<u64>().ok(),
|
|
680
|
+
_ => None,
|
|
681
|
+
}
|
|
682
|
+
})
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/// Reads the cpu quota and period from the cpu.max file.
|
|
686
|
+
/// Returns None if the file cannot be read, or the quota/limit cannot be parsed
|
|
687
|
+
///
|
|
688
|
+
/// The cpu.max file is expected to be in the format 'quota period'
|
|
689
|
+
fn read_cpus_limit(&self) -> Option<CGroupCpuLimits> {
|
|
690
|
+
let limit_text = self.fs.read_cpu_limit_file()?;
|
|
691
|
+
let mut parts = limit_text.split_whitespace();
|
|
692
|
+
let quota_str = parts.next()?;
|
|
693
|
+
let period_str = parts.next()?;
|
|
694
|
+
|
|
695
|
+
let quota = if quota_str == "max" {
|
|
696
|
+
CpuQuota::Unlimited
|
|
697
|
+
} else {
|
|
698
|
+
CpuQuota::Limited(quota_str.parse().ok()?)
|
|
699
|
+
};
|
|
700
|
+
let period = period_str.parse().ok()?;
|
|
701
|
+
|
|
702
|
+
Some(CGroupCpuLimits { quota, period })
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/// Implementation of the `CGroupCpuFileSystem` that reads directly
|
|
707
|
+
/// from the host cgroup v2 hierarchy.
|
|
708
|
+
#[derive(Debug)]
|
|
709
|
+
struct CgroupV2CpuFileSystem;
|
|
710
|
+
|
|
711
|
+
impl CgroupV2CpuFileSystem {
|
|
712
|
+
const BASE_PATH: &'static str = "/sys/fs/cgroup";
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
impl CGroupCpuFileSystem for CgroupV2CpuFileSystem {
|
|
716
|
+
fn read_cpu_stat_file(&self) -> Option<String> {
|
|
717
|
+
let path = PathBuf::from(Self::BASE_PATH).join("cpu.stat");
|
|
718
|
+
fs::read_to_string(path).ok()
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
fn read_cpu_limit_file(&self) -> Option<String> {
|
|
722
|
+
let path = PathBuf::from(Self::BASE_PATH).join("cpu.max");
|
|
723
|
+
fs::read_to_string(path).ok()
|
|
544
724
|
}
|
|
545
725
|
}
|
|
546
726
|
|
|
@@ -548,19 +728,26 @@ impl SystemResourceInfo for RealSysInfo {
|
|
|
548
728
|
mod tests {
|
|
549
729
|
use super::*;
|
|
550
730
|
use crate::{abstractions::MeteredPermitDealer, telemetry::metrics::MetricsContext};
|
|
551
|
-
use std::
|
|
552
|
-
|
|
553
|
-
|
|
731
|
+
use std::{
|
|
732
|
+
cell::RefCell,
|
|
733
|
+
env,
|
|
734
|
+
hint::black_box,
|
|
735
|
+
rc::Rc,
|
|
736
|
+
sync::{
|
|
737
|
+
Arc,
|
|
738
|
+
atomic::{AtomicU64, Ordering},
|
|
739
|
+
},
|
|
740
|
+
thread::sleep,
|
|
554
741
|
};
|
|
555
|
-
use
|
|
742
|
+
use temporalio_common::worker::WorkflowSlotKind;
|
|
556
743
|
|
|
557
744
|
struct FakeMIS {
|
|
558
745
|
used: Arc<AtomicU64>,
|
|
559
746
|
}
|
|
560
747
|
impl FakeMIS {
|
|
561
|
-
fn new() -> (Self
|
|
748
|
+
fn new() -> (Arc<Self>, Arc<AtomicU64>) {
|
|
562
749
|
let used = Arc::new(AtomicU64::new(0));
|
|
563
|
-
(Self { used: used.clone() }, used)
|
|
750
|
+
(Arc::new(Self { used: used.clone() }), used)
|
|
564
751
|
}
|
|
565
752
|
}
|
|
566
753
|
impl SystemResourceInfo for FakeMIS {
|
|
@@ -727,4 +914,213 @@ mod tests {
|
|
|
727
914
|
let _p2 = pd.try_acquire_owned().unwrap();
|
|
728
915
|
assert!(pd.try_acquire_owned().is_err());
|
|
729
916
|
}
|
|
917
|
+
|
|
918
|
+
#[derive(Clone)]
|
|
919
|
+
struct FakeCGroupFS {
|
|
920
|
+
stat: Rc<RefCell<Option<String>>>,
|
|
921
|
+
limit: Rc<RefCell<Option<String>>>,
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
impl FakeCGroupFS {
|
|
925
|
+
fn new(stat: Rc<RefCell<Option<String>>>, limit: Rc<RefCell<Option<String>>>) -> Self {
|
|
926
|
+
Self { stat, limit }
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
impl CGroupCpuFileSystem for FakeCGroupFS {
|
|
931
|
+
fn read_cpu_stat_file(&self) -> Option<String> {
|
|
932
|
+
self.stat.borrow().clone()
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
fn read_cpu_limit_file(&self) -> Option<String> {
|
|
936
|
+
self.limit.borrow().clone()
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
#[test]
|
|
941
|
+
fn cgroup_quota_respected() {
|
|
942
|
+
let stat = Rc::new(RefCell::new(Some("usage_usec 500".into())));
|
|
943
|
+
let limit = Rc::new(RefCell::new(Some("1000 1000".into())));
|
|
944
|
+
let fake_fs = FakeCGroupFS::new(stat.clone(), limit.clone());
|
|
945
|
+
|
|
946
|
+
let cgroup_info = CGroupCpuInfo::new(fake_fs);
|
|
947
|
+
|
|
948
|
+
std::thread::sleep(Duration::from_micros(1_000_u64));
|
|
949
|
+
|
|
950
|
+
// No additional usage -> percentage should resolve to exactly zero.
|
|
951
|
+
assert_eq!(Some(0.0), cgroup_info.calc_cpu_percent());
|
|
952
|
+
|
|
953
|
+
// Add some usage such that it we should be above 0, but < 1
|
|
954
|
+
stat.replace(Some("usage_usec 1000".into()));
|
|
955
|
+
std::thread::sleep(Duration::from_micros(1_000_u64));
|
|
956
|
+
|
|
957
|
+
let cpu_percent = cgroup_info
|
|
958
|
+
.calc_cpu_percent()
|
|
959
|
+
.expect("expected usage value");
|
|
960
|
+
assert!(
|
|
961
|
+
cpu_percent > 0. && cpu_percent < 1.0,
|
|
962
|
+
"epected cpu usage between (0.0, 1.0)"
|
|
963
|
+
);
|
|
964
|
+
|
|
965
|
+
// Simulate a large usage increase that should saturate the quota.
|
|
966
|
+
stat.replace(Some("usage_usec 1000000".into()));
|
|
967
|
+
|
|
968
|
+
let cpu_percent = cgroup_info
|
|
969
|
+
.calc_cpu_percent()
|
|
970
|
+
.expect("expected usage value");
|
|
971
|
+
assert!(
|
|
972
|
+
cpu_percent > 1.0,
|
|
973
|
+
"expected cpu usage greater than 1.0, got {cpu_percent}"
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
#[test]
|
|
978
|
+
fn cgroup_unlimited_quota_is_ignored() {
|
|
979
|
+
let stat = Rc::new(RefCell::new(Some("usage_usec 1000".into())));
|
|
980
|
+
let limit = Rc::new(RefCell::new(Some("max 1000".into())));
|
|
981
|
+
|
|
982
|
+
let cgroup_info = CGroupCpuInfo::new(FakeCGroupFS::new(stat.clone(), limit.clone()));
|
|
983
|
+
|
|
984
|
+
std::thread::sleep(Duration::from_micros(1_000_u64));
|
|
985
|
+
|
|
986
|
+
// Unlimited quota is treated as disabled regardless of usage.
|
|
987
|
+
assert!(cgroup_info.calc_cpu_percent().is_none());
|
|
988
|
+
stat.replace(Some("usage_usec 2000".into()));
|
|
989
|
+
|
|
990
|
+
std::thread::sleep(Duration::from_micros(1_000_u64));
|
|
991
|
+
assert!(cgroup_info.calc_cpu_percent().is_none());
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
#[test]
|
|
995
|
+
fn cgroup_stat_file_temporarily_unavailable() {
|
|
996
|
+
let stat = Rc::new(RefCell::new(None));
|
|
997
|
+
let limit = Rc::new(RefCell::new(Some("1000 1000".into())));
|
|
998
|
+
|
|
999
|
+
let cgroup_info = CGroupCpuInfo::new(FakeCGroupFS::new(stat.clone(), limit.clone()));
|
|
1000
|
+
|
|
1001
|
+
std::thread::sleep(Duration::from_micros(1_000_u64));
|
|
1002
|
+
|
|
1003
|
+
assert!(cgroup_info.calc_cpu_percent().is_none());
|
|
1004
|
+
|
|
1005
|
+
// When available, the next call finishes initialization
|
|
1006
|
+
stat.replace(Some("usage_usec 1000".into()));
|
|
1007
|
+
std::thread::sleep(Duration::from_micros(1_000_u64));
|
|
1008
|
+
assert!(cgroup_info.calc_cpu_percent().is_none());
|
|
1009
|
+
|
|
1010
|
+
// A third call properly calculates percentage
|
|
1011
|
+
stat.replace(Some("usage_usec 1500".into()));
|
|
1012
|
+
std::thread::sleep(Duration::from_micros(1_000_u64));
|
|
1013
|
+
let cpu_percent = cgroup_info
|
|
1014
|
+
.calc_cpu_percent()
|
|
1015
|
+
.expect("expected usage value");
|
|
1016
|
+
assert!(cpu_percent > 0., "expected cpu percent > 0");
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
#[test]
|
|
1020
|
+
fn cgroup_realsysinfo_uses_cgroup_limits_cpu() {
|
|
1021
|
+
if env::var("CGROUP_TESTS_ENABLED").is_err() {
|
|
1022
|
+
eprintln!("Skipping: cgroup tests not enabled");
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
let sys_info = RealSysInfo::new();
|
|
1027
|
+
let cgroup_info = CGroupCpuInfo::new(CgroupV2CpuFileSystem);
|
|
1028
|
+
let CGroupCpuLimits { quota, period } = cgroup_info
|
|
1029
|
+
.read_cpus_limit()
|
|
1030
|
+
.expect("unable to read cpu quota.");
|
|
1031
|
+
|
|
1032
|
+
let CpuQuota::Limited(limit) = quota else {
|
|
1033
|
+
eprintln!("Skipping: cpu quota reported unlimited");
|
|
1034
|
+
return;
|
|
1035
|
+
};
|
|
1036
|
+
|
|
1037
|
+
// Prime the internal CPU tracker with some activity.
|
|
1038
|
+
let baseline_time = Instant::now();
|
|
1039
|
+
let prev_usage = cgroup_info
|
|
1040
|
+
.read_cpu_usage()
|
|
1041
|
+
.expect("unable to read cpu usage baseline");
|
|
1042
|
+
|
|
1043
|
+
// Consume some CPU so that the next refresh observes a measurable delta.
|
|
1044
|
+
burn_cpu(Duration::from_millis(300));
|
|
1045
|
+
|
|
1046
|
+
let cpu_usage = sys_info.used_cpu_percent();
|
|
1047
|
+
let measurement_end = Instant::now();
|
|
1048
|
+
let current_usage = cgroup_info
|
|
1049
|
+
.read_cpu_usage()
|
|
1050
|
+
.expect("unable to read cpu usage after refresh");
|
|
1051
|
+
|
|
1052
|
+
let elapsed_us = measurement_end.duration_since(baseline_time).as_micros() as f64;
|
|
1053
|
+
let usage_delta = current_usage.saturating_sub(prev_usage) as f64;
|
|
1054
|
+
assert!(usage_delta > 0.0, "zero cpu usage delta observed");
|
|
1055
|
+
|
|
1056
|
+
let expected_cpu = usage_delta * period as f64 / (limit as f64 * elapsed_us);
|
|
1057
|
+
let cpu_diff = (cpu_usage - expected_cpu).abs();
|
|
1058
|
+
const CPU_TOLERANCE: f64 = 0.3;
|
|
1059
|
+
assert!(
|
|
1060
|
+
cpu_diff <= CPU_TOLERANCE,
|
|
1061
|
+
"RealSysInfo CPU percent {cpu_usage:.3} diverged from cgroup calculation \
|
|
1062
|
+
{expected_cpu:.3} by {cpu_diff:.3}"
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
#[test]
|
|
1067
|
+
fn cgroup_realsysinfo_uses_cgroup_limits_mem() {
|
|
1068
|
+
if env::var("CGROUP_TESTS_ENABLED").is_err() {
|
|
1069
|
+
eprintln!("Skipping: cgroup tests not enabled");
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
let mut sys = sysinfo::System::new();
|
|
1074
|
+
sys.refresh_memory();
|
|
1075
|
+
let current_mem = sys
|
|
1076
|
+
.cgroup_limits()
|
|
1077
|
+
.expect("unable to read cgroup memory details");
|
|
1078
|
+
|
|
1079
|
+
if current_mem.total_memory == sys.total_memory() {
|
|
1080
|
+
eprintln!("Skipping: no memory limit detected. limit == total host memory");
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
let sys_info = RealSysInfo::new();
|
|
1085
|
+
|
|
1086
|
+
assert_eq!(
|
|
1087
|
+
sys_info.total_mem(),
|
|
1088
|
+
current_mem.total_memory, // sysinfo::System does min(cgroup limit, host total) internally
|
|
1089
|
+
"RealSysInfo total_mem should equal min(cgroup limit, host total)"
|
|
1090
|
+
);
|
|
1091
|
+
|
|
1092
|
+
let cur_used = current_mem
|
|
1093
|
+
.total_memory
|
|
1094
|
+
.saturating_sub(current_mem.free_memory);
|
|
1095
|
+
let half_total = current_mem.total_memory / 2;
|
|
1096
|
+
let expected_percentage = if cur_used > half_total {
|
|
1097
|
+
cur_used as f64 / current_mem.total_memory as f64
|
|
1098
|
+
} else {
|
|
1099
|
+
0.5
|
|
1100
|
+
};
|
|
1101
|
+
// allocate to half of memory
|
|
1102
|
+
let to_allocate: usize = (half_total).saturating_sub(cur_used) as usize;
|
|
1103
|
+
let _buf = black_box(vec![1u8; to_allocate]);
|
|
1104
|
+
|
|
1105
|
+
// make sure we sleep enough to let real_sys_info need a refresh
|
|
1106
|
+
sleep(Duration::from_millis(200));
|
|
1107
|
+
|
|
1108
|
+
let percentage = sys_info.used_mem_percent();
|
|
1109
|
+
let diff = (percentage - expected_percentage).abs();
|
|
1110
|
+
|
|
1111
|
+
assert!(
|
|
1112
|
+
diff < 0.2,
|
|
1113
|
+
"RealSysInfo used_mem_percentage should be ~= {}%",
|
|
1114
|
+
expected_percentage * 100.0
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
fn burn_cpu(duration: Duration) {
|
|
1119
|
+
let start = Instant::now();
|
|
1120
|
+
let mut value: u64 = 0;
|
|
1121
|
+
while start.elapsed() < duration {
|
|
1122
|
+
value = value.wrapping_add(1);
|
|
1123
|
+
black_box(value);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
730
1126
|
}
|