@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.
Files changed (388) hide show
  1. package/Cargo.lock +135 -100
  2. package/Cargo.toml +3 -2
  3. package/{sdk-core/fsm/rustfsm_trait/LICENSE.txt → LICENSE} +5 -5
  4. package/README.md +0 -1
  5. package/bridge-macros/Cargo.toml +16 -0
  6. package/bridge-macros/src/derive_js_function.rs +126 -0
  7. package/bridge-macros/src/derive_tryfromjs.rs +138 -0
  8. package/bridge-macros/src/derive_tryintojs.rs +151 -0
  9. package/bridge-macros/src/lib.rs +42 -0
  10. package/lib/native.d.ts +13 -6
  11. package/package.json +6 -5
  12. package/releases/aarch64-apple-darwin/index.node +0 -0
  13. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  14. package/releases/x86_64-apple-darwin/index.node +0 -0
  15. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  16. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  17. package/sdk-core/.cargo/config.toml +9 -3
  18. package/sdk-core/.github/workflows/per-pr.yml +42 -5
  19. package/sdk-core/AGENTS.md +17 -19
  20. package/sdk-core/Cargo.toml +6 -7
  21. package/sdk-core/README.md +12 -15
  22. package/sdk-core/arch_docs/diagrams/deps.svg +102 -0
  23. package/sdk-core/{client → crates/client}/Cargo.toml +7 -9
  24. package/sdk-core/{client → crates/client}/src/lib.rs +110 -159
  25. package/sdk-core/{client → crates/client}/src/metrics.rs +1 -1
  26. package/sdk-core/{client → crates/client}/src/raw.rs +73 -44
  27. package/sdk-core/crates/client/src/request_extensions.rs +40 -0
  28. package/sdk-core/{client → crates/client}/src/retry.rs +24 -17
  29. package/sdk-core/crates/client/src/worker/mod.rs +1468 -0
  30. package/sdk-core/{client → crates/client}/src/workflow_handle/mod.rs +4 -4
  31. package/sdk-core/{core-api → crates/common}/Cargo.toml +17 -8
  32. package/sdk-core/crates/common/protos/api_cloud_upstream/VERSION +1 -0
  33. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/account/v1/message.proto +18 -0
  34. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +38 -11
  35. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +21 -4
  36. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +6 -6
  37. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/sink/v1/message.proto +22 -0
  38. package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/create-release.yml +5 -0
  39. package/sdk-core/{core-api → crates/common}/src/envconfig.rs +2 -2
  40. package/sdk-core/{core-api → crates/common}/src/errors.rs +8 -1
  41. package/sdk-core/{fsm/rustfsm_trait/src/lib.rs → crates/common/src/fsm_trait.rs} +1 -27
  42. package/sdk-core/{core-api → crates/common}/src/lib.rs +24 -9
  43. package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/canned_histories.rs +1 -1
  44. package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/history_builder.rs +1 -1
  45. package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/history_info.rs +2 -2
  46. package/sdk-core/{sdk-core-protos/src/lib.rs → crates/common/src/protos/mod.rs} +18 -17
  47. package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/test_utils.rs +1 -1
  48. package/sdk-core/{core-api → crates/common}/src/telemetry/metrics.rs +447 -50
  49. package/sdk-core/{core-api → crates/common}/src/telemetry.rs +3 -1
  50. package/sdk-core/{core-api → crates/common}/src/worker.rs +112 -18
  51. package/sdk-core/crates/common/tests/worker_task_types_test.rs +129 -0
  52. package/sdk-core/crates/macros/Cargo.toml +23 -0
  53. package/sdk-core/{fsm/rustfsm_procmacro → crates/macros}/src/lib.rs +6 -11
  54. package/sdk-core/{sdk → crates/sdk}/Cargo.toml +10 -10
  55. package/sdk-core/{sdk → crates/sdk}/src/activity_context.rs +8 -6
  56. package/sdk-core/{sdk → crates/sdk}/src/interceptors.rs +1 -1
  57. package/sdk-core/{sdk → crates/sdk}/src/lib.rs +42 -37
  58. package/sdk-core/{sdk → crates/sdk}/src/workflow_context/options.rs +2 -2
  59. package/sdk-core/{sdk → crates/sdk}/src/workflow_context.rs +21 -19
  60. package/sdk-core/{sdk → crates/sdk}/src/workflow_future.rs +1 -1
  61. package/sdk-core/{core → crates/sdk-core}/Cargo.toml +32 -25
  62. package/sdk-core/{tests → crates/sdk-core/benches}/workflow_replay_bench.rs +10 -10
  63. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +32 -0
  64. package/sdk-core/crates/sdk-core/machine_coverage/CancelExternalMachine_Coverage.puml +9 -0
  65. package/sdk-core/crates/sdk-core/machine_coverage/CancelWorkflowMachine_Coverage.puml +6 -0
  66. package/sdk-core/crates/sdk-core/machine_coverage/ChildWorkflowMachine_Coverage.puml +27 -0
  67. package/sdk-core/crates/sdk-core/machine_coverage/CompleteWorkflowMachine_Coverage.puml +6 -0
  68. package/sdk-core/crates/sdk-core/machine_coverage/ContinueAsNewWorkflowMachine_Coverage.puml +6 -0
  69. package/sdk-core/crates/sdk-core/machine_coverage/FailWorkflowMachine_Coverage.puml +6 -0
  70. package/sdk-core/crates/sdk-core/machine_coverage/LocalActivityMachine_Coverage.puml +23 -0
  71. package/sdk-core/crates/sdk-core/machine_coverage/ModifyWorkflowPropertiesMachine_Coverage.puml +5 -0
  72. package/sdk-core/crates/sdk-core/machine_coverage/PatchMachine_Coverage.puml +8 -0
  73. package/sdk-core/crates/sdk-core/machine_coverage/SignalExternalMachine_Coverage.puml +12 -0
  74. package/sdk-core/crates/sdk-core/machine_coverage/TimerMachine_Coverage.puml +13 -0
  75. package/sdk-core/crates/sdk-core/machine_coverage/UpdateMachine_Coverage.puml +19 -0
  76. package/sdk-core/crates/sdk-core/machine_coverage/UpsertSearchAttributesMachine_Coverage.puml +5 -0
  77. package/sdk-core/crates/sdk-core/machine_coverage/WorkflowTaskMachine_Coverage.puml +11 -0
  78. package/sdk-core/{core → crates/sdk-core}/src/abstractions.rs +62 -6
  79. package/sdk-core/crates/sdk-core/src/antithesis.rs +60 -0
  80. package/sdk-core/{core → crates/sdk-core}/src/core_tests/activity_tasks.rs +36 -31
  81. package/sdk-core/{core → crates/sdk-core}/src/core_tests/mod.rs +12 -9
  82. package/sdk-core/{core → crates/sdk-core}/src/core_tests/queries.rs +24 -21
  83. package/sdk-core/{core → crates/sdk-core}/src/core_tests/replay_flag.rs +10 -8
  84. package/sdk-core/{core → crates/sdk-core}/src/core_tests/updates.rs +17 -15
  85. package/sdk-core/{core → crates/sdk-core}/src/core_tests/workers.rs +242 -17
  86. package/sdk-core/{core → crates/sdk-core}/src/core_tests/workflow_cancels.rs +1 -1
  87. package/sdk-core/{core → crates/sdk-core}/src/core_tests/workflow_tasks.rs +126 -39
  88. package/sdk-core/{core → crates/sdk-core}/src/debug_client.rs +1 -1
  89. package/sdk-core/{core → crates/sdk-core}/src/ephemeral_server/mod.rs +3 -3
  90. package/sdk-core/crates/sdk-core/src/histfetch.rs +33 -0
  91. package/sdk-core/{core → crates/sdk-core}/src/internal_flags.rs +4 -3
  92. package/sdk-core/{core → crates/sdk-core}/src/lib.rs +85 -43
  93. package/sdk-core/{core → crates/sdk-core}/src/pollers/mod.rs +8 -6
  94. package/sdk-core/{core → crates/sdk-core}/src/pollers/poll_buffer.rs +51 -16
  95. package/sdk-core/{core → crates/sdk-core}/src/protosext/mod.rs +1 -1
  96. package/sdk-core/{core → crates/sdk-core}/src/protosext/protocol_messages.rs +1 -1
  97. package/sdk-core/{core → crates/sdk-core}/src/replay/mod.rs +14 -11
  98. package/sdk-core/{core → crates/sdk-core}/src/retry_logic.rs +19 -1
  99. package/sdk-core/{core → crates/sdk-core}/src/telemetry/log_export.rs +2 -2
  100. package/sdk-core/{core → crates/sdk-core}/src/telemetry/metrics.rs +80 -34
  101. package/sdk-core/{core → crates/sdk-core}/src/telemetry/mod.rs +4 -4
  102. package/sdk-core/{core → crates/sdk-core}/src/telemetry/otel.rs +1 -1
  103. package/sdk-core/{core → crates/sdk-core}/src/telemetry/prometheus_meter.rs +13 -13
  104. package/sdk-core/{core → crates/sdk-core}/src/telemetry/prometheus_server.rs +2 -2
  105. package/sdk-core/{core → crates/sdk-core}/src/test_help/integ_helpers.rs +127 -40
  106. package/sdk-core/{core → crates/sdk-core}/src/test_help/unit_helpers.rs +13 -11
  107. package/sdk-core/{core → crates/sdk-core}/src/worker/activities/activity_heartbeat_manager.rs +2 -2
  108. package/sdk-core/{core → crates/sdk-core}/src/worker/activities/local_activities.rs +14 -12
  109. package/sdk-core/{core → crates/sdk-core}/src/worker/activities.rs +21 -12
  110. package/sdk-core/{core → crates/sdk-core}/src/worker/client/mocks.rs +25 -12
  111. package/sdk-core/{core → crates/sdk-core}/src/worker/client.rs +164 -71
  112. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +246 -0
  113. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1462 -0
  114. package/sdk-core/{core → crates/sdk-core}/src/worker/nexus.rs +15 -14
  115. package/sdk-core/{core → crates/sdk-core}/src/worker/slot_provider.rs +12 -13
  116. package/sdk-core/{core → crates/sdk-core}/src/worker/tuner/fixed_size.rs +5 -1
  117. package/sdk-core/{core → crates/sdk-core}/src/worker/tuner/resource_based.rs +453 -57
  118. package/sdk-core/{core → crates/sdk-core}/src/worker/tuner.rs +21 -4
  119. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/driven_workflow.rs +1 -1
  120. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/history_update.rs +2 -2
  121. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/activity_state_machine.rs +147 -37
  122. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/cancel_external_state_machine.rs +8 -9
  123. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/cancel_nexus_op_state_machine.rs +14 -12
  124. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/cancel_workflow_state_machine.rs +6 -7
  125. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/child_workflow_state_machine.rs +31 -37
  126. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/complete_workflow_state_machine.rs +13 -8
  127. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +6 -7
  128. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/fail_workflow_state_machine.rs +6 -7
  129. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/local_activity_state_machine.rs +33 -30
  130. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/mod.rs +22 -17
  131. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +4 -3
  132. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/nexus_operation_state_machine.rs +20 -22
  133. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/patch_state_machine.rs +12 -11
  134. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/signal_external_state_machine.rs +9 -12
  135. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/timer_state_machine.rs +26 -13
  136. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/transition_coverage.rs +1 -2
  137. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/update_state_machine.rs +19 -13
  138. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +20 -18
  139. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/workflow_machines/local_acts.rs +1 -1
  140. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/workflow_machines.rs +61 -70
  141. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/machines/workflow_task_state_machine.rs +13 -15
  142. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/managed_run.rs +55 -37
  143. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/mod.rs +166 -60
  144. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/run_cache.rs +10 -7
  145. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/wft_extraction.rs +4 -2
  146. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/wft_poller.rs +15 -4
  147. package/sdk-core/{core → crates/sdk-core}/src/worker/workflow/workflow_stream.rs +30 -16
  148. package/sdk-core/{tests → crates/sdk-core/tests}/c_bridge_smoke_test.c +1 -1
  149. package/sdk-core/{tests → crates/sdk-core/tests}/cloud_tests.rs +1 -1
  150. package/sdk-core/crates/sdk-core/tests/common/fake_grpc_server.rs +106 -0
  151. package/sdk-core/{tests → crates/sdk-core/tests}/common/http_proxy.rs +1 -1
  152. package/sdk-core/{tests → crates/sdk-core/tests}/common/mod.rs +93 -74
  153. package/sdk-core/{tests → crates/sdk-core/tests}/common/workflows.rs +4 -3
  154. package/sdk-core/crates/sdk-core/tests/fsm_procmacro.rs +6 -0
  155. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/dupe_transitions_fail.rs +1 -3
  156. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/dupe_transitions_fail.stderr +12 -0
  157. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/dynamic_dest_pass.rs +2 -4
  158. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/forgot_name_fail.rs +1 -3
  159. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/forgot_name_fail.stderr +4 -4
  160. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/handler_arg_pass.rs +2 -4
  161. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/handler_pass.rs +2 -4
  162. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/medium_complex_pass.rs +2 -4
  163. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/no_handle_conversions_require_into_fail.rs +2 -4
  164. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/no_handle_conversions_require_into_fail.stderr +15 -0
  165. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/simple_pass.rs +2 -4
  166. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/struct_event_variant_fail.rs +1 -3
  167. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/struct_event_variant_fail.stderr +5 -0
  168. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/tuple_more_item_event_variant_fail.rs +1 -3
  169. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/tuple_more_item_event_variant_fail.stderr +5 -0
  170. package/sdk-core/{fsm/rustfsm_procmacro/tests/trybuild → crates/sdk-core/tests/fsm_trybuild}/tuple_zero_item_event_variant_fail.rs +1 -3
  171. package/sdk-core/crates/sdk-core/tests/fsm_trybuild/tuple_zero_item_event_variant_fail.stderr +5 -0
  172. package/sdk-core/{tests → crates/sdk-core/tests}/global_metric_tests.rs +14 -15
  173. package/sdk-core/{tests → crates/sdk-core/tests/heavy_tests}/fuzzy_workflow.rs +3 -3
  174. package/sdk-core/{tests → crates/sdk-core/tests}/heavy_tests.rs +19 -12
  175. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/activity_functions.rs +1 -1
  176. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/client_tests.rs +16 -111
  177. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/ephemeral_server_tests.rs +5 -6
  178. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/heartbeat_tests.rs +23 -19
  179. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/metrics_tests.rs +134 -60
  180. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/pagination_tests.rs +4 -4
  181. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/polling_tests.rs +37 -36
  182. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/queries_tests.rs +12 -10
  183. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/update_tests.rs +41 -29
  184. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/visibility_tests.rs +24 -19
  185. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +1061 -0
  186. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/worker_tests.rs +113 -51
  187. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/worker_versioning_tests.rs +19 -17
  188. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/activities.rs +35 -30
  189. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/appdata_propagation.rs +3 -3
  190. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/cancel_external.rs +14 -9
  191. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/cancel_wf.rs +13 -8
  192. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/child_workflows.rs +48 -35
  193. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/continue_as_new.rs +14 -9
  194. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/determinism.rs +24 -15
  195. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/eager.rs +9 -4
  196. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/local_activities.rs +47 -47
  197. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/modify_wf_properties.rs +16 -11
  198. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/nexus.rs +51 -23
  199. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/patches.rs +22 -10
  200. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/replay.rs +19 -17
  201. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/resets.rs +14 -5
  202. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/signals.rs +24 -15
  203. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/stickyness.rs +8 -6
  204. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/timers.rs +28 -18
  205. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/upsert_search_attrs.rs +18 -13
  206. package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests.rs +46 -41
  207. package/sdk-core/{tests → crates/sdk-core/tests}/main.rs +15 -9
  208. package/sdk-core/{tests → crates/sdk-core/tests}/manual_tests.rs +20 -14
  209. package/sdk-core/{tests → crates/sdk-core/tests}/runner.rs +2 -2
  210. package/sdk-core/{tests → crates/sdk-core/tests}/shared_tests/mod.rs +10 -5
  211. package/sdk-core/{tests → crates/sdk-core/tests}/shared_tests/priority.rs +5 -5
  212. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/Cargo.toml +13 -10
  213. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/include/temporal-sdk-core-c-bridge.h +32 -23
  214. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/client.rs +55 -32
  215. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/envconfig.rs +1 -1
  216. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/lib.rs +1 -1
  217. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/metric.rs +1 -1
  218. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/runtime.rs +24 -9
  219. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/testing.rs +1 -1
  220. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/tests/context.rs +11 -10
  221. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/tests/mod.rs +7 -7
  222. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/tests/utils.rs +3 -4
  223. package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/worker.rs +111 -58
  224. package/sdk-core/docker-cgroup-tests.sh +24 -0
  225. package/sdk-core/{docker → etc/docker}/docker-compose-ci.yaml +9 -9
  226. package/sdk-core/{docker → etc/docker}/docker-compose-telem.yaml +11 -11
  227. package/sdk-core/{docker → etc/docker}/docker-compose.yaml +8 -8
  228. package/sdk-core/{integ-with-otel.sh → etc/integ-with-otel.sh} +1 -1
  229. package/sdk-core/etc/regen-depgraph.sh +2 -2
  230. package/src/client.rs +24 -33
  231. package/src/helpers/try_from_js.rs +1 -1
  232. package/src/logs.rs +1 -1
  233. package/src/metrics.rs +3 -3
  234. package/src/runtime.rs +42 -28
  235. package/src/testing.rs +3 -3
  236. package/src/worker.rs +70 -36
  237. package/ts/native.ts +13 -6
  238. package/LICENSE.md +0 -23
  239. package/sdk-core/client/src/worker_registry/mod.rs +0 -282
  240. package/sdk-core/core/src/worker/heartbeat.rs +0 -230
  241. package/sdk-core/core/src/worker/mod.rs +0 -990
  242. package/sdk-core/etc/deps.svg +0 -162
  243. package/sdk-core/fsm/Cargo.toml +0 -21
  244. package/sdk-core/fsm/README.md +0 -3
  245. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +0 -27
  246. package/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +0 -21
  247. package/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +0 -8
  248. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +0 -12
  249. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +0 -15
  250. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +0 -5
  251. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +0 -5
  252. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +0 -5
  253. package/sdk-core/fsm/rustfsm_trait/Cargo.toml +0 -14
  254. package/sdk-core/fsm/src/lib.rs +0 -2
  255. package/sdk-core/sdk-core-protos/Cargo.toml +0 -37
  256. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +0 -1
  257. /package/sdk-core/{client → crates/client}/src/callback_based.rs +0 -0
  258. /package/sdk-core/{client → crates/client}/src/proxy.rs +0 -0
  259. /package/sdk-core/{client → crates/client}/src/replaceable.rs +0 -0
  260. /package/sdk-core/{sdk-core-protos → crates/common}/build.rs +0 -0
  261. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/.github/workflows/build.yaml +0 -0
  262. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/.github/workflows/push-to-buf.yml +0 -0
  263. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/CODEOWNERS +0 -0
  264. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/LICENSE +0 -0
  265. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/Makefile +0 -0
  266. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/README.md +0 -0
  267. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/buf.gen.yaml +0 -0
  268. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/buf.lock +0 -0
  269. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/buf.yaml +0 -0
  270. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/connectivityrule/v1/message.proto +0 -0
  271. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +0 -0
  272. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +0 -0
  273. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/nexus/v1/message.proto +0 -0
  274. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +0 -0
  275. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/resource/v1/message.proto +0 -0
  276. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_cloud_upstream/temporal/api/cloud/usage/v1/message.proto +0 -0
  277. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/CODEOWNERS +0 -0
  278. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  279. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/ci.yml +0 -0
  280. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/publish-docs.yml +0 -0
  281. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/push-to-buf.yml +0 -0
  282. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/trigger-api-go-delete-release.yml +0 -0
  283. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/trigger-api-go-publish-release.yml +0 -0
  284. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +0 -0
  285. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/LICENSE +0 -0
  286. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/Makefile +0 -0
  287. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/README.md +0 -0
  288. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/api-linter.yaml +0 -0
  289. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/buf.gen.yaml +0 -0
  290. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/buf.lock +0 -0
  291. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/buf.yaml +0 -0
  292. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/api/annotations.proto +0 -0
  293. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/api/http.proto +0 -0
  294. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/any.proto +0 -0
  295. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/descriptor.proto +0 -0
  296. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/duration.proto +0 -0
  297. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/empty.proto +0 -0
  298. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/struct.proto +0 -0
  299. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/timestamp.proto +0 -0
  300. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/google/protobuf/wrappers.proto +0 -0
  301. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/openapi/openapiv2.json +0 -0
  302. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/openapi/openapiv3.yaml +0 -0
  303. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/openapi/payload_description.txt +0 -0
  304. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/activity/v1/message.proto +0 -0
  305. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/batch/v1/message.proto +0 -0
  306. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/command/v1/message.proto +0 -0
  307. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/common/v1/message.proto +0 -0
  308. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/deployment/v1/message.proto +0 -0
  309. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -0
  310. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/command_type.proto +0 -0
  311. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/common.proto +0 -0
  312. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/deployment.proto +0 -0
  313. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/event_type.proto +0 -0
  314. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +0 -0
  315. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/namespace.proto +0 -0
  316. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/nexus.proto +0 -0
  317. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/query.proto +0 -0
  318. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/reset.proto +0 -0
  319. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/schedule.proto +0 -0
  320. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -0
  321. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/update.proto +0 -0
  322. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/enums/v1/workflow.proto +0 -0
  323. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/errordetails/v1/message.proto +0 -0
  324. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/export/v1/message.proto +0 -0
  325. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/failure/v1/message.proto +0 -0
  326. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/filter/v1/message.proto +0 -0
  327. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/history/v1/message.proto +0 -0
  328. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/namespace/v1/message.proto +0 -0
  329. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/nexus/v1/message.proto +0 -0
  330. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +0 -0
  331. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -0
  332. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/protocol/v1/message.proto +0 -0
  333. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/query/v1/message.proto +0 -0
  334. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/replication/v1/message.proto +0 -0
  335. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/rules/v1/message.proto +0 -0
  336. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/schedule/v1/message.proto +0 -0
  337. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/enhanced_stack_trace.proto +0 -0
  338. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +0 -0
  339. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/user_metadata.proto +0 -0
  340. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/worker_config.proto +0 -0
  341. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +0 -0
  342. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +0 -0
  343. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/update/v1/message.proto +0 -0
  344. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/version/v1/message.proto +0 -0
  345. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/worker/v1/message.proto +0 -0
  346. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/workflow/v1/message.proto +0 -0
  347. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +0 -0
  348. /package/sdk-core/{sdk-core-protos → crates/common}/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +0 -0
  349. /package/sdk-core/{sdk-core-protos → crates/common}/protos/google/rpc/status.proto +0 -0
  350. /package/sdk-core/{sdk-core-protos → crates/common}/protos/grpc/health/v1/health.proto +0 -0
  351. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/activity_result/activity_result.proto +0 -0
  352. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/activity_task/activity_task.proto +0 -0
  353. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -0
  354. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/common/common.proto +0 -0
  355. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/core_interface.proto +0 -0
  356. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/external_data/external_data.proto +0 -0
  357. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/nexus/nexus.proto +0 -0
  358. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +0 -0
  359. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +0 -0
  360. /package/sdk-core/{sdk-core-protos → crates/common}/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -0
  361. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/Makefile +0 -0
  362. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/api-linter.yaml +0 -0
  363. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/buf.yaml +0 -0
  364. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -0
  365. /package/sdk-core/{sdk-core-protos → crates/common}/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -0
  366. /package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/constants.rs +0 -0
  367. /package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/task_token.rs +0 -0
  368. /package/sdk-core/{sdk-core-protos/src → crates/common/src/protos}/utilities.rs +0 -0
  369. /package/sdk-core/{fsm → crates/macros}/LICENSE.txt +0 -0
  370. /package/sdk-core/{sdk → crates/sdk}/src/app_data.rs +0 -0
  371. /package/sdk-core/{core → crates/sdk-core}/src/abstractions/take_cell.rs +0 -0
  372. /package/sdk-core/{core → crates/sdk-core}/src/test_help/mod.rs +0 -0
  373. /package/sdk-core/{core → crates/sdk-core}/src/worker/slot_supplier.rs +0 -0
  374. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/ends_empty_wft_complete.bin +0 -0
  375. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/evict_while_la_running_no_interference-16_history.bin +0 -0
  376. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/evict_while_la_running_no_interference-23_history.bin +0 -0
  377. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/evict_while_la_running_no_interference-85_history.bin +0 -0
  378. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/fail_wf_task.bin +0 -0
  379. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-0_history.bin +0 -0
  380. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-1_history.bin +0 -0
  381. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-2_history.bin +0 -0
  382. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/long_local_activity_with_update-3_history.bin +0 -0
  383. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/old_change_marker_format.bin +0 -0
  384. /package/sdk-core/{histories → crates/sdk-core/tests/histories}/timer_workflow_history.bin +0 -0
  385. /package/sdk-core/{tests → crates/sdk-core/tests}/integ_tests/workflow_tests/priority.rs +0 -0
  386. /package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/build.rs +0 -0
  387. /package/sdk-core/{core-c-bridge → crates/sdk-core-c-bridge}/src/random.rs +0 -0
  388. /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 temporal_sdk_core_api::{
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 = ResourceController::new_with_sysinfo(options, RealSysInfo::new());
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.inner.gauge_f64("resource_slots_mem_usage".into());
223
- let cpu_usage = meter.inner.gauge_f64("resource_slots_cpu_usage".into());
224
- let mem_pid_output = meter
225
- .inner
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
- pub struct RealSysInfo {
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
- last_refresh: AtomicCell<Instant>,
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
- let mem = lock.used_memory();
522
- self.cur_mem_usage.store(mem, Ordering::Release);
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
- // TODO: This should really happen on a background thread since it's getting called from
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.refresh_if_needed();
543
- f64::from_bits(self.cur_cpu_usage.load(Ordering::Acquire))
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::sync::{
552
- Arc,
553
- atomic::{AtomicU64, Ordering},
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 temporal_sdk_core_api::worker::WorkflowSlotKind;
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, Arc<AtomicU64>) {
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
  }