@temporalio/core-bridge 1.8.5 → 1.9.0-rc.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 (196) hide show
  1. package/Cargo.lock +189 -152
  2. package/Cargo.toml +1 -0
  3. package/lib/index.d.ts +17 -44
  4. package/lib/index.js.map +1 -1
  5. package/package.json +3 -4
  6. package/releases/aarch64-apple-darwin/index.node +0 -0
  7. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  8. package/releases/x86_64-apple-darwin/index.node +0 -0
  9. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  10. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  11. package/sdk-core/.github/workflows/heavy.yml +4 -0
  12. package/sdk-core/.github/workflows/per-pr.yml +96 -0
  13. package/sdk-core/ARCHITECTURE.md +1 -1
  14. package/sdk-core/Cargo.toml +6 -0
  15. package/sdk-core/README.md +37 -21
  16. package/sdk-core/client/Cargo.toml +6 -3
  17. package/sdk-core/client/src/lib.rs +272 -138
  18. package/sdk-core/client/src/metrics.rs +68 -57
  19. package/sdk-core/client/src/raw.rs +191 -45
  20. package/sdk-core/client/src/retry.rs +20 -0
  21. package/sdk-core/client/src/worker_registry/mod.rs +264 -0
  22. package/sdk-core/client/src/workflow_handle/mod.rs +2 -1
  23. package/sdk-core/core/Cargo.toml +16 -18
  24. package/sdk-core/core/src/core_tests/child_workflows.rs +7 -7
  25. package/sdk-core/core/src/core_tests/mod.rs +1 -0
  26. package/sdk-core/core/src/core_tests/replay_flag.rs +29 -39
  27. package/sdk-core/core/src/core_tests/updates.rs +73 -0
  28. package/sdk-core/core/src/core_tests/workflow_tasks.rs +52 -1
  29. package/sdk-core/core/src/ephemeral_server/mod.rs +34 -11
  30. package/sdk-core/core/src/internal_flags.rs +7 -1
  31. package/sdk-core/core/src/lib.rs +19 -36
  32. package/sdk-core/core/src/protosext/mod.rs +11 -3
  33. package/sdk-core/core/src/protosext/protocol_messages.rs +102 -0
  34. package/sdk-core/core/src/replay/mod.rs +100 -48
  35. package/sdk-core/core/src/telemetry/log_export.rs +161 -28
  36. package/sdk-core/core/src/telemetry/metrics.rs +869 -248
  37. package/sdk-core/core/src/telemetry/mod.rs +135 -239
  38. package/sdk-core/core/src/telemetry/prometheus_server.rs +36 -31
  39. package/sdk-core/core/src/test_help/mod.rs +63 -4
  40. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +12 -2
  41. package/sdk-core/core/src/worker/activities.rs +276 -10
  42. package/sdk-core/core/src/worker/client/mocks.rs +18 -0
  43. package/sdk-core/core/src/worker/client.rs +16 -3
  44. package/sdk-core/core/src/worker/mod.rs +50 -19
  45. package/sdk-core/core/src/worker/slot_provider.rs +175 -0
  46. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +27 -34
  47. package/sdk-core/core/src/worker/workflow/history_update.rs +4 -1
  48. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +36 -94
  49. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +34 -22
  50. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +50 -34
  51. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +106 -92
  52. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +22 -21
  53. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +386 -499
  54. package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -2
  55. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +33 -26
  56. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +198 -215
  57. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +66 -62
  58. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +88 -119
  59. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +3 -1
  60. package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +411 -0
  61. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +26 -25
  62. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +302 -85
  63. package/sdk-core/core/src/worker/workflow/managed_run.rs +179 -132
  64. package/sdk-core/core/src/worker/workflow/mod.rs +121 -46
  65. package/sdk-core/core/src/worker/workflow/run_cache.rs +8 -12
  66. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +45 -38
  67. package/sdk-core/core-api/Cargo.toml +7 -6
  68. package/sdk-core/core-api/src/lib.rs +4 -12
  69. package/sdk-core/core-api/src/telemetry/metrics.rs +334 -0
  70. package/sdk-core/core-api/src/telemetry.rs +53 -42
  71. package/sdk-core/core-api/src/worker.rs +7 -0
  72. package/sdk-core/{.buildkite/docker → docker}/docker-compose.yaml +1 -1
  73. package/sdk-core/etc/dynamic-config.yaml +11 -1
  74. package/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +1 -1
  75. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +1 -3
  76. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +2 -2
  77. package/sdk-core/sdk/Cargo.toml +1 -1
  78. package/sdk-core/sdk/src/lib.rs +85 -7
  79. package/sdk-core/sdk/src/workflow_context/options.rs +4 -0
  80. package/sdk-core/sdk/src/workflow_context.rs +43 -15
  81. package/sdk-core/sdk/src/workflow_future.rs +334 -204
  82. package/sdk-core/sdk-core-protos/Cargo.toml +2 -2
  83. package/sdk-core/sdk-core-protos/build.rs +14 -14
  84. package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/Dockerfile +2 -0
  85. package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +99 -0
  86. package/sdk-core/sdk-core-protos/protos/api_upstream/api-linter.yaml +56 -0
  87. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.gen.yaml +20 -0
  88. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.lock +11 -0
  89. package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +18 -0
  90. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/annotations.proto +31 -0
  91. package/sdk-core/sdk-core-protos/protos/api_upstream/google/api/http.proto +379 -0
  92. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/any.proto +162 -0
  93. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/descriptor.proto +1212 -0
  94. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/duration.proto +115 -0
  95. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/empty.proto +51 -0
  96. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/timestamp.proto +144 -0
  97. package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/wrappers.proto +123 -0
  98. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/batch/v1/message.proto +3 -5
  99. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/command/v1/message.proto +11 -13
  100. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/common/v1/message.proto +2 -4
  101. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
  102. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/reset.proto +1 -1
  103. package/sdk-core/{protos/api_upstream/build/tools.go → sdk-core-protos/protos/api_upstream/temporal/api/export/v1/message.proto} +22 -6
  104. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/filter/v1/message.proto +2 -4
  105. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/history/v1/message.proto +21 -23
  106. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/namespace/v1/message.proto +2 -4
  107. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/request_response.proto +2 -0
  108. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/operatorservice/v1/service.proto +4 -0
  109. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/replication/v1/message.proto +1 -3
  110. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/schedule/v1/message.proto +36 -20
  111. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +13 -0
  112. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -4
  113. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/update/v1/message.proto +1 -1
  114. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/version/v1/message.proto +2 -3
  115. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflow/v1/message.proto +18 -20
  116. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/request_response.proto +84 -32
  117. package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/workflowservice/v1/service.proto +205 -47
  118. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +57 -0
  119. package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +27 -0
  120. package/sdk-core/sdk-core-protos/src/history_builder.rs +67 -2
  121. package/sdk-core/sdk-core-protos/src/lib.rs +75 -2
  122. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
  123. package/sdk-core/test-utils/Cargo.toml +5 -1
  124. package/sdk-core/test-utils/src/canned_histories.rs +3 -57
  125. package/sdk-core/test-utils/src/interceptors.rs +46 -0
  126. package/sdk-core/test-utils/src/lib.rs +106 -38
  127. package/sdk-core/tests/integ_tests/metrics_tests.rs +110 -15
  128. package/sdk-core/tests/integ_tests/queries_tests.rs +174 -3
  129. package/sdk-core/tests/integ_tests/update_tests.rs +908 -0
  130. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +44 -1
  131. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -1
  132. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
  133. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -4
  134. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +61 -0
  135. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +27 -2
  136. package/sdk-core/tests/integ_tests/workflow_tests.rs +1 -0
  137. package/sdk-core/tests/main.rs +2 -1
  138. package/sdk-core/tests/runner.rs +15 -2
  139. package/src/conversions.rs +75 -89
  140. package/src/helpers.rs +74 -0
  141. package/src/runtime.rs +17 -6
  142. package/src/worker.rs +14 -61
  143. package/ts/index.ts +21 -52
  144. package/sdk-core/.buildkite/docker/Dockerfile +0 -9
  145. package/sdk-core/.buildkite/docker/build.sh +0 -5
  146. package/sdk-core/.buildkite/docker/docker-compose-ci.yaml +0 -27
  147. package/sdk-core/.buildkite/pipeline.yml +0 -57
  148. package/sdk-core/.github/workflows/semgrep.yml +0 -25
  149. package/sdk-core/core/src/worker/workflow/bridge.rs +0 -35
  150. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +0 -215
  151. package/sdk-core/protos/api_upstream/.buildkite/Dockerfile +0 -2
  152. package/sdk-core/protos/api_upstream/Makefile +0 -80
  153. package/sdk-core/protos/api_upstream/api-linter.yaml +0 -40
  154. package/sdk-core/protos/api_upstream/buf.yaml +0 -9
  155. package/sdk-core/protos/api_upstream/build/go.mod +0 -7
  156. package/sdk-core/protos/api_upstream/build/go.sum +0 -5
  157. package/sdk-core/protos/api_upstream/go.mod +0 -6
  158. package/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +0 -141
  159. /package/sdk-core/{.buildkite/docker → docker}/docker-compose-telem.yaml +0 -0
  160. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/docker-compose.yml +0 -0
  161. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.buildkite/pipeline.yml +0 -0
  162. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/CODEOWNERS +0 -0
  163. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  164. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/publish-docs.yml +0 -0
  165. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/.github/workflows/trigger-api-go-update.yml +0 -0
  166. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/LICENSE +0 -0
  167. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/README.md +0 -0
  168. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/batch_operation.proto +0 -0
  169. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/command_type.proto +0 -0
  170. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/common.proto +0 -0
  171. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/event_type.proto +0 -0
  172. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/namespace.proto +0 -0
  173. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/query.proto +0 -0
  174. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/schedule.proto +0 -0
  175. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/task_queue.proto +0 -0
  176. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/update.proto +0 -0
  177. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/enums/v1/workflow.proto +0 -0
  178. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/errordetails/v1/message.proto +0 -0
  179. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/failure/v1/message.proto +0 -0
  180. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/protocol/v1/message.proto +0 -0
  181. /package/sdk-core/{protos → sdk-core-protos/protos}/api_upstream/temporal/api/query/v1/message.proto +0 -0
  182. /package/sdk-core/{protos → sdk-core-protos/protos}/google/rpc/status.proto +0 -0
  183. /package/sdk-core/{protos → sdk-core-protos/protos}/grpc/health/v1/health.proto +0 -0
  184. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_result/activity_result.proto +0 -0
  185. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/activity_task/activity_task.proto +0 -0
  186. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/child_workflow/child_workflow.proto +0 -0
  187. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/common/common.proto +0 -0
  188. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/core_interface.proto +0 -0
  189. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/external_data/external_data.proto +0 -0
  190. /package/sdk-core/{protos → sdk-core-protos/protos}/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +0 -0
  191. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/Makefile +0 -0
  192. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/api-linter.yaml +0 -0
  193. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/buf.yaml +0 -0
  194. /package/sdk-core/{protos/api_upstream → sdk-core-protos/protos/testsrv_upstream}/dependencies/gogoproto/gogo.proto +0 -0
  195. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +0 -0
  196. /package/sdk-core/{protos → sdk-core-protos/protos}/testsrv_upstream/temporal/api/testservice/v1/service.proto +0 -0
@@ -2,7 +2,10 @@ use crate::integ_tests::activity_functions::echo;
2
2
  use anyhow::anyhow;
3
3
  use assert_matches::assert_matches;
4
4
  use futures_util::future::join_all;
5
- use std::time::Duration;
5
+ use std::{
6
+ sync::atomic::{AtomicBool, Ordering},
7
+ time::Duration,
8
+ };
6
9
  use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowExecutionResult, WorkflowOptions};
7
10
  use temporal_sdk::{
8
11
  ActContext, ActExitValue, ActivityCancelledError, ActivityOptions, CancellableFuture,
@@ -974,3 +977,43 @@ async fn graceful_shutdown() {
974
977
  };
975
978
  join!(shutdowner, runner);
976
979
  }
980
+
981
+ #[tokio::test]
982
+ async fn activity_can_be_cancelled_by_local_timeout() {
983
+ let wf_name = "activity_can_be_cancelled_by_local_timeout";
984
+ let mut starter = CoreWfStarter::new(wf_name);
985
+ starter
986
+ .worker_config
987
+ .local_timeout_buffer_for_activities(Duration::from_secs(0));
988
+ let mut worker = starter.worker().await;
989
+ worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
990
+ let res = ctx
991
+ .activity(ActivityOptions {
992
+ activity_type: "echo_activity".to_string(),
993
+ start_to_close_timeout: Some(Duration::from_secs(1)),
994
+ input: "hi!".as_json_payload().expect("serializes fine"),
995
+ retry_policy: Some(RetryPolicy {
996
+ maximum_attempts: 1,
997
+ ..Default::default()
998
+ }),
999
+ ..Default::default()
1000
+ })
1001
+ .await;
1002
+ assert!(res.timed_out().is_some());
1003
+ Ok(().into())
1004
+ });
1005
+ static WAS_CANCELLED: AtomicBool = AtomicBool::new(false);
1006
+ worker.register_activity(
1007
+ "echo_activity",
1008
+ |ctx: ActContext, echo_me: String| async move {
1009
+ // Doesn't heartbeat
1010
+ ctx.cancelled().await;
1011
+ WAS_CANCELLED.store(true, Ordering::Relaxed);
1012
+ Ok(echo_me)
1013
+ },
1014
+ );
1015
+
1016
+ starter.start_with_worker(wf_name, &mut worker).await;
1017
+ worker.run_until_done().await.unwrap();
1018
+ assert!(WAS_CANCELLED.load(Ordering::Relaxed));
1019
+ }
@@ -25,7 +25,7 @@ async fn cancel_sender(ctx: WfContext) -> WorkflowResult<()> {
25
25
  Ok(().into())
26
26
  }
27
27
 
28
- async fn cancel_receiver(mut ctx: WfContext) -> WorkflowResult<()> {
28
+ async fn cancel_receiver(ctx: WfContext) -> WorkflowResult<()> {
29
29
  ctx.cancelled().await;
30
30
  Ok(().into())
31
31
  }
@@ -4,7 +4,7 @@ use temporal_sdk::{WfContext, WfExitValue, WorkflowResult};
4
4
  use temporal_sdk_core_protos::temporal::api::enums::v1::WorkflowExecutionStatus;
5
5
  use temporal_sdk_core_test_utils::CoreWfStarter;
6
6
 
7
- async fn cancelled_wf(mut ctx: WfContext) -> WorkflowResult<()> {
7
+ async fn cancelled_wf(ctx: WfContext) -> WorkflowResult<()> {
8
8
  let cancelled = tokio::select! {
9
9
  _ = ctx.timer(Duration::from_secs(500)) => false,
10
10
  _ = ctx.cancelled() => true
@@ -64,7 +64,7 @@ async fn abandoned_child_bug_repro() {
64
64
 
65
65
  worker.register_wf(
66
66
  PARENT_WF_TYPE.to_string(),
67
- move |mut ctx: WfContext| async move {
67
+ move |ctx: WfContext| async move {
68
68
  let child = ctx.child_workflow(ChildWorkflowOptions {
69
69
  workflow_id: "abandoned-child".to_owned(),
70
70
  workflow_type: CHILD_WF_TYPE.to_owned(),
@@ -89,7 +89,7 @@ async fn abandoned_child_bug_repro() {
89
89
  Ok(().into())
90
90
  },
91
91
  );
92
- worker.register_wf(CHILD_WF_TYPE.to_string(), |mut ctx: WfContext| async move {
92
+ worker.register_wf(CHILD_WF_TYPE.to_string(), |ctx: WfContext| async move {
93
93
  ctx.cancelled().await;
94
94
  Ok(WfExitValue::<()>::Cancelled)
95
95
  });
@@ -135,9 +135,9 @@ async fn abandoned_child_resolves_post_cancel() {
135
135
 
136
136
  worker.register_wf(
137
137
  PARENT_WF_TYPE.to_string(),
138
- move |mut ctx: WfContext| async move {
138
+ move |ctx: WfContext| async move {
139
139
  let child = ctx.child_workflow(ChildWorkflowOptions {
140
- workflow_id: "abandoned-child".to_owned(),
140
+ workflow_id: "abandoned-child-resolve-post-cancel".to_owned(),
141
141
  workflow_type: CHILD_WF_TYPE.to_owned(),
142
142
  parent_close_policy: ParentClosePolicy::Abandon,
143
143
  cancel_type: ChildWorkflowCancellationType::Abandon,
@@ -0,0 +1,61 @@
1
+ use std::time::Duration;
2
+ use temporal_client::{WorkflowClientTrait, WorkflowExecutionInfo};
3
+ use temporal_sdk::{WfContext, WorkflowResult};
4
+ use temporal_sdk_core_test_utils::{get_integ_server_options, CoreWfStarter, NAMESPACE};
5
+
6
+ pub async fn eager_wf(_context: WfContext) -> WorkflowResult<()> {
7
+ Ok(().into())
8
+ }
9
+
10
+ #[tokio::test]
11
+ async fn eager_wf_start() {
12
+ let wf_name = "eager_wf_start";
13
+ let mut starter = CoreWfStarter::new(wf_name);
14
+ starter.workflow_options.enable_eager_workflow_start = true;
15
+ // hang the test if eager task dispatch failed
16
+ starter.workflow_options.task_timeout = Some(Duration::from_secs(1500));
17
+ starter.no_remote_activities();
18
+ let mut worker = starter.worker().await;
19
+ worker.register_wf(wf_name.to_owned(), eager_wf);
20
+ starter.eager_start_with_worker(wf_name, &mut worker).await;
21
+ worker.run_until_done().await.unwrap();
22
+ }
23
+
24
+ #[tokio::test]
25
+ async fn eager_wf_start_different_clients() {
26
+ let wf_name = "eager_wf_start";
27
+ let mut starter = CoreWfStarter::new(wf_name);
28
+ starter.workflow_options.enable_eager_workflow_start = true;
29
+ // hang the test if wf task needs retry
30
+ starter.workflow_options.task_timeout = Some(Duration::from_secs(1500));
31
+ starter.no_remote_activities();
32
+ let mut worker = starter.worker().await;
33
+ worker.register_wf(wf_name.to_owned(), eager_wf);
34
+
35
+ let client = get_integ_server_options()
36
+ .connect(NAMESPACE.to_string(), None, None)
37
+ .await
38
+ .expect("Should connect");
39
+ let w = starter.get_worker().await;
40
+ let res = client
41
+ .start_workflow(
42
+ vec![],
43
+ w.get_config().task_queue.clone(), // task_queue
44
+ wf_name.to_string(), // workflow_id
45
+ wf_name.to_string(), // workflow_type
46
+ None,
47
+ starter.workflow_options.clone(),
48
+ )
49
+ .await
50
+ .unwrap();
51
+ // different clients means no eager_wf_start.
52
+ assert!(res.eager_workflow_task.is_none());
53
+
54
+ //wf task delivered through default path
55
+ worker.started_workflows.lock().push(WorkflowExecutionInfo {
56
+ namespace: NAMESPACE.to_string(),
57
+ workflow_id: wf_name.to_string(),
58
+ run_id: Some(res.run_id.clone()),
59
+ });
60
+ worker.run_until_done().await.unwrap();
61
+ }
@@ -167,6 +167,19 @@ async fn replay_ok_ending_with_timed_out() {
167
167
  replay_abrupt_ending(t2).await;
168
168
  }
169
169
 
170
+ #[tokio::test]
171
+ async fn replay_shutdown_worker() {
172
+ let t = canned_histories::single_timer("1");
173
+ let func = timers_wf(1);
174
+ let mut worker = replay_sdk_worker([test_hist_to_replay(t)]);
175
+ worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
176
+ let shutdown_ctr_i = UniqueShutdownWorker::default();
177
+ let shutdown_ctr = shutdown_ctr_i.runs.clone();
178
+ worker.set_worker_interceptor(shutdown_ctr_i);
179
+ worker.run().await.unwrap();
180
+ assert_eq!(shutdown_ctr.lock().len(), 1);
181
+ }
182
+
170
183
  #[rstest::rstest]
171
184
  #[tokio::test]
172
185
  async fn multiple_histories_replay(#[values(false, true)] use_feeder: bool) {
@@ -188,7 +201,7 @@ async fn multiple_histories_replay(#[values(false, true)] use_feeder: bool) {
188
201
  };
189
202
  let runs_ctr_i = UniqueRunsCounter::default();
190
203
  let runs_ctr = runs_ctr_i.runs.clone();
191
- worker.set_worker_interceptor(Box::new(runs_ctr_i));
204
+ worker.set_worker_interceptor(runs_ctr_i);
192
205
  worker.register_wf("onetimer", one_timer_wf);
193
206
  worker.register_wf("seqtimer", seq_timer_wf);
194
207
 
@@ -287,6 +300,18 @@ impl WorkerInterceptor for UniqueRunsCounter {
287
300
  async fn on_workflow_activation_completion(&self, completion: &WorkflowActivationCompletion) {
288
301
  self.runs.lock().insert(completion.run_id.clone());
289
302
  }
303
+ }
290
304
 
291
- fn on_shutdown(&self, _: &Worker) {}
305
+ #[derive(Default)]
306
+ struct UniqueShutdownWorker {
307
+ runs: Arc<Mutex<HashSet<String>>>,
308
+ }
309
+ #[async_trait::async_trait(?Send)]
310
+ impl WorkerInterceptor for UniqueShutdownWorker {
311
+ fn on_shutdown(&self, _sdk_worker: &Worker) {
312
+ // Assumed one worker per task queue.
313
+ self.runs
314
+ .lock()
315
+ .insert(_sdk_worker.task_queue().to_string());
316
+ }
292
317
  }
@@ -5,6 +5,7 @@ mod cancel_wf;
5
5
  mod child_workflows;
6
6
  mod continue_as_new;
7
7
  mod determinism;
8
+ mod eager;
8
9
  mod local_activities;
9
10
  mod modify_wf_properties;
10
11
  mod patches;
@@ -14,6 +14,7 @@ mod integ_tests {
14
14
  mod metrics_tests;
15
15
  mod polling_tests;
16
16
  mod queries_tests;
17
+ mod update_tests;
17
18
  mod visibility_tests;
18
19
  mod workflow_tests;
19
20
 
@@ -37,7 +38,7 @@ mod integ_tests {
37
38
  let opts = get_integ_server_options();
38
39
  let runtime = CoreRuntime::new_assume_tokio(get_integ_telem_options()).unwrap();
39
40
  let mut retrying_client = opts
40
- .connect_no_namespace(runtime.metric_meter().as_deref(), None)
41
+ .connect_no_namespace(runtime.telemetry().get_temporal_metric_meter(), None)
41
42
  .await
42
43
  .unwrap();
43
44
 
@@ -70,10 +70,19 @@ async fn main() -> Result<(), anyhow::Error> {
70
70
  ServerKind::TemporalCLI => {
71
71
  let config = TemporalDevServerConfigBuilder::default()
72
72
  .exe(default_cached_download())
73
+ // TODO: Delete when temporalCLI enables it by default.
74
+ .extra_args(vec![
75
+ "--dynamic-config-value".to_string(),
76
+ "system.enableEagerWorkflowStart=true".to_string(),
77
+ ])
73
78
  .build()?;
74
79
  println!("Using temporal CLI");
75
80
  (
76
- Some(config.start_server_with_output(Stdio::null()).await?),
81
+ Some(
82
+ config
83
+ .start_server_with_output(Stdio::null(), Stdio::null())
84
+ .await?,
85
+ ),
77
86
  vec![(INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR, "true")],
78
87
  )
79
88
  }
@@ -83,7 +92,11 @@ async fn main() -> Result<(), anyhow::Error> {
83
92
  .build()?;
84
93
  println!("Using java test server");
85
94
  (
86
- Some(config.start_server_with_output(Stdio::null()).await?),
95
+ Some(
96
+ config
97
+ .start_server_with_output(Stdio::null(), Stdio::null())
98
+ .await?,
99
+ ),
87
100
  vec![(INTEG_TEST_SERVER_USED_ENV_VAR, "true")],
88
101
  )
89
102
  }
@@ -5,18 +5,20 @@ use neon::{
5
5
  prelude::*,
6
6
  types::{JsBoolean, JsNumber, JsString},
7
7
  };
8
- use opentelemetry::trace::{SpanContext, SpanId, TraceFlags, TraceId, TraceState};
9
- use std::{collections::HashMap, net::SocketAddr, str::FromStr, time::Duration};
8
+ use std::{collections::HashMap, net::SocketAddr, sync::Arc, time::Duration};
10
9
  use temporal_sdk_core::{
11
- api::telemetry::{
12
- Logger, MetricTemporality, MetricsExporter, OtelCollectorOptions, TelemetryOptions,
13
- TelemetryOptionsBuilder, TraceExportConfig, TraceExporter,
10
+ api::telemetry::{Logger, MetricTemporality, TelemetryOptions, TelemetryOptionsBuilder},
11
+ api::{
12
+ telemetry::{
13
+ metrics::CoreMeter, OtelCollectorOptionsBuilder, PrometheusExporterOptionsBuilder,
14
+ },
15
+ worker::{WorkerConfig, WorkerConfigBuilder},
14
16
  },
15
- api::worker::{WorkerConfig, WorkerConfigBuilder},
16
17
  ephemeral_server::{
17
18
  TemporalDevServerConfig, TemporalDevServerConfigBuilder, TestServerConfig,
18
19
  TestServerConfigBuilder,
19
20
  },
21
+ telemetry::{build_otlp_metric_exporter, start_prometheus_metric_exporter},
20
22
  ClientOptions, ClientOptionsBuilder, ClientTlsConfig, RetryConfig, TlsConfig, Url,
21
23
  };
22
24
 
@@ -44,7 +46,6 @@ impl ArrayHandleConversionsExt for Handle<'_, JsArray> {
44
46
 
45
47
  pub trait ObjectHandleConversionsExt {
46
48
  fn set_default(&self, cx: &mut FunctionContext, key: &str, value: &str) -> NeonResult<()>;
47
- fn as_otel_span_context(&self, ctx: &mut FunctionContext) -> NeonResult<SpanContext>;
48
49
  fn as_client_options(&self, ctx: &mut FunctionContext) -> NeonResult<ClientOptions>;
49
50
  fn as_telemetry_options(&self, cx: &mut FunctionContext) -> NeonResult<TelemetryOptions>;
50
51
  fn as_worker_config(&self, cx: &mut FunctionContext) -> NeonResult<WorkerConfig>;
@@ -60,19 +61,6 @@ pub trait ObjectHandleConversionsExt {
60
61
  }
61
62
 
62
63
  impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
63
- fn as_otel_span_context(&self, ctx: &mut FunctionContext) -> NeonResult<SpanContext> {
64
- let trace_id = js_value_getter!(ctx, self, "traceId", JsString);
65
- let span_id = js_value_getter!(ctx, self, "spanId", JsString);
66
- let trace_flags = js_value_getter!(ctx, self, "traceFlags", JsNumber);
67
- Ok(SpanContext::new(
68
- TraceId::from_hex(&trace_id).expect("TraceId is valid"),
69
- SpanId::from_hex(&span_id).expect("SpanId is valid"),
70
- TraceFlags::new(trace_flags as u8),
71
- false,
72
- TraceState::from_str("").expect("Trace state must be valid"),
73
- ))
74
- }
75
-
76
64
  fn as_hash_map_of_string_to_string(
77
65
  &self,
78
66
  cx: &mut FunctionContext,
@@ -178,10 +166,11 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
178
166
 
179
167
  fn as_telemetry_options(&self, cx: &mut FunctionContext) -> NeonResult<TelemetryOptions> {
180
168
  let mut telemetry_opts = TelemetryOptionsBuilder::default();
181
- telemetry_opts.no_temporal_prefix_for_metrics(
182
- js_optional_value_getter!(cx, self, "noTemporalPrefixForMetrics", JsBoolean)
183
- .unwrap_or_default(),
184
- );
169
+ if js_optional_value_getter!(cx, self, "noTemporalPrefixForMetrics", JsBoolean)
170
+ .unwrap_or_default()
171
+ {
172
+ telemetry_opts.metric_prefix("".to_string());
173
+ }
185
174
 
186
175
  if let Some(ref logging) = js_optional_getter!(cx, self, "logging", JsObject) {
187
176
  let filter = js_value_getter!(cx, logging, "filter", JsString);
@@ -197,52 +186,72 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
197
186
  }
198
187
 
199
188
  if let Some(ref metrics) = js_optional_getter!(cx, self, "metrics", JsObject) {
200
- if let Some(temporality) =
201
- js_optional_value_getter!(cx, metrics, "temporality", JsString)
202
- {
203
- match temporality.as_str() {
204
- "cumulative" => {
205
- telemetry_opts.metric_temporality(MetricTemporality::Cumulative);
206
- }
207
- "delta" => {
208
- telemetry_opts.metric_temporality(MetricTemporality::Delta);
209
- }
210
- _ => {
211
- cx.throw_type_error("Invalid telemetryOptions.metrics.temporality, expected 'cumulative' or 'delta'")?;
212
- }
213
- };
214
- }
215
189
  if let Some(ref prom) = js_optional_getter!(cx, metrics, "prometheus", JsObject) {
190
+ if js_optional_getter!(cx, metrics, "otel", JsObject).is_some() {
191
+ cx.throw_type_error(
192
+ "Invalid telemetryOptions.metrics: can't have both premetheus and otel at the same time",
193
+ )?
194
+ }
195
+
196
+ let mut options = PrometheusExporterOptionsBuilder::default();
197
+
216
198
  let addr = js_value_getter!(cx, prom, "bindAddress", JsString);
217
199
  match addr.parse::<SocketAddr>() {
218
- Ok(address) => telemetry_opts.metrics(MetricsExporter::Prometheus(address)),
219
- Err(_) => cx.throw_type_error(
220
- "Invalid telemetryOptions.metrics.prometheus.bindAddress",
221
- )?,
200
+ Ok(addr) => options.socket_addr(addr),
201
+ Err(_) => {
202
+ return cx.throw_type_error(
203
+ "Invalid telemetryOptions.metrics.prometheus.bindAddress",
204
+ )?
205
+ }
222
206
  };
207
+
208
+ let options = options
209
+ .build()
210
+ .expect("Failed to build prometheus exporter options");
211
+ let prom_info = start_prometheus_metric_exporter(options)
212
+ .expect("Failed creating prometheus exporter");
213
+ telemetry_opts.metrics(prom_info.meter as Arc<dyn CoreMeter>);
223
214
  } else if let Some(ref otel) = js_optional_getter!(cx, metrics, "otel", JsObject) {
215
+ let mut options = OtelCollectorOptionsBuilder::default();
216
+
224
217
  let url = js_value_getter!(cx, otel, "url", JsString);
225
- let url = match Url::parse(&url) {
226
- Ok(url) => url,
227
- Err(_) => cx.throw_type_error("Invalid telemetryOptions.metrics.otel.url")?,
218
+ match Url::parse(&url) {
219
+ Ok(url) => options.url(url),
220
+ Err(_) => {
221
+ return cx.throw_type_error("Invalid telemetryOptions.metrics.otel.url")
222
+ }
223
+ };
224
+
225
+ if let Some(ref headers) = js_optional_getter!(cx, otel, "headers", JsObject) {
226
+ options.headers(headers.as_hash_map_of_string_to_string(cx)?);
228
227
  };
229
- let headers =
230
- if let Some(ref headers) = js_optional_getter!(cx, otel, "headers", JsObject) {
231
- headers.as_hash_map_of_string_to_string(cx)?
232
- } else {
233
- Default::default()
228
+
229
+ if let Some(metric_periodicity) =
230
+ js_optional_value_getter!(cx, otel, "metricsExportInterval", JsNumber)
231
+ .map(|f| f as u64)
232
+ {
233
+ options.metric_periodicity(Duration::from_millis(metric_periodicity));
234
+ }
235
+
236
+ // FIXME: Move temporality to the otel object
237
+ if let Some(temporality) =
238
+ js_optional_value_getter!(cx, metrics, "temporality", JsString)
239
+ {
240
+ match temporality.as_str() {
241
+ "cumulative" => options.metric_temporality(MetricTemporality::Cumulative),
242
+ "delta" => options.metric_temporality(MetricTemporality::Delta),
243
+ _ => {
244
+ return cx.throw_type_error("Invalid telemetryOptions.metrics.temporality, expected 'cumulative' or 'delta'");
245
+ }
234
246
  };
235
- let metric_periodicity = Some(Duration::from_millis(js_value_getter!(
236
- cx,
237
- otel,
238
- "metricsExportInterval",
239
- JsNumber
240
- ) as u64));
241
- telemetry_opts.metrics(MetricsExporter::Otel(OtelCollectorOptions {
242
- url,
243
- headers,
244
- metric_periodicity,
245
- }));
247
+ };
248
+
249
+ let options = options
250
+ .build()
251
+ .expect("Failed to build otlp exporter options");
252
+ let otlp_exporter =
253
+ build_otlp_metric_exporter(options).expect("Failed to build otlp exporter");
254
+ telemetry_opts.metrics(Arc::new(otlp_exporter) as Arc<dyn CoreMeter>);
246
255
  } else {
247
256
  cx.throw_type_error(
248
257
  "Invalid telemetryOptions.metrics, missing `prometheus` or `otel` option",
@@ -250,33 +259,6 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
250
259
  }
251
260
  }
252
261
 
253
- if let Some(ref tracing) = js_optional_getter!(cx, self, "tracing", JsObject) {
254
- let filter = js_value_getter!(cx, tracing, "filter", JsString);
255
- if let Some(ref otel) = js_optional_getter!(cx, tracing, "otel", JsObject) {
256
- let url = js_value_getter!(cx, otel, "url", JsString);
257
- let url = match Url::parse(&url) {
258
- Ok(url) => url,
259
- Err(_) => cx.throw_type_error("Invalid telemetryOptions.tracing.otel.url")?,
260
- };
261
- let headers =
262
- if let Some(ref headers) = js_optional_getter!(cx, otel, "headers", JsObject) {
263
- headers.as_hash_map_of_string_to_string(cx)?
264
- } else {
265
- Default::default()
266
- };
267
- telemetry_opts.tracing(TraceExportConfig {
268
- filter,
269
- exporter: TraceExporter::Otel(OtelCollectorOptions {
270
- url,
271
- headers,
272
- metric_periodicity: None,
273
- }),
274
- });
275
- } else {
276
- cx.throw_type_error("Invalid telemetryOptions.tracing, missing `otel` option")?
277
- }
278
- }
279
-
280
262
  telemetry_opts.build().map_err(|reason| {
281
263
  cx.throw_type_error::<_, TelemetryOptions>(format!("{}", reason))
282
264
  .unwrap_err()
@@ -332,6 +314,9 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
332
314
  js_optional_getter!(cx, self, "shutdownGraceTimeMs", JsNumber)
333
315
  .map(|num| Duration::from_millis(num.value(cx) as u64));
334
316
 
317
+ let nonsticky_to_sticky_poll_ratio =
318
+ js_value_getter!(cx, self, "nonStickyToStickyPollRatio", JsNumber) as f32;
319
+
335
320
  match WorkerConfigBuilder::default()
336
321
  .worker_build_id(js_value_getter!(cx, self, "buildId", JsString))
337
322
  .client_identity_override(Some(js_value_getter!(cx, self, "identity", JsString)))
@@ -342,6 +327,7 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
342
327
  .max_outstanding_local_activities(max_outstanding_local_activities)
343
328
  .max_concurrent_wft_polls(max_concurrent_wft_polls)
344
329
  .max_concurrent_at_polls(max_concurrent_at_polls)
330
+ .nonsticky_to_sticky_poll_ratio(nonsticky_to_sticky_poll_ratio)
345
331
  .max_cached_workflows(max_cached_workflows)
346
332
  .sticky_queue_schedule_to_start_timeout(sticky_queue_schedule_to_start_timeout)
347
333
  .graceful_shutdown_period(graceful_shutdown_period)
package/src/helpers.rs CHANGED
@@ -187,3 +187,77 @@ where
187
187
  cx.throw_type_error::<_, Vec<u8>>(format!("Invalid or missing {}", full_attr_path))
188
188
  }
189
189
  }
190
+
191
+ // Recursively convert a Serde value to a JS value
192
+ pub fn serde_value_to_js_value<'a>(
193
+ cx: &mut impl Context<'a>,
194
+ val: serde_json::Value,
195
+ ) -> JsResult<'a, JsValue> {
196
+ match val {
197
+ serde_json::Value::String(s) => Ok(cx.string(s).upcast()),
198
+ serde_json::Value::Number(n) => Ok(cx.number(n.as_f64().unwrap()).upcast()),
199
+ serde_json::Value::Bool(b) => Ok(cx.boolean(b).upcast()),
200
+ serde_json::Value::Null => Ok(cx.null().upcast()),
201
+ serde_json::Value::Array(vec) => {
202
+ let arr: Handle<'a, JsArray> = JsArray::new(cx, vec.len() as u32);
203
+ for (i, v) in vec.into_iter().enumerate() {
204
+ let v = serde_value_to_js_value(cx, v)?;
205
+ arr.set(cx, i as u32, v)?;
206
+ }
207
+ Ok(arr.upcast())
208
+ }
209
+ serde_json::Value::Object(map) => hashmap_to_js_value(cx, map).map(|v| v.upcast()),
210
+ }
211
+ }
212
+
213
+ pub fn hashmap_to_js_value<'a>(
214
+ cx: &mut impl Context<'a>,
215
+ map: impl IntoIterator<Item = (String, serde_json::Value)>,
216
+ ) -> JsResult<'a, JsObject> {
217
+ let obj: Handle<'a, JsObject> = cx.empty_object();
218
+ for (k, v) in map {
219
+ let k = cx.string(snake_to_camel(k));
220
+ let v = serde_value_to_js_value(cx, v)?;
221
+ obj.set(cx, k, v)?;
222
+ }
223
+ Ok(obj)
224
+ }
225
+
226
+ fn snake_to_camel(input: String) -> String {
227
+ match input.find('_') {
228
+ None => input,
229
+ Some(first) => {
230
+ let mut result = String::with_capacity(input.len());
231
+ if first > 0 {
232
+ result.push_str(&input[..first]);
233
+ }
234
+ let mut capitalize = true;
235
+ for c in input[first + 1..].chars() {
236
+ if c == '_' {
237
+ capitalize = true;
238
+ } else if capitalize {
239
+ result.push(c.to_ascii_uppercase());
240
+ capitalize = false;
241
+ } else {
242
+ result.push(c.to_ascii_lowercase());
243
+ }
244
+ }
245
+ result
246
+ }
247
+ }
248
+ }
249
+
250
+ #[cfg(test)]
251
+ mod tests {
252
+ use super::*;
253
+
254
+ #[test]
255
+ fn snake_to_camel_works() {
256
+ assert_eq!(snake_to_camel("this_is_a_test".into()), "thisIsATest");
257
+ assert_eq!(snake_to_camel("this___IS_a_TEST".into()), "thisIsATest");
258
+ assert_eq!(
259
+ snake_to_camel("éàç_this_is_a_test".into()),
260
+ "éàçThisIsATest"
261
+ );
262
+ }
263
+ }
package/src/runtime.rs CHANGED
@@ -14,8 +14,10 @@ use temporal_client::{ClientInitError, ConfiguredClient, TemporalServiceClientWi
14
14
  use temporal_sdk_core::api::telemetry::{CoreTelemetry, TelemetryOptions};
15
15
  use temporal_sdk_core::CoreRuntime;
16
16
  use temporal_sdk_core::{
17
- ephemeral_server::EphemeralServer as CoreEphemeralServer, init_replay_worker, init_worker,
18
- replay::HistoryForReplay, ClientOptions, RetryClient, WorkerConfig,
17
+ ephemeral_server::EphemeralServer as CoreEphemeralServer,
18
+ init_replay_worker, init_worker,
19
+ replay::{HistoryForReplay, ReplayWorkerInput},
20
+ ClientOptions, RetryClient, WorkerConfig,
19
21
  };
20
22
  use tokio::sync::{
21
23
  mpsc::{channel, unbounded_channel, Sender, UnboundedReceiver, UnboundedSender},
@@ -149,7 +151,7 @@ pub fn start_bridge_loop(
149
151
  core_runtime.tokio_handle().spawn(async move {
150
152
  match options
151
153
  .connect_no_namespace(
152
- runtime_clone.metric_meter().as_deref(),
154
+ runtime_clone.telemetry().get_metric_meter(),
153
155
  headers.map(|h| Arc::new(RwLock::new(h))),
154
156
  )
155
157
  .await
@@ -195,15 +197,24 @@ pub fn start_bridge_loop(
195
197
  send_result(channel.clone(), callback, |cx| {
196
198
  let logarr = cx.empty_array();
197
199
  for (i, cl) in logs.into_iter().enumerate() {
198
- // Not much to do here except for panic when there's an
199
- // error here.
200
+ // Not much to do here except for panic when there's an error here.
200
201
  let logobj = cx.empty_object();
202
+
201
203
  let level = cx.string(cl.level.to_string());
202
204
  logobj.set(cx, "level", level).unwrap();
205
+
203
206
  let ts = system_time_to_js(cx, cl.timestamp).unwrap();
204
207
  logobj.set(cx, "timestamp", ts).unwrap();
208
+
205
209
  let msg = cx.string(cl.message);
206
210
  logobj.set(cx, "message", msg).unwrap();
211
+
212
+ let fieldsobj = hashmap_to_js_value(cx, cl.fields);
213
+ logobj.set(cx, "fields", fieldsobj.unwrap()).unwrap();
214
+
215
+ let target = cx.string(cl.target);
216
+ logobj.set(cx, "target", target).unwrap();
217
+
207
218
  logarr.set(cx, i as u32, logobj).unwrap();
208
219
  }
209
220
  Ok(logarr)
@@ -238,7 +249,7 @@ pub fn start_bridge_loop(
238
249
  callback,
239
250
  } => {
240
251
  let (tunnel, stream) = HistoryForReplayTunnel::new(runtime);
241
- match init_replay_worker(config, Box::pin(stream)) {
252
+ match init_replay_worker(ReplayWorkerInput::new(config, Box::pin(stream))) {
242
253
  Ok(worker) => {
243
254
  let (tx, rx) = unbounded_channel();
244
255
  core_runtime.tokio_handle().spawn(start_worker_loop(