@temporalio/core-bridge 1.14.2-canary-release-testing.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/Cargo.lock +794 -650
  2. package/bridge-macros/src/derive_tryintojs.rs +40 -0
  3. package/lib/native.d.ts +24 -3
  4. package/package.json +4 -4
  5. package/releases/aarch64-apple-darwin/index.node +0 -0
  6. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  7. package/releases/x86_64-apple-darwin/index.node +0 -0
  8. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  9. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  10. package/sdk-core/.github/workflows/per-pr.yml +6 -6
  11. package/sdk-core/AGENTS.md +42 -31
  12. package/sdk-core/Cargo.toml +4 -1
  13. package/sdk-core/README.md +19 -13
  14. package/sdk-core/crates/client/Cargo.toml +4 -0
  15. package/sdk-core/crates/client/README.md +139 -0
  16. package/sdk-core/crates/client/src/async_activity_handle.rs +297 -0
  17. package/sdk-core/crates/client/src/callback_based.rs +7 -0
  18. package/sdk-core/crates/client/src/errors.rs +294 -0
  19. package/sdk-core/crates/client/src/{raw.rs → grpc.rs} +370 -159
  20. package/sdk-core/crates/client/src/lib.rs +920 -1326
  21. package/sdk-core/crates/client/src/metrics.rs +24 -33
  22. package/sdk-core/crates/client/src/options_structs.rs +457 -0
  23. package/sdk-core/crates/client/src/replaceable.rs +5 -4
  24. package/sdk-core/crates/client/src/request_extensions.rs +8 -9
  25. package/sdk-core/crates/client/src/retry.rs +99 -54
  26. package/sdk-core/crates/client/src/{worker/mod.rs → worker.rs} +104 -29
  27. package/sdk-core/crates/client/src/workflow_handle.rs +826 -0
  28. package/sdk-core/crates/common/Cargo.toml +62 -3
  29. package/sdk-core/crates/common/build.rs +742 -12
  30. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/ci.yml +2 -0
  31. package/sdk-core/crates/common/protos/api_upstream/.github/workflows/create-release.yml +0 -5
  32. package/sdk-core/crates/common/protos/api_upstream/Makefile +2 -1
  33. package/sdk-core/crates/common/protos/api_upstream/README.md +8 -0
  34. package/sdk-core/crates/common/protos/api_upstream/cmd/check-path-conflicts/main.go +137 -0
  35. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv2.json +3329 -2647
  36. package/sdk-core/crates/common/protos/api_upstream/openapi/openapiv3.yaml +2734 -708
  37. package/sdk-core/crates/common/protos/api_upstream/temporal/api/activity/v1/message.proto +155 -3
  38. package/sdk-core/crates/common/protos/api_upstream/temporal/api/command/v1/message.proto +26 -0
  39. package/sdk-core/crates/common/protos/api_upstream/temporal/api/common/v1/message.proto +8 -1
  40. package/sdk-core/crates/common/protos/api_upstream/temporal/api/deployment/v1/message.proto +27 -1
  41. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/activity.proto +81 -0
  42. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/event_type.proto +4 -0
  43. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +4 -0
  44. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +15 -0
  45. package/sdk-core/crates/common/protos/api_upstream/temporal/api/enums/v1/workflow.proto +63 -15
  46. package/sdk-core/crates/common/protos/api_upstream/temporal/api/errordetails/v1/message.proto +8 -0
  47. package/sdk-core/crates/common/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -0
  48. package/sdk-core/crates/common/protos/api_upstream/temporal/api/history/v1/message.proto +111 -17
  49. package/sdk-core/crates/common/protos/api_upstream/temporal/api/namespace/v1/message.proto +21 -0
  50. package/sdk-core/crates/common/protos/api_upstream/temporal/api/nexus/v1/message.proto +20 -1
  51. package/sdk-core/crates/common/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +4 -0
  52. package/sdk-core/crates/common/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
  53. package/sdk-core/crates/common/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -0
  54. package/sdk-core/crates/common/protos/api_upstream/temporal/api/worker/v1/message.proto +4 -7
  55. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflow/v1/message.proto +80 -22
  56. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +347 -23
  57. package/sdk-core/crates/common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +242 -43
  58. package/sdk-core/crates/common/protos/local/temporal/sdk/core/core_interface.proto +15 -0
  59. package/sdk-core/crates/common/protos/local/temporal/sdk/core/nexus/nexus.proto +9 -2
  60. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +8 -0
  61. package/sdk-core/crates/common/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +22 -5
  62. package/sdk-core/crates/common/src/activity_definition.rs +20 -0
  63. package/sdk-core/crates/common/src/data_converters.rs +770 -0
  64. package/sdk-core/crates/common/src/envconfig.rs +5 -0
  65. package/sdk-core/crates/common/src/lib.rs +15 -211
  66. package/sdk-core/crates/common/src/payload_visitor.rs +648 -0
  67. package/sdk-core/crates/common/src/priority.rs +110 -0
  68. package/sdk-core/crates/common/src/protos/canned_histories.rs +19 -0
  69. package/sdk-core/crates/common/src/protos/history_builder.rs +45 -0
  70. package/sdk-core/crates/common/src/protos/history_info.rs +2 -0
  71. package/sdk-core/crates/common/src/protos/mod.rs +134 -27
  72. package/sdk-core/crates/common/src/protos/task_token.rs +3 -3
  73. package/sdk-core/crates/common/src/protos/utilities.rs +11 -0
  74. package/sdk-core/crates/{sdk-core → common}/src/telemetry/log_export.rs +11 -16
  75. package/sdk-core/crates/common/src/telemetry/metrics/core.rs +125 -0
  76. package/sdk-core/crates/common/src/telemetry/metrics.rs +272 -225
  77. package/sdk-core/crates/{sdk-core → common}/src/telemetry/otel.rs +8 -13
  78. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_meter.rs +49 -50
  79. package/sdk-core/crates/{sdk-core → common}/src/telemetry/prometheus_server.rs +2 -3
  80. package/sdk-core/crates/common/src/telemetry.rs +278 -19
  81. package/sdk-core/crates/common/src/worker.rs +68 -636
  82. package/sdk-core/crates/common/src/workflow_definition.rs +60 -0
  83. package/sdk-core/crates/macros/Cargo.toml +5 -1
  84. package/sdk-core/crates/macros/src/activities_definitions.rs +585 -0
  85. package/sdk-core/crates/macros/src/fsm_impl.rs +507 -0
  86. package/sdk-core/crates/macros/src/lib.rs +138 -512
  87. package/sdk-core/crates/macros/src/macro_utils.rs +106 -0
  88. package/sdk-core/crates/macros/src/workflow_definitions.rs +1224 -0
  89. package/sdk-core/crates/sdk/Cargo.toml +19 -6
  90. package/sdk-core/crates/sdk/README.md +415 -0
  91. package/sdk-core/crates/sdk/src/activities.rs +417 -0
  92. package/sdk-core/crates/sdk/src/interceptors.rs +1 -1
  93. package/sdk-core/crates/sdk/src/lib.rs +759 -442
  94. package/sdk-core/crates/sdk/src/workflow_context/options.rs +64 -35
  95. package/sdk-core/crates/sdk/src/workflow_context.rs +1033 -289
  96. package/sdk-core/crates/sdk/src/workflow_future.rs +277 -213
  97. package/sdk-core/crates/sdk/src/workflows.rs +711 -0
  98. package/sdk-core/crates/sdk-core/Cargo.toml +59 -65
  99. package/sdk-core/crates/sdk-core/benches/workflow_replay_bench.rs +45 -54
  100. package/sdk-core/crates/sdk-core/machine_coverage/ActivityMachine_Coverage.puml +1 -1
  101. package/sdk-core/crates/sdk-core/src/abstractions.rs +6 -10
  102. package/sdk-core/crates/sdk-core/src/core_tests/activity_tasks.rs +6 -5
  103. package/sdk-core/crates/sdk-core/src/core_tests/mod.rs +22 -21
  104. package/sdk-core/crates/sdk-core/src/core_tests/queries.rs +21 -25
  105. package/sdk-core/crates/sdk-core/src/core_tests/replay_flag.rs +7 -10
  106. package/sdk-core/crates/sdk-core/src/core_tests/updates.rs +14 -17
  107. package/sdk-core/crates/sdk-core/src/core_tests/workers.rs +647 -27
  108. package/sdk-core/crates/sdk-core/src/core_tests/workflow_tasks.rs +46 -41
  109. package/sdk-core/crates/sdk-core/src/ephemeral_server/mod.rs +13 -16
  110. package/sdk-core/crates/sdk-core/src/histfetch.rs +20 -10
  111. package/sdk-core/crates/sdk-core/src/lib.rs +60 -123
  112. package/sdk-core/crates/sdk-core/src/pollers/mod.rs +4 -9
  113. package/sdk-core/crates/sdk-core/src/pollers/poll_buffer.rs +411 -32
  114. package/sdk-core/crates/sdk-core/src/protosext/mod.rs +2 -2
  115. package/sdk-core/crates/sdk-core/src/replay/mod.rs +14 -5
  116. package/sdk-core/crates/sdk-core/src/telemetry/metrics.rs +183 -198
  117. package/sdk-core/crates/sdk-core/src/telemetry/mod.rs +3 -281
  118. package/sdk-core/crates/sdk-core/src/test_help/integ_helpers.rs +35 -16
  119. package/sdk-core/crates/sdk-core/src/test_help/unit_helpers.rs +3 -6
  120. package/sdk-core/crates/sdk-core/src/worker/activities/activity_heartbeat_manager.rs +1 -0
  121. package/sdk-core/crates/sdk-core/src/worker/activities/local_activities.rs +11 -14
  122. package/sdk-core/crates/sdk-core/src/worker/activities.rs +16 -19
  123. package/sdk-core/crates/sdk-core/src/worker/client/mocks.rs +11 -5
  124. package/sdk-core/crates/sdk-core/src/worker/client.rs +104 -86
  125. package/sdk-core/crates/sdk-core/src/worker/heartbeat.rs +10 -14
  126. package/sdk-core/crates/sdk-core/src/worker/mod.rs +1175 -241
  127. package/sdk-core/crates/sdk-core/src/worker/nexus.rs +150 -23
  128. package/sdk-core/crates/sdk-core/src/worker/slot_provider.rs +2 -2
  129. package/sdk-core/crates/sdk-core/src/worker/tuner/fixed_size.rs +2 -2
  130. package/sdk-core/crates/sdk-core/src/worker/tuner/resource_based.rs +25 -27
  131. package/sdk-core/crates/sdk-core/src/worker/tuner.rs +64 -44
  132. package/sdk-core/crates/sdk-core/src/worker/workflow/driven_workflow.rs +9 -3
  133. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/patch_state_machine.rs +5 -8
  134. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +21 -22
  135. package/sdk-core/crates/sdk-core/src/worker/workflow/machines/workflow_machines.rs +28 -4
  136. package/sdk-core/crates/sdk-core/src/worker/workflow/managed_run.rs +20 -41
  137. package/sdk-core/crates/sdk-core/src/worker/workflow/mod.rs +50 -9
  138. package/sdk-core/crates/sdk-core/src/worker/workflow/run_cache.rs +4 -7
  139. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_extraction.rs +2 -4
  140. package/sdk-core/crates/sdk-core/src/worker/workflow/wft_poller.rs +8 -9
  141. package/sdk-core/crates/sdk-core/src/worker/workflow/workflow_stream.rs +1 -3
  142. package/sdk-core/crates/sdk-core/tests/activities_procmacro.rs +6 -0
  143. package/sdk-core/crates/sdk-core/tests/activities_trybuild/basic_pass.rs +54 -0
  144. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.rs +18 -0
  145. package/sdk-core/crates/sdk-core/tests/activities_trybuild/invalid_self_type_fail.stderr +5 -0
  146. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.rs +14 -0
  147. package/sdk-core/crates/sdk-core/tests/activities_trybuild/missing_context_fail.stderr +5 -0
  148. package/sdk-core/crates/sdk-core/tests/activities_trybuild/multi_arg_pass.rs +48 -0
  149. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_input_pass.rs +14 -0
  150. package/sdk-core/crates/sdk-core/tests/activities_trybuild/no_return_type_pass.rs +19 -0
  151. package/sdk-core/crates/sdk-core/tests/cloud_tests.rs +14 -5
  152. package/sdk-core/crates/sdk-core/tests/common/activity_functions.rs +55 -0
  153. package/sdk-core/crates/sdk-core/tests/common/mod.rs +281 -236
  154. package/sdk-core/crates/sdk-core/tests/common/workflows.rs +41 -28
  155. package/sdk-core/crates/sdk-core/tests/global_metric_tests.rs +9 -14
  156. package/sdk-core/crates/sdk-core/tests/heavy_tests/fuzzy_workflow.rs +73 -66
  157. package/sdk-core/crates/sdk-core/tests/heavy_tests.rs +306 -268
  158. package/sdk-core/crates/sdk-core/tests/integ_tests/async_activity_client_tests.rs +230 -0
  159. package/sdk-core/crates/sdk-core/tests/integ_tests/client_tests.rs +94 -57
  160. package/sdk-core/crates/sdk-core/tests/integ_tests/data_converter_tests.rs +381 -0
  161. package/sdk-core/crates/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +37 -38
  162. package/sdk-core/crates/sdk-core/tests/integ_tests/heartbeat_tests.rs +49 -40
  163. package/sdk-core/crates/sdk-core/tests/integ_tests/metrics_tests.rs +447 -300
  164. package/sdk-core/crates/sdk-core/tests/integ_tests/pagination_tests.rs +50 -45
  165. package/sdk-core/crates/sdk-core/tests/integ_tests/polling_tests.rs +157 -157
  166. package/sdk-core/crates/sdk-core/tests/integ_tests/queries_tests.rs +103 -89
  167. package/sdk-core/crates/sdk-core/tests/integ_tests/update_tests.rs +609 -463
  168. package/sdk-core/crates/sdk-core/tests/integ_tests/visibility_tests.rs +80 -62
  169. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_heartbeat_tests.rs +389 -265
  170. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_tests.rs +250 -185
  171. package/sdk-core/crates/sdk-core/tests/integ_tests/worker_versioning_tests.rs +52 -49
  172. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_client_tests.rs +180 -0
  173. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/activities.rs +437 -327
  174. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +82 -58
  175. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +56 -30
  176. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +364 -251
  177. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/client_interactions.rs +552 -0
  178. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +110 -46
  179. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +243 -149
  180. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/eager.rs +98 -32
  181. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1475 -1040
  182. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +73 -43
  183. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +402 -245
  184. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/patches.rs +343 -207
  185. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/queries.rs +415 -0
  186. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/replay.rs +96 -36
  187. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/resets.rs +155 -140
  188. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/signals.rs +183 -113
  189. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +85 -44
  190. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/timers.rs +142 -48
  191. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +73 -56
  192. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests.rs +365 -242
  193. package/sdk-core/crates/sdk-core/tests/main.rs +22 -16
  194. package/sdk-core/crates/sdk-core/tests/manual_tests.rs +233 -187
  195. package/sdk-core/crates/sdk-core/tests/runner.rs +4 -6
  196. package/sdk-core/crates/sdk-core/tests/shared_tests/mod.rs +73 -27
  197. package/sdk-core/crates/sdk-core/tests/shared_tests/priority.rs +107 -84
  198. package/sdk-core/crates/sdk-core/tests/workflows_procmacro.rs +6 -0
  199. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.rs +26 -0
  200. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/async_query_fail.stderr +5 -0
  201. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/basic_pass.rs +49 -0
  202. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/minimal_pass.rs +21 -0
  203. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.rs +26 -0
  204. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/mut_query_fail.stderr +5 -0
  205. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.rs +21 -0
  206. package/sdk-core/crates/sdk-core/tests/workflows_trybuild/sync_run_fail.stderr +5 -0
  207. package/sdk-core/crates/sdk-core-c-bridge/Cargo.toml +8 -1
  208. package/sdk-core/crates/sdk-core-c-bridge/include/temporal-sdk-core-c-bridge.h +37 -26
  209. package/sdk-core/crates/sdk-core-c-bridge/src/client.rs +180 -87
  210. package/sdk-core/crates/sdk-core-c-bridge/src/lib.rs +89 -5
  211. package/sdk-core/crates/sdk-core-c-bridge/src/metric.rs +10 -16
  212. package/sdk-core/crates/sdk-core-c-bridge/src/runtime.rs +59 -67
  213. package/sdk-core/crates/sdk-core-c-bridge/src/testing.rs +10 -10
  214. package/sdk-core/crates/sdk-core-c-bridge/src/tests/context.rs +57 -22
  215. package/sdk-core/crates/sdk-core-c-bridge/src/tests/mod.rs +108 -12
  216. package/sdk-core/crates/sdk-core-c-bridge/src/tests/utils.rs +9 -52
  217. package/sdk-core/crates/sdk-core-c-bridge/src/worker.rs +74 -91
  218. package/sdk-core/rustfmt.toml +2 -1
  219. package/src/client.rs +206 -289
  220. package/src/helpers/try_into_js.rs +88 -2
  221. package/src/metrics.rs +277 -35
  222. package/src/runtime.rs +94 -45
  223. package/src/testing.rs +9 -16
  224. package/src/worker.rs +86 -68
  225. package/ts/native.ts +39 -3
  226. package/sdk-core/crates/client/src/workflow_handle/mod.rs +0 -212
  227. package/sdk-core/crates/common/src/errors.rs +0 -85
  228. package/sdk-core/crates/common/tests/worker_task_types_test.rs +0 -129
  229. package/sdk-core/crates/macros/LICENSE.txt +0 -21
  230. package/sdk-core/crates/sdk/src/activity_context.rs +0 -238
  231. package/sdk-core/crates/sdk/src/app_data.rs +0 -37
  232. package/sdk-core/crates/sdk-core/tests/integ_tests/activity_functions.rs +0 -5
  233. package/sdk-core/crates/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +0 -61
@@ -1,11 +1,11 @@
1
1
  use std::{
2
- sync::Arc,
2
+ sync::{Arc, Mutex},
3
3
  time::{Duration, SystemTime, UNIX_EPOCH},
4
4
  };
5
5
 
6
6
  use neon::{
7
7
  object::Object,
8
- prelude::Context,
8
+ prelude::{Context, Root},
9
9
  result::JsResult,
10
10
  types::{
11
11
  JsArray, JsBigInt, JsBoolean, JsBuffer, JsNumber, JsString, JsUndefined, JsValue, Value,
@@ -36,6 +36,13 @@ impl TryIntoJs for u32 {
36
36
  }
37
37
  }
38
38
 
39
+ impl TryIntoJs for f64 {
40
+ type Output = JsNumber;
41
+ fn try_into_js<'a>(self, cx: &mut impl Context<'a>) -> JsResult<'a, JsNumber> {
42
+ Ok(cx.number(self))
43
+ }
44
+ }
45
+
39
46
  impl TryIntoJs for String {
40
47
  type Output = JsString;
41
48
  fn try_into_js<'a>(self, cx: &mut impl Context<'a>) -> JsResult<'a, JsString> {
@@ -127,3 +134,82 @@ impl<T0: TryIntoJs, T1: TryIntoJs> TryIntoJs for (T0, T1) {
127
134
  Ok(array)
128
135
  }
129
136
  }
137
+
138
+ /// A handle that wraps another `TryIntoJs` type, memoizing the converted JavaScript value.
139
+ /// That is, the value is converted to JavaScript only once, and then the same JavaScript value
140
+ /// is returned for subsequent calls. This notably ensures that the value sent to the JS side
141
+ /// is exactly the same object every time (i.e. `===` comparison is true).
142
+ #[derive(Clone, Debug)]
143
+ pub struct MemoizedHandle<T: TryIntoJs + Clone + std::fmt::Debug>
144
+ where
145
+ T::Output: std::fmt::Debug,
146
+ {
147
+ internal: Arc<Mutex<MemoizedInternal<T>>>,
148
+ }
149
+
150
+ #[derive(Debug)]
151
+ enum MemoizedInternal<T: TryIntoJs + Clone + std::fmt::Debug> {
152
+ Pending(T),
153
+ Rooted(Root<T::Output>),
154
+ }
155
+
156
+ impl<T: TryIntoJs + Clone + std::fmt::Debug> MemoizedHandle<T>
157
+ where
158
+ T::Output: Object + std::fmt::Debug,
159
+ {
160
+ pub fn new(value: T) -> Self {
161
+ Self {
162
+ internal: Arc::new(Mutex::new(MemoizedInternal::Pending(value))),
163
+ }
164
+ }
165
+ }
166
+
167
+ impl<T: TryIntoJs + Clone + std::fmt::Debug> TryIntoJs for MemoizedHandle<T>
168
+ where
169
+ T::Output: Object + std::fmt::Debug,
170
+ {
171
+ type Output = T::Output;
172
+ fn try_into_js<'cx>(self, cx: &mut impl Context<'cx>) -> JsResult<'cx, T::Output> {
173
+ let mut guard = self.internal.lock().expect("MemoizedHandle lock");
174
+ match *guard {
175
+ MemoizedInternal::Pending(ref value) => {
176
+ let rooted_value = value.clone().try_into_js(cx)?.root(cx);
177
+ let js_value = rooted_value.to_inner(cx);
178
+ *guard = MemoizedInternal::Rooted(rooted_value);
179
+ Ok(js_value)
180
+ }
181
+ MemoizedInternal::Rooted(ref handle) => Ok(handle.to_inner(cx)),
182
+ }
183
+ }
184
+ }
185
+
186
+ /// To avoid some recurring error patterns when crossing the JS bridge, we normally translate
187
+ /// `Option<T>` to `T | null` on the JS side. This however implies extra code on the JS side
188
+ /// to check for `null` and convert to `undefined` as appropriate. This generally poses no
189
+ /// problem, as manipulation of objects on the JS side is anyway desirable for other reasons.
190
+ ///
191
+ /// In rare cases, however, this extra manipulation may not be desirable. For example, when
192
+ /// passing buffered metrics to the JS Side, we want to preserve object identity. Modifying
193
+ /// objects on the JS side would either break object identity or introduce unnecessary overhead.
194
+ ///
195
+ /// For those rare cases, this newtype wrapper to indicate that an option property should be
196
+ /// translated to `undefined` on the JS side, rather than `null`.
197
+ #[derive(Clone, Debug)]
198
+ pub struct OptionAsUndefined<T: TryIntoJs + Clone + std::fmt::Debug>(Option<T>);
199
+
200
+ impl<T: TryIntoJs + Clone + std::fmt::Debug> From<Option<T>> for OptionAsUndefined<T> {
201
+ fn from(value: Option<T>) -> Self {
202
+ Self(value)
203
+ }
204
+ }
205
+
206
+ impl<T: TryIntoJs + Clone + std::fmt::Debug> TryIntoJs for OptionAsUndefined<T> {
207
+ type Output = JsValue;
208
+ fn try_into_js<'a>(self, cx: &mut impl Context<'a>) -> JsResult<'a, JsValue> {
209
+ if let Some(value) = self.0 {
210
+ Ok(value.try_into_js(cx)?.upcast())
211
+ } else {
212
+ Ok(cx.undefined().upcast())
213
+ }
214
+ }
215
+ }
package/src/metrics.rs CHANGED
@@ -1,28 +1,36 @@
1
+ use std::any::Any;
1
2
  use std::collections::HashMap;
3
+ use std::sync::Arc;
2
4
 
3
- use anyhow::Context as _;
4
5
  use neon::prelude::*;
5
6
  use serde::Deserialize;
6
7
 
7
- use temporalio_common::telemetry::metrics::{
8
- CoreMeter, Counter as CoreCounter, Gauge as CoreGauge, Histogram as CoreHistogram,
9
- MetricParametersBuilder, NewAttributes, TemporalMeter,
10
- };
11
- use temporalio_common::telemetry::metrics::{
12
- GaugeF64 as CoreGaugeF64, HistogramF64 as CoreHistogramF64,
8
+ use temporalio_common::telemetry::metrics::core::{
9
+ BufferInstrumentRef as CoreBufferInstrumentRef, CustomMetricAttributes, MetricCallBufferer,
10
+ MetricEvent as CoreMetricEvent, MetricKind as CoreMetricKind, MetricUpdateVal,
13
11
  };
14
12
  use temporalio_common::telemetry::metrics::{
15
- MetricKeyValue as CoreMetricKeyValue, MetricValue as CoreMetricValue,
13
+ Counter as CoreCounter, Gauge as CoreGauge, GaugeF64 as CoreGaugeF64,
14
+ Histogram as CoreHistogram, HistogramF64 as CoreHistogramF64,
15
+ MetricKeyValue as CoreMetricKeyValue, MetricParameters as CoreMetricParameters,
16
+ MetricValue as CoreMetricValue, NewAttributes, TemporalMeter,
16
17
  };
17
18
 
18
- use bridge_macros::js_function;
19
+ use bridge_macros::{TryIntoJs, js_function};
20
+ use temporalio_sdk_core::telemetry::MetricsCallBuffer as CoreMetricsCallBuffer;
19
21
 
22
+ use crate::helpers::properties::ObjectExt as _;
23
+ use crate::helpers::try_into_js::{MemoizedHandle, OptionAsUndefined};
20
24
  use crate::helpers::{
21
25
  BridgeError, BridgeResult, JsonString, MutableFinalize, OpaqueInboundHandle,
22
- OpaqueOutboundHandle,
26
+ OpaqueOutboundHandle, TryIntoJs,
23
27
  };
24
28
  use crate::runtime::Runtime;
25
29
 
30
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
31
+ // Metric Meter (aka Custom Metrics)
32
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
33
+
26
34
  pub fn init(cx: &mut neon::prelude::ModuleContext) -> neon::prelude::NeonResult<()> {
27
35
  cx.export_function("newMetricCounter", new_metric_counter)?;
28
36
  cx.export_function("newMetricHistogram", new_metric_histogram)?;
@@ -115,13 +123,12 @@ pub fn new_metric_counter(
115
123
  "Failed to get metric meter".into(),
116
124
  ))?;
117
125
 
118
- let counter = meter.inner.counter(
119
- MetricParametersBuilder::default()
126
+ let counter = meter.counter(
127
+ CoreMetricParameters::builder()
120
128
  .name(name)
121
129
  .unit(unit)
122
130
  .description(description)
123
- .build()
124
- .context("Failed to build metric parameters")?,
131
+ .build(),
125
132
  );
126
133
 
127
134
  Ok(OpaqueOutboundHandle::new(Counter { meter, counter }))
@@ -142,13 +149,12 @@ pub fn new_metric_histogram(
142
149
  "Failed to get metric meter".into(),
143
150
  ))?;
144
151
 
145
- let histogram = meter.inner.histogram(
146
- MetricParametersBuilder::default()
152
+ let histogram = meter.histogram(
153
+ CoreMetricParameters::builder()
147
154
  .name(name)
148
155
  .unit(unit)
149
156
  .description(description)
150
- .build()
151
- .context("Failed to build metric parameters")?,
157
+ .build(),
152
158
  );
153
159
 
154
160
  Ok(OpaqueOutboundHandle::new(Histogram { meter, histogram }))
@@ -169,13 +175,12 @@ pub fn new_metric_histogram_f64(
169
175
  "Failed to get metric meter".into(),
170
176
  ))?;
171
177
 
172
- let histogram = meter.inner.histogram_f64(
173
- MetricParametersBuilder::default()
178
+ let histogram = meter.histogram_f64(
179
+ CoreMetricParameters::builder()
174
180
  .name(name)
175
181
  .unit(unit)
176
182
  .description(description)
177
- .build()
178
- .context("Failed to build metric parameters")?,
183
+ .build(),
179
184
  );
180
185
 
181
186
  Ok(OpaqueOutboundHandle::new(HistogramF64 { meter, histogram }))
@@ -196,13 +201,12 @@ pub fn new_metric_gauge(
196
201
  "Failed to get metric meter".into(),
197
202
  ))?;
198
203
 
199
- let gauge = meter.inner.gauge(
200
- MetricParametersBuilder::default()
204
+ let gauge = meter.gauge(
205
+ CoreMetricParameters::builder()
201
206
  .name(name)
202
207
  .unit(unit)
203
208
  .description(description)
204
- .build()
205
- .context("Failed to build metric parameters")?,
209
+ .build(),
206
210
  );
207
211
 
208
212
  Ok(OpaqueOutboundHandle::new(Gauge { meter, gauge }))
@@ -223,13 +227,12 @@ pub fn new_metric_gauge_f64(
223
227
  "Failed to get metric meter".into(),
224
228
  ))?;
225
229
 
226
- let gauge = meter.inner.gauge_f64(
227
- MetricParametersBuilder::default()
230
+ let gauge = meter.gauge_f64(
231
+ CoreMetricParameters::builder()
228
232
  .name(name)
229
233
  .unit(unit)
230
234
  .description(description)
231
- .build()
232
- .context("Failed to build metric parameters")?,
235
+ .build(),
233
236
  );
234
237
 
235
238
  Ok(OpaqueOutboundHandle::new(GaugeF64 { meter, gauge }))
@@ -245,10 +248,11 @@ pub fn add_metric_counter_value(
245
248
  attributes: JsonString<MetricAttributes>,
246
249
  ) -> BridgeResult<()> {
247
250
  let counter_handle = counter_handle.borrow()?;
251
+
248
252
  let attributes = counter_handle
249
253
  .meter
250
- .inner
251
254
  .new_attributes(parse_metric_attributes(attributes.value));
255
+
252
256
  counter_handle.counter.add(value as u64, &attributes);
253
257
  Ok(())
254
258
  }
@@ -262,7 +266,6 @@ pub fn record_metric_histogram_value(
262
266
  let histogram_handle = histogram_handle.borrow()?;
263
267
  let attributes = histogram_handle
264
268
  .meter
265
- .inner
266
269
  .new_attributes(parse_metric_attributes(attributes.value));
267
270
  histogram_handle.histogram.record(value, &attributes);
268
271
  Ok(())
@@ -277,7 +280,6 @@ pub fn record_metric_histogram_f64_value(
277
280
  let histogram_handle = histogram_handle.borrow()?;
278
281
  let attributes = histogram_handle
279
282
  .meter
280
- .inner
281
283
  .new_attributes(parse_metric_attributes(attributes.value));
282
284
  histogram_handle.histogram.record(value, &attributes);
283
285
  Ok(())
@@ -292,7 +294,6 @@ pub fn set_metric_gauge_value(
292
294
  let gauge_handle = gauge_handle.borrow()?;
293
295
  let attributes = gauge_handle
294
296
  .meter
295
- .inner
296
297
  .new_attributes(parse_metric_attributes(attributes.value));
297
298
  gauge_handle.gauge.record(value, &attributes);
298
299
  Ok(())
@@ -307,12 +308,240 @@ pub fn set_metric_gauge_f64_value(
307
308
  let gauge_handle = gauge_handle.borrow()?;
308
309
  let attributes = gauge_handle
309
310
  .meter
310
- .inner
311
311
  .new_attributes(parse_metric_attributes(attributes.value));
312
312
  gauge_handle.gauge.record(value, &attributes);
313
313
  Ok(())
314
314
  }
315
315
 
316
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
317
+ // Buffered Metrics (aka lang-side metrics exporter)
318
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
319
+
320
+ #[derive(Debug)]
321
+ pub struct MetricsCallBuffer {
322
+ pub(crate) core_buffer: Arc<CoreMetricsCallBuffer<BufferedMetricRef>>,
323
+ use_seconds_for_durations: bool,
324
+ }
325
+
326
+ impl MetricsCallBuffer {
327
+ pub(crate) fn new(max_buffer_size: usize, use_seconds_for_durations: bool) -> Self {
328
+ Self {
329
+ core_buffer: Arc::new(CoreMetricsCallBuffer::new(max_buffer_size)),
330
+ use_seconds_for_durations,
331
+ }
332
+ }
333
+
334
+ pub(crate) fn retrieve(&self) -> Vec<BufferedMetricUpdate> {
335
+ self.core_buffer
336
+ .retrieve()
337
+ .iter()
338
+ .filter_map(|e| self.convert_metric_event(e))
339
+ .collect()
340
+ }
341
+
342
+ fn convert_metric_event(
343
+ &self,
344
+ event: &CoreMetricEvent<BufferedMetricRef>,
345
+ ) -> Option<BufferedMetricUpdate> {
346
+ match event {
347
+ CoreMetricEvent::Create {
348
+ params,
349
+ populate_into,
350
+ kind,
351
+ } => {
352
+ // Create the metric and put it on the lazy ref
353
+ let metric = BufferedMetric::new(params, *kind, self.use_seconds_for_durations);
354
+ populate_into
355
+ .set(Arc::new(BufferedMetricRef(MemoizedHandle::new(metric))))
356
+ .expect("Unable to set buffered metric on reference");
357
+
358
+ None
359
+ }
360
+
361
+ // Create the attributes and put it on the lazy ref
362
+ CoreMetricEvent::CreateAttributes {
363
+ populate_into,
364
+ append_from,
365
+ attributes,
366
+ } => {
367
+ let append_from = append_from.as_ref().map(|f| {
368
+ f.get()
369
+ .clone()
370
+ .as_any()
371
+ .downcast::<BufferedMetricAttributesRef>()
372
+ .expect("Unable to downcast to expected buffered metric attributes")
373
+ });
374
+ let attributes = BufferedMetricAttributes {
375
+ new_attributes: attributes.clone(),
376
+ append_from: append_from.map(|f| f.as_ref().clone()),
377
+ };
378
+
379
+ let r = BufferedMetricAttributesRef(MemoizedHandle::new(attributes));
380
+ populate_into
381
+ .set(Arc::new(r))
382
+ .expect("Unable to set buffered metric attributes on reference");
383
+
384
+ None
385
+ }
386
+
387
+ CoreMetricEvent::Update {
388
+ instrument,
389
+ attributes,
390
+ update,
391
+ } => Some(BufferedMetricUpdate {
392
+ metric: instrument.get().as_ref().clone(),
393
+ #[allow(clippy::match_same_arms, clippy::cast_precision_loss)]
394
+ value: match update {
395
+ MetricUpdateVal::Duration(v) if self.use_seconds_for_durations => {
396
+ v.as_secs_f64()
397
+ }
398
+ MetricUpdateVal::Duration(v) => v.as_millis() as f64,
399
+ MetricUpdateVal::Delta(v) => *v as f64,
400
+ MetricUpdateVal::DeltaF64(v) => *v,
401
+ MetricUpdateVal::Value(v) => *v as f64,
402
+ MetricUpdateVal::ValueF64(v) => *v,
403
+ },
404
+ attributes: attributes
405
+ .get()
406
+ .clone()
407
+ .as_any()
408
+ .downcast::<BufferedMetricAttributesRef>()
409
+ .expect("Unable to downcast to expected buffered metric attributes")
410
+ .as_ref()
411
+ .clone(),
412
+ }),
413
+ }
414
+ }
415
+ }
416
+
417
+ #[derive(TryIntoJs)]
418
+ pub struct BufferedMetricUpdate {
419
+ metric: BufferedMetricRef,
420
+ value: f64,
421
+ attributes: BufferedMetricAttributesRef,
422
+ }
423
+
424
+ #[derive(TryIntoJs, Clone, Debug)]
425
+ struct BufferedMetric {
426
+ name: String,
427
+ description: OptionAsUndefined<String>,
428
+ unit: OptionAsUndefined<String>,
429
+ kind: MetricKind,
430
+ value_type: MetricValueType,
431
+ }
432
+
433
+ impl BufferedMetric {
434
+ pub fn new(
435
+ params: &CoreMetricParameters,
436
+ kind: CoreMetricKind,
437
+ use_seconds_for_durations: bool,
438
+ ) -> Self {
439
+ let unit = match kind {
440
+ CoreMetricKind::HistogramDuration if params.unit == "duration" => {
441
+ Some((if use_seconds_for_durations { "s" } else { "ms" }).to_string())
442
+ }
443
+ _ => (!params.unit.is_empty()).then_some(params.unit.to_string()),
444
+ };
445
+
446
+ #[allow(clippy::match_same_arms)]
447
+ let (kind, value_type) = match kind {
448
+ CoreMetricKind::Counter => (MetricKind::Counter, MetricValueType::Int),
449
+ CoreMetricKind::Gauge => (MetricKind::Gauge, MetricValueType::Int),
450
+ CoreMetricKind::GaugeF64 => (MetricKind::Gauge, MetricValueType::Float),
451
+ CoreMetricKind::Histogram => (MetricKind::Histogram, MetricValueType::Int),
452
+ CoreMetricKind::HistogramF64 => (MetricKind::Histogram, MetricValueType::Float),
453
+ CoreMetricKind::HistogramDuration => (MetricKind::Histogram, MetricValueType::Int),
454
+ };
455
+
456
+ let description =
457
+ (!params.description.is_empty()).then_some(params.description.to_string());
458
+
459
+ Self {
460
+ name: params.name.to_string(),
461
+ description: description.into(),
462
+ unit: unit.into(),
463
+ kind,
464
+ value_type,
465
+ }
466
+ }
467
+ }
468
+
469
+ #[derive(Clone, Debug)]
470
+ pub struct BufferedMetricRef(MemoizedHandle<BufferedMetric>);
471
+ impl CoreBufferInstrumentRef for BufferedMetricRef {}
472
+
473
+ impl TryIntoJs for BufferedMetricRef {
474
+ type Output = JsObject;
475
+ fn try_into_js<'cx>(self, cx: &mut impl Context<'cx>) -> JsResult<'cx, Self::Output> {
476
+ self.0.try_into_js(cx)
477
+ }
478
+ }
479
+
480
+ #[derive(Clone, Debug)]
481
+ struct BufferedMetricAttributes {
482
+ new_attributes: Vec<CoreMetricKeyValue>,
483
+ append_from: Option<BufferedMetricAttributesRef>,
484
+ }
485
+
486
+ impl TryIntoJs for BufferedMetricAttributes {
487
+ type Output = JsObject;
488
+ fn try_into_js<'cx>(self, cx: &mut impl Context<'cx>) -> JsResult<'cx, Self::Output> {
489
+ let object = cx.empty_object();
490
+
491
+ // Copy existing attributes, if any
492
+ if let Some(existing) = self.append_from {
493
+ let existing_attrs = existing.try_into_js(cx)?;
494
+
495
+ object_assign(cx, object, existing_attrs)?;
496
+ }
497
+
498
+ // Assign new attributes
499
+ for kv in self.new_attributes {
500
+ let k = kv.key.as_str();
501
+ #[allow(clippy::cast_precision_loss)]
502
+ match &kv.value {
503
+ CoreMetricValue::String(v) => object.set_property_from(cx, k, v.as_str()),
504
+ CoreMetricValue::Int(v) => object.set_property_from(cx, k, *v as f64),
505
+ CoreMetricValue::Float(v) => object.set_property_from(cx, k, *v),
506
+ CoreMetricValue::Bool(v) => object.set_property_from(cx, k, *v),
507
+ }?;
508
+ }
509
+
510
+ Ok(object)
511
+ }
512
+ }
513
+
514
+ #[derive(Clone, Debug)]
515
+ struct BufferedMetricAttributesRef(MemoizedHandle<BufferedMetricAttributes>);
516
+
517
+ impl CustomMetricAttributes for BufferedMetricAttributesRef {
518
+ fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
519
+ self as Arc<dyn Any + Send + Sync>
520
+ }
521
+ }
522
+
523
+ impl TryIntoJs for BufferedMetricAttributesRef {
524
+ type Output = JsObject;
525
+ fn try_into_js<'cx>(self, cx: &mut impl Context<'cx>) -> JsResult<'cx, Self::Output> {
526
+ self.0.try_into_js(cx)
527
+ }
528
+ }
529
+
530
+ #[derive(TryIntoJs, Clone, Debug)]
531
+ enum MetricKind {
532
+ Counter,
533
+ Gauge,
534
+ Histogram,
535
+ }
536
+
537
+ #[derive(TryIntoJs, Clone, Debug)]
538
+ enum MetricValueType {
539
+ Int,
540
+ Float,
541
+ }
542
+
543
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
544
+ // Helpers
316
545
  ////////////////////////////////////////////////////////////////////////////////////////////////////
317
546
 
318
547
  fn parse_metric_attributes(attrs: MetricAttributes) -> NewAttributes {
@@ -326,3 +555,16 @@ fn parse_metric_attributes(attrs: MetricAttributes) -> NewAttributes {
326
555
  .collect();
327
556
  NewAttributes { attributes: attrs }
328
557
  }
558
+
559
+ fn object_assign<'cx>(
560
+ cx: &mut impl Context<'cx>,
561
+ object: Handle<'cx, JsObject>,
562
+ source: Handle<'cx, JsObject>,
563
+ ) -> JsResult<'cx, JsObject> {
564
+ let object_class = cx.global::<JsFunction>("Object")?;
565
+ let assign_function = object_class.get::<JsFunction, _, _>(cx, "assign")?;
566
+ let null = cx.null();
567
+ assign_function.call(cx, null, vec![object.upcast(), source.upcast()])?;
568
+
569
+ Ok(object)
570
+ }