@temporalio/core-bridge 1.13.0 → 1.13.2

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 (181) hide show
  1. package/Cargo.lock +239 -382
  2. package/Cargo.toml +11 -11
  3. package/lib/native.d.ts +10 -3
  4. package/package.json +3 -3
  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/.cargo/config.toml +71 -11
  11. package/sdk-core/.clippy.toml +1 -0
  12. package/sdk-core/.github/workflows/heavy.yml +2 -0
  13. package/sdk-core/.github/workflows/per-pr.yml +50 -18
  14. package/sdk-core/ARCHITECTURE.md +44 -48
  15. package/sdk-core/Cargo.toml +26 -7
  16. package/sdk-core/README.md +4 -0
  17. package/sdk-core/arch_docs/diagrams/TimerMachine_Coverage.puml +14 -0
  18. package/sdk-core/arch_docs/diagrams/initial_event_history.png +0 -0
  19. package/sdk-core/arch_docs/sdks_intro.md +299 -0
  20. package/sdk-core/client/Cargo.toml +8 -7
  21. package/sdk-core/client/src/callback_based.rs +1 -2
  22. package/sdk-core/client/src/lib.rs +485 -299
  23. package/sdk-core/client/src/metrics.rs +32 -8
  24. package/sdk-core/client/src/proxy.rs +124 -5
  25. package/sdk-core/client/src/raw.rs +598 -307
  26. package/sdk-core/client/src/replaceable.rs +253 -0
  27. package/sdk-core/client/src/retry.rs +9 -6
  28. package/sdk-core/client/src/worker_registry/mod.rs +19 -3
  29. package/sdk-core/client/src/workflow_handle/mod.rs +20 -17
  30. package/sdk-core/core/Cargo.toml +100 -31
  31. package/sdk-core/core/src/core_tests/activity_tasks.rs +55 -225
  32. package/sdk-core/core/src/core_tests/mod.rs +2 -8
  33. package/sdk-core/core/src/core_tests/queries.rs +3 -5
  34. package/sdk-core/core/src/core_tests/replay_flag.rs +3 -62
  35. package/sdk-core/core/src/core_tests/updates.rs +4 -5
  36. package/sdk-core/core/src/core_tests/workers.rs +4 -3
  37. package/sdk-core/core/src/core_tests/workflow_cancels.rs +10 -7
  38. package/sdk-core/core/src/core_tests/workflow_tasks.rs +28 -291
  39. package/sdk-core/core/src/ephemeral_server/mod.rs +15 -3
  40. package/sdk-core/core/src/internal_flags.rs +11 -1
  41. package/sdk-core/core/src/lib.rs +50 -36
  42. package/sdk-core/core/src/pollers/mod.rs +5 -5
  43. package/sdk-core/core/src/pollers/poll_buffer.rs +2 -2
  44. package/sdk-core/core/src/protosext/mod.rs +13 -5
  45. package/sdk-core/core/src/protosext/protocol_messages.rs +4 -11
  46. package/sdk-core/core/src/retry_logic.rs +256 -108
  47. package/sdk-core/core/src/telemetry/metrics.rs +1 -0
  48. package/sdk-core/core/src/telemetry/mod.rs +8 -2
  49. package/sdk-core/core/src/telemetry/prometheus_meter.rs +2 -2
  50. package/sdk-core/core/src/test_help/integ_helpers.rs +971 -0
  51. package/sdk-core/core/src/test_help/mod.rs +10 -1100
  52. package/sdk-core/core/src/test_help/unit_helpers.rs +218 -0
  53. package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +42 -6
  54. package/sdk-core/core/src/worker/activities/local_activities.rs +19 -19
  55. package/sdk-core/core/src/worker/activities.rs +10 -3
  56. package/sdk-core/core/src/worker/client/mocks.rs +3 -3
  57. package/sdk-core/core/src/worker/client.rs +130 -93
  58. package/sdk-core/core/src/worker/heartbeat.rs +12 -13
  59. package/sdk-core/core/src/worker/mod.rs +31 -21
  60. package/sdk-core/core/src/worker/nexus.rs +14 -3
  61. package/sdk-core/core/src/worker/slot_provider.rs +9 -0
  62. package/sdk-core/core/src/worker/tuner.rs +159 -0
  63. package/sdk-core/core/src/worker/workflow/history_update.rs +3 -265
  64. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -54
  65. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +0 -82
  66. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +0 -67
  67. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -192
  68. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +0 -43
  69. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +6 -554
  70. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -71
  71. package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +102 -3
  72. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +10 -539
  73. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +0 -139
  74. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -119
  75. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +6 -63
  76. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +9 -4
  77. package/sdk-core/core/src/worker/workflow/mod.rs +5 -1
  78. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +8 -3
  79. package/sdk-core/core-api/Cargo.toml +4 -4
  80. package/sdk-core/core-api/src/envconfig.rs +153 -54
  81. package/sdk-core/core-api/src/lib.rs +68 -0
  82. package/sdk-core/core-api/src/telemetry/metrics.rs +2 -1
  83. package/sdk-core/core-api/src/telemetry.rs +13 -0
  84. package/sdk-core/core-c-bridge/Cargo.toml +13 -8
  85. package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +184 -22
  86. package/sdk-core/core-c-bridge/src/client.rs +462 -184
  87. package/sdk-core/core-c-bridge/src/envconfig.rs +314 -0
  88. package/sdk-core/core-c-bridge/src/lib.rs +1 -0
  89. package/sdk-core/core-c-bridge/src/random.rs +4 -4
  90. package/sdk-core/core-c-bridge/src/runtime.rs +22 -23
  91. package/sdk-core/core-c-bridge/src/testing.rs +1 -4
  92. package/sdk-core/core-c-bridge/src/tests/context.rs +31 -31
  93. package/sdk-core/core-c-bridge/src/tests/mod.rs +32 -28
  94. package/sdk-core/core-c-bridge/src/tests/utils.rs +7 -7
  95. package/sdk-core/core-c-bridge/src/worker.rs +319 -66
  96. package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -1
  97. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +5 -5
  98. package/sdk-core/sdk/Cargo.toml +8 -2
  99. package/sdk-core/sdk/src/activity_context.rs +1 -1
  100. package/sdk-core/sdk/src/app_data.rs +1 -1
  101. package/sdk-core/sdk/src/interceptors.rs +1 -4
  102. package/sdk-core/sdk/src/lib.rs +1 -5
  103. package/sdk-core/sdk/src/workflow_context/options.rs +10 -1
  104. package/sdk-core/sdk/src/workflow_future.rs +1 -1
  105. package/sdk-core/sdk-core-protos/Cargo.toml +6 -6
  106. package/sdk-core/sdk-core-protos/build.rs +10 -23
  107. package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +9 -1
  108. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +254 -5
  109. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +234 -5
  110. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +1 -1
  111. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +6 -0
  112. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -2
  113. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -2
  114. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -6
  115. package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  116. package/sdk-core/{test-utils → sdk-core-protos}/src/canned_histories.rs +5 -5
  117. package/sdk-core/sdk-core-protos/src/history_builder.rs +2 -2
  118. package/sdk-core/sdk-core-protos/src/lib.rs +25 -9
  119. package/sdk-core/sdk-core-protos/src/test_utils.rs +89 -0
  120. package/sdk-core/sdk-core-protos/src/utilities.rs +14 -5
  121. package/sdk-core/tests/c_bridge_smoke_test.c +10 -0
  122. package/sdk-core/tests/cloud_tests.rs +10 -8
  123. package/sdk-core/tests/common/http_proxy.rs +134 -0
  124. package/sdk-core/{test-utils/src/lib.rs → tests/common/mod.rs} +214 -281
  125. package/sdk-core/{test-utils/src → tests/common}/workflows.rs +4 -3
  126. package/sdk-core/tests/fuzzy_workflow.rs +1 -1
  127. package/sdk-core/tests/global_metric_tests.rs +8 -7
  128. package/sdk-core/tests/heavy_tests.rs +7 -3
  129. package/sdk-core/tests/integ_tests/client_tests.rs +111 -24
  130. package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +14 -9
  131. package/sdk-core/tests/integ_tests/heartbeat_tests.rs +4 -4
  132. package/sdk-core/tests/integ_tests/metrics_tests.rs +114 -14
  133. package/sdk-core/tests/integ_tests/pagination_tests.rs +273 -0
  134. package/sdk-core/tests/integ_tests/polling_tests.rs +311 -93
  135. package/sdk-core/tests/integ_tests/queries_tests.rs +4 -4
  136. package/sdk-core/tests/integ_tests/update_tests.rs +13 -7
  137. package/sdk-core/tests/integ_tests/visibility_tests.rs +26 -9
  138. package/sdk-core/tests/integ_tests/worker_tests.rs +668 -13
  139. package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +40 -24
  140. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +244 -11
  141. package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +1 -1
  142. package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +78 -2
  143. package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +61 -2
  144. package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +465 -7
  145. package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +41 -2
  146. package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +315 -3
  147. package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
  148. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1990 -14
  149. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +65 -2
  150. package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +123 -23
  151. package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +525 -3
  152. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +65 -16
  153. package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +32 -23
  154. package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +126 -5
  155. package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +1 -2
  156. package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +124 -8
  157. package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +62 -2
  158. package/sdk-core/tests/integ_tests/workflow_tests.rs +67 -8
  159. package/sdk-core/tests/main.rs +26 -17
  160. package/sdk-core/tests/manual_tests.rs +5 -1
  161. package/sdk-core/tests/runner.rs +22 -40
  162. package/sdk-core/tests/shared_tests/mod.rs +1 -1
  163. package/sdk-core/tests/shared_tests/priority.rs +1 -1
  164. package/sdk-core/{core/benches/workflow_replay.rs → tests/workflow_replay_bench.rs} +10 -5
  165. package/src/client.rs +97 -20
  166. package/src/helpers/callbacks.rs +4 -4
  167. package/src/helpers/errors.rs +7 -1
  168. package/src/helpers/handles.rs +1 -0
  169. package/src/helpers/try_from_js.rs +4 -3
  170. package/src/lib.rs +3 -2
  171. package/src/metrics.rs +3 -0
  172. package/src/runtime.rs +5 -2
  173. package/src/worker.rs +9 -12
  174. package/ts/native.ts +13 -3
  175. package/sdk-core/arch_docs/diagrams/workflow_internals.svg +0 -1
  176. package/sdk-core/core/src/core_tests/child_workflows.rs +0 -281
  177. package/sdk-core/core/src/core_tests/determinism.rs +0 -318
  178. package/sdk-core/core/src/core_tests/local_activities.rs +0 -1442
  179. package/sdk-core/test-utils/Cargo.toml +0 -38
  180. package/sdk-core/test-utils/src/histfetch.rs +0 -28
  181. package/sdk-core/test-utils/src/interceptors.rs +0 -46
@@ -1,19 +1,24 @@
1
+ // All non-main.rs tests ignore dead common code so that the linter doesn't complain about about it.
2
+ #[allow(dead_code)]
3
+ mod common;
4
+
5
+ use crate::common::integ_dev_server_config;
1
6
  use anyhow::{anyhow, bail};
2
7
  use clap::Parser;
8
+ use common::INTEG_SERVER_TARGET_ENV_VAR;
3
9
  use std::{
4
10
  env,
5
11
  path::{Path, PathBuf},
6
12
  process::Stdio,
7
13
  };
8
- use temporal_sdk_core::ephemeral_server::{
9
- EphemeralExe, EphemeralExeVersion, TemporalDevServerConfigBuilder, TestServerConfigBuilder,
10
- };
11
- use temporal_sdk_core_test_utils::{
12
- INTEG_SERVER_TARGET_ENV_VAR, INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR,
13
- INTEG_TEST_SERVER_USED_ENV_VAR, SEARCH_ATTR_INT, SEARCH_ATTR_TXT, default_cached_download,
14
- };
14
+ use temporal_sdk_core::ephemeral_server::{TestServerConfigBuilder, default_cached_download};
15
15
  use tokio::{self, process::Command};
16
16
 
17
+ /// This env var is set (to any value) if temporal CLI dev server is in use
18
+ const INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR: &str = "INTEG_TEMPORAL_DEV_SERVER_ON";
19
+ /// This env var is set (to any value) if the test server is in use
20
+ const INTEG_TEST_SERVER_USED_ENV_VAR: &str = "INTEG_TEST_SERVER_ON";
21
+
17
22
  #[derive(clap::Parser)]
18
23
  #[command(author, version, about, long_about = None)]
19
24
  struct Cli {
@@ -58,10 +63,15 @@ async fn main() -> Result<(), anyhow::Error> {
58
63
  } = Cli::parse();
59
64
  let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
60
65
  // Try building first, so that we error early on build failures & don't start server
66
+ // Unclear why --all-features doesn't work here
61
67
  let test_args_preamble = [
62
68
  "test",
63
69
  "--features",
64
70
  "temporal-sdk-core-protos/serde_serialize",
71
+ "--features",
72
+ "test-utilities",
73
+ "--features",
74
+ "ephemeral-server",
65
75
  "--test",
66
76
  &test_name,
67
77
  ]
@@ -84,39 +94,11 @@ async fn main() -> Result<(), anyhow::Error> {
84
94
 
85
95
  let (server, envs) = match server_kind {
86
96
  ServerKind::TemporalCLI => {
87
- let cli_version = if let Some(ver_override) = option_env!("CLI_VERSION_OVERRIDE") {
88
- EphemeralExe::CachedDownload {
89
- version: EphemeralExeVersion::Fixed(ver_override.to_owned()),
90
- dest_dir: None,
91
- ttl: None,
92
- }
93
- } else {
94
- default_cached_download()
95
- };
96
- let config = TemporalDevServerConfigBuilder::default()
97
- .exe(cli_version)
98
- .extra_args(vec![
99
- // TODO: Delete when temporalCLI enables it by default.
100
- "--dynamic-config-value".to_string(),
101
- "system.enableEagerWorkflowStart=true".to_string(),
102
- "--dynamic-config-value".to_string(),
103
- "system.enableNexus=true".to_string(),
104
- "--dynamic-config-value".to_owned(),
105
- "frontend.workerVersioningWorkflowAPIs=true".to_owned(),
106
- "--dynamic-config-value".to_owned(),
107
- "frontend.workerVersioningDataAPIs=true".to_owned(),
108
- "--dynamic-config-value".to_owned(),
109
- "system.enableDeploymentVersions=true".to_owned(),
110
- "--http-port".to_string(),
111
- "7243".to_string(),
112
- "--search-attribute".to_string(),
113
- format!("{SEARCH_ATTR_TXT}=Text"),
114
- "--search-attribute".to_string(),
115
- format!("{SEARCH_ATTR_INT}=Int"),
116
- ])
117
- .ui(true)
118
- .build()?;
119
- println!("Using temporal CLI: {:?}", config);
97
+ let config =
98
+ integ_dev_server_config(vec!["--http-port".to_string(), "7243".to_string()])
99
+ .ui(true)
100
+ .build()?;
101
+ println!("Using temporal CLI: {config:?}");
120
102
  (
121
103
  Some(
122
104
  config
@@ -1,12 +1,12 @@
1
1
  //! Shared tests that are meant to be run against both local dev server and cloud
2
2
 
3
+ use crate::common::CoreWfStarter;
3
4
  use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
4
5
  use temporal_sdk::WfContext;
5
6
  use temporal_sdk_core_protos::temporal::api::{
6
7
  enums::v1::{EventType, WorkflowTaskFailedCause::GrpcMessageTooLarge},
7
8
  history::v1::history_event::Attributes::WorkflowTaskFailedEventAttributes,
8
9
  };
9
- use temporal_sdk_core_test_utils::CoreWfStarter;
10
10
 
11
11
  pub(crate) mod priority;
12
12
 
@@ -1,3 +1,4 @@
1
+ use crate::common::CoreWfStarter;
1
2
  use std::time::Duration;
2
3
  use temporal_client::{
3
4
  GetWorkflowResultOpts, Priority, WfClientExt, WorkflowClientTrait, WorkflowOptions,
@@ -7,7 +8,6 @@ use temporal_sdk_core_protos::{
7
8
  coresdk::AsJsonPayloadExt,
8
9
  temporal::api::{common, history::v1::history_event::Attributes},
9
10
  };
10
- use temporal_sdk_core_test_utils::CoreWfStarter;
11
11
 
12
12
  pub(crate) async fn priority_values_sent_to_server() {
13
13
  let mut starter = if let Some(wfs) =
@@ -1,3 +1,11 @@
1
+ //! This bench lives outside of the traditional /benches directory so it can share common code with
2
+ //! integration tests.
3
+
4
+ // All non-main.rs tests ignore dead common code so that the linter doesn't complain about about it.
5
+ #[allow(dead_code)]
6
+ mod common;
7
+
8
+ use crate::common::{DONT_AUTO_INIT_INTEG_TELEM, prom_metrics, replay_sdk_worker};
1
9
  use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
2
10
  use futures_util::StreamExt;
3
11
  use std::{
@@ -10,10 +18,7 @@ use temporal_sdk_core::{CoreRuntime, replay::HistoryForReplay};
10
18
  use temporal_sdk_core_api::telemetry::metrics::{
11
19
  MetricKeyValue, MetricParametersBuilder, NewAttributes,
12
20
  };
13
- use temporal_sdk_core_protos::DEFAULT_WORKFLOW_TYPE;
14
- use temporal_sdk_core_test_utils::{
15
- DONT_AUTO_INIT_INTEG_TELEM, canned_histories, prom_metrics, replay_sdk_worker,
16
- };
21
+ use temporal_sdk_core_protos::{DEFAULT_WORKFLOW_TYPE, canned_histories};
17
22
 
18
23
  pub fn criterion_benchmark(c: &mut Criterion) {
19
24
  let tokio_runtime = tokio::runtime::Builder::new_current_thread()
@@ -73,7 +78,7 @@ pub fn bench_metrics(c: &mut Criterion) {
73
78
  .build()
74
79
  .unwrap();
75
80
  let _tokio = tokio_runtime.enter();
76
- let (mut telemopts, addr, _aborter) = prom_metrics(None);
81
+ let (mut telemopts, _addr, _aborter) = prom_metrics(None);
77
82
  telemopts.logging = None;
78
83
  let rt = CoreRuntime::new_assume_tokio(telemopts).unwrap();
79
84
  let meter = rt.telemetry().get_metric_meter().unwrap();
package/src/client.rs CHANGED
@@ -3,12 +3,12 @@ use std::time::Duration;
3
3
  use std::{collections::HashMap, sync::Arc};
4
4
 
5
5
  use neon::prelude::*;
6
- use tonic::metadata::MetadataKey;
6
+ use tonic::metadata::{BinaryMetadataValue, MetadataKey};
7
7
 
8
8
  use temporal_sdk_core::{ClientOptions as CoreClientOptions, CoreRuntime, RetryClient};
9
9
 
10
10
  use bridge_macros::{TryFromJs, js_function};
11
- use temporal_client::{ClientInitError, ConfiguredClient, TemporalServiceClientWithMetrics};
11
+ use temporal_client::{ClientInitError, ConfiguredClient, TemporalServiceClient};
12
12
 
13
13
  use crate::runtime::Runtime;
14
14
  use crate::{helpers::*, runtime::RuntimeExt as _};
@@ -38,7 +38,7 @@ pub fn init(cx: &mut neon::prelude::ModuleContext) -> neon::prelude::NeonResult<
38
38
  Ok(())
39
39
  }
40
40
 
41
- type CoreClient = RetryClient<ConfiguredClient<TemporalServiceClientWithMetrics>>;
41
+ type CoreClient = RetryClient<ConfiguredClient<TemporalServiceClient>>;
42
42
 
43
43
  pub struct Client {
44
44
  // These fields are pub because they are accessed from Worker::new
@@ -61,6 +61,10 @@ pub fn client_new(
61
61
 
62
62
  let core_client = match res {
63
63
  Ok(core_client) => core_client,
64
+ Err(ClientInitError::InvalidHeaders(e)) => Err(BridgeError::TypeError {
65
+ message: format!("Invalid metadata key: {e}"),
66
+ field: None,
67
+ })?,
64
68
  Err(ClientInitError::SystemInfoCallError(e)) => Err(BridgeError::TransportError(
65
69
  format!("Failed to call GetSystemInfo: {e}"),
66
70
  ))?,
@@ -84,13 +88,27 @@ pub fn client_new(
84
88
  #[js_function]
85
89
  pub fn client_update_headers(
86
90
  client: OpaqueInboundHandle<Client>,
87
- headers: HashMap<String, String>,
91
+ headers: HashMap<String, MetadataValue>,
88
92
  ) -> BridgeResult<()> {
93
+ let (ascii_headers, bin_headers) = config::partition_headers(Some(headers));
94
+ client
95
+ .borrow()?
96
+ .core_client
97
+ .get_client()
98
+ .set_headers(ascii_headers.unwrap_or_default())
99
+ .map_err(|err| BridgeError::TypeError {
100
+ message: format!("Invalid metadata key: {err}"),
101
+ field: None,
102
+ })?;
89
103
  client
90
104
  .borrow()?
91
105
  .core_client
92
106
  .get_client()
93
- .set_headers(headers);
107
+ .set_binary_headers(bin_headers.unwrap_or_default())
108
+ .map_err(|err| BridgeError::TypeError {
109
+ message: format!("Invalid metadata key: {err}"),
110
+ field: None,
111
+ })?;
94
112
  Ok(())
95
113
  }
96
114
 
@@ -122,10 +140,16 @@ pub struct RpcCall {
122
140
  pub rpc: String,
123
141
  pub req: Vec<u8>,
124
142
  pub retry: bool,
125
- pub metadata: HashMap<String, String>,
143
+ pub metadata: HashMap<String, MetadataValue>,
126
144
  pub timeout: Option<Duration>,
127
145
  }
128
146
 
147
+ #[derive(Debug, Clone, TryFromJs)]
148
+ pub enum MetadataValue {
149
+ Ascii { value: String },
150
+ Binary { value: Vec<u8> },
151
+ }
152
+
129
153
  /// Send a request to the Workflow Service using the provided Client
130
154
  #[js_function]
131
155
  pub fn client_send_workflow_service_request(
@@ -226,6 +250,8 @@ macro_rules! rpc_call {
226
250
  }
227
251
 
228
252
  // FIXME: "this function may allocate 1400106 bytes on the stack"
253
+ #[allow(clippy::cognitive_complexity)]
254
+ #[allow(clippy::large_stack_frames)]
229
255
  #[allow(clippy::too_many_lines)]
230
256
  async fn client_invoke_workflow_service(
231
257
  mut retry_client: CoreClient,
@@ -264,6 +290,9 @@ async fn client_invoke_workflow_service(
264
290
  "DescribeDeployment" => {
265
291
  rpc_call!(retry_client, call, describe_deployment)
266
292
  }
293
+ "DescribeWorker" => {
294
+ rpc_call!(retry_client, call, describe_worker)
295
+ }
267
296
  "DeprecateNamespace" => rpc_call!(retry_client, call, deprecate_namespace),
268
297
  "DescribeNamespace" => rpc_call!(retry_client, call, describe_namespace),
269
298
  "DescribeSchedule" => rpc_call!(retry_client, call, describe_schedule),
@@ -424,6 +453,9 @@ async fn client_invoke_workflow_service(
424
453
  "SetWorkerDeploymentCurrentVersion" => {
425
454
  rpc_call!(retry_client, call, set_worker_deployment_current_version)
426
455
  }
456
+ "SetWorkerDeploymentManager" => {
457
+ rpc_call!(retry_client, call, set_worker_deployment_manager)
458
+ }
427
459
  "SetWorkerDeploymentRampingVersion" => {
428
460
  rpc_call!(retry_client, call, set_worker_deployment_ramping_version)
429
461
  }
@@ -491,6 +523,7 @@ async fn client_invoke_workflow_service(
491
523
  }
492
524
  }
493
525
 
526
+ #[allow(clippy::cognitive_complexity)]
494
527
  async fn client_invoke_operator_service(
495
528
  mut retry_client: CoreClient,
496
529
  call: RpcCall,
@@ -576,16 +609,29 @@ fn rpc_req<P: prost::Message + Default>(call: RpcCall) -> BridgeResult<tonic::Re
576
609
 
577
610
  let mut req = tonic::Request::new(proto);
578
611
  for (k, v) in call.metadata {
579
- req.metadata_mut().insert(
580
- MetadataKey::from_str(k.as_str()).map_err(|err| BridgeError::TypeError {
581
- field: None,
582
- message: format!("Invalid metadata key: {err}"),
583
- })?,
584
- v.parse().map_err(|err| BridgeError::TypeError {
585
- field: None,
586
- message: format!("Invalid metadata value: {err}"),
587
- })?,
588
- );
612
+ match v {
613
+ MetadataValue::Ascii { value: v } => {
614
+ req.metadata_mut().insert(
615
+ MetadataKey::from_str(k.as_str()).map_err(|err| BridgeError::TypeError {
616
+ field: None,
617
+ message: format!("Invalid metadata key: {err}"),
618
+ })?,
619
+ v.parse().map_err(|err| BridgeError::TypeError {
620
+ field: None,
621
+ message: format!("Invalid metadata value: {err}"),
622
+ })?,
623
+ );
624
+ }
625
+ MetadataValue::Binary { value: v } => {
626
+ req.metadata_mut().insert_bin(
627
+ MetadataKey::from_str(k.as_str()).map_err(|err| BridgeError::TypeError {
628
+ field: None,
629
+ message: format!("Invalid metadata key: {err}"),
630
+ })?,
631
+ BinaryMetadataValue::from_bytes(&v),
632
+ );
633
+ }
634
+ }
589
635
  }
590
636
 
591
637
  if let Some(timeout) = call.timeout {
@@ -601,7 +647,7 @@ where
601
647
  {
602
648
  match res {
603
649
  Ok(resp) => Ok(resp.get_ref().encode_to_vec()),
604
- Err(err) => Err(BridgeError::ServiceError(err)),
650
+ Err(err) => Err(BridgeError::from(err)),
605
651
  }
606
652
  }
607
653
 
@@ -620,7 +666,7 @@ mod config {
620
666
 
621
667
  use bridge_macros::TryFromJs;
622
668
 
623
- use crate::helpers::*;
669
+ use crate::{client::MetadataValue, helpers::*};
624
670
 
625
671
  #[derive(Debug, Clone, TryFromJs)]
626
672
  pub(super) struct ClientOptions {
@@ -629,7 +675,7 @@ mod config {
629
675
  client_version: String,
630
676
  tls: Option<TlsConfig>,
631
677
  http_connect_proxy: Option<HttpConnectProxy>,
632
- headers: Option<HashMap<String, String>>,
678
+ headers: Option<HashMap<String, MetadataValue>>,
633
679
  api_key: Option<String>,
634
680
  disable_error_code_metric_tags: bool,
635
681
  }
@@ -669,13 +715,16 @@ mod config {
669
715
  builder.tls_cfg(tls.into());
670
716
  }
671
717
 
718
+ let (ascii_headers, bin_headers) = partition_headers(self.headers);
719
+
672
720
  let client_options = builder
673
721
  .target_url(self.target_url)
674
722
  .client_name(self.client_name)
675
723
  .client_version(self.client_version)
676
724
  // tls_cfg -- above
677
725
  .http_connect_proxy(self.http_connect_proxy.map(Into::into))
678
- .headers(self.headers)
726
+ .headers(ascii_headers)
727
+ .binary_headers(bin_headers)
679
728
  .api_key(self.api_key)
680
729
  .disable_error_code_metric_tags(self.disable_error_code_metric_tags)
681
730
  // identity -- skipped: will be set on worker
@@ -711,4 +760,32 @@ mod config {
711
760
  }
712
761
  }
713
762
  }
763
+
764
+ #[allow(clippy::type_complexity)]
765
+ pub(super) fn partition_headers(
766
+ headers: Option<HashMap<String, MetadataValue>>,
767
+ ) -> (
768
+ Option<HashMap<String, String>>,
769
+ Option<HashMap<String, Vec<u8>>>,
770
+ ) {
771
+ let Some(headers) = headers else {
772
+ return (None, None);
773
+ };
774
+ let mut ascii_headers = HashMap::default();
775
+ let mut bin_headers = HashMap::default();
776
+ for (k, v) in headers {
777
+ match v {
778
+ MetadataValue::Ascii { value: v } => {
779
+ ascii_headers.insert(k, v);
780
+ }
781
+ MetadataValue::Binary { value: v } => {
782
+ bin_headers.insert(k, v);
783
+ }
784
+ }
785
+ }
786
+ (
787
+ (!ascii_headers.is_empty()).then_some(ascii_headers),
788
+ (!bin_headers.is_empty()).then_some(bin_headers),
789
+ )
790
+ }
714
791
  }
@@ -223,10 +223,10 @@ where
223
223
 
224
224
  impl<Args: TryIntoJsArgs + Send + Sync, Ret: TryFromJs + Send + Sync> CallbackInner<Args, Ret> {
225
225
  fn call<'a, C: Context<'a>>(&self, cx: &mut C, args: Args) -> BridgeResult<Ret> {
226
- let this: Handle<'a, JsValue> = self
227
- .this
228
- .as_ref()
229
- .map_or(cx.undefined().upcast(), |t| t.to_inner(cx).upcast());
226
+ let this: Handle<'a, JsValue> = match self.this.as_ref() {
227
+ Some(t) => t.to_inner(cx).upcast(),
228
+ None => cx.undefined().upcast(),
229
+ };
230
230
 
231
231
  // Convert the arguments to a JS array using the new trait
232
232
  let js_args = args.try_into_js_args(cx)?;
@@ -75,7 +75,7 @@ pub enum BridgeError {
75
75
  ///
76
76
  /// Becomes a JS `ServiceError` (adhering to the same interface as `grpc.ServiceError`).
77
77
  #[error(transparent)]
78
- ServiceError(#[from] tonic::Status),
78
+ ServiceError(Box<tonic::Status>),
79
79
 
80
80
  /// Generic wrapper for other errors.
81
81
  ///
@@ -99,6 +99,12 @@ pub enum BridgeError {
99
99
  JsThrow { thrown: RefCell<Option<ThrowBox>> },
100
100
  }
101
101
 
102
+ impl From<tonic::Status> for BridgeError {
103
+ fn from(value: tonic::Status) -> Self {
104
+ Self::ServiceError(Box::new(value))
105
+ }
106
+ }
107
+
102
108
  // Append Field Context ////////////////////////////////////////////////////////////////////////////
103
109
 
104
110
  pub trait AppendFieldContext {
@@ -9,6 +9,7 @@ use parking_lot::Mutex;
9
9
 
10
10
  use super::{BridgeError, BridgeResult, IntoThrow, TryFromJs, TryIntoJs};
11
11
 
12
+ #[allow(clippy::doc_overindented_list_items)]
12
13
  /// Opaque Handles are native structures that are sent into the JS side but without exposing
13
14
  /// their internal structure; i.e. they are only meant to be passed back to the Rust side
14
15
  /// on appropriate API calls.
@@ -11,7 +11,7 @@ use neon::{
11
11
  };
12
12
  use temporal_sdk_core::Url;
13
13
 
14
- use super::{BridgeError, BridgeResult};
14
+ use super::{AppendFieldContext, BridgeError, BridgeResult};
15
15
 
16
16
  /// Trait for Rust types that can be created from JavaScript values, possibly throwing an error.
17
17
  pub trait TryFromJs: Sized {
@@ -175,8 +175,9 @@ impl<T: TryFromJs> TryFromJs for HashMap<String, T> {
175
175
  let mut map = Self::new();
176
176
  for key_handle in props {
177
177
  let key = key_handle.to_string(cx)?.value(cx);
178
- let value = obj.get_value(cx, key_handle)?;
179
- map.insert(key, T::try_from_js(cx, value)?);
178
+ let js_value = obj.get_value(cx, key_handle)?;
179
+ let value = T::try_from_js(cx, js_value).field(&key)?;
180
+ map.insert(key, value);
180
181
  }
181
182
  Ok(map)
182
183
  }
package/src/lib.rs CHANGED
@@ -1,4 +1,4 @@
1
- #![warn(
1
+ #![deny(
2
2
  clippy::pedantic,
3
3
  clippy::nursery,
4
4
  clippy::cargo,
@@ -10,7 +10,8 @@
10
10
  clippy::too_long_first_doc_paragraph,
11
11
  clippy::option_if_let_else,
12
12
  clippy::multiple_crate_versions,
13
- clippy::significant_drop_tightening
13
+ clippy::significant_drop_tightening,
14
+ clippy::upper_case_acronyms
14
15
  )]
15
16
 
16
17
  pub mod helpers;
package/src/metrics.rs CHANGED
@@ -235,7 +235,10 @@ pub fn new_metric_gauge_f64(
235
235
  Ok(OpaqueOutboundHandle::new(GaugeF64 { meter, gauge }))
236
236
  }
237
237
 
238
+ // We do not need to worry about losing the sign of `value` as JS verifies this is positive
239
+ // It is understood that if passing in a float to a counter the value will be truncated
238
240
  #[js_function]
241
+ #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
239
242
  pub fn add_metric_counter_value(
240
243
  counter_handle: OpaqueInboundHandle<Counter>,
241
244
  value: f64,
package/src/runtime.rs CHANGED
@@ -62,8 +62,11 @@ pub fn runtime_new(
62
62
  let (telemetry_options, metrics_options, logging_options) = bridge_options.try_into()?;
63
63
 
64
64
  // Create core runtime which starts tokio multi-thread runtime
65
- let mut core_runtime = CoreRuntime::new(telemetry_options, TokioRuntimeBuilder::default())
66
- .context("Failed to initialize Core Runtime")?;
65
+ let mut core_runtime = CoreRuntime::new(
66
+ telemetry_options,
67
+ TokioRuntimeBuilder::default(),
68
+ )
69
+ .context("Failed to initialize Core Runtime")?;
67
70
 
68
71
  enter_sync!(core_runtime);
69
72
 
package/src/worker.rs CHANGED
@@ -296,7 +296,7 @@ pub fn worker_complete_nexus_task(
296
296
  .complete_nexus_task(nexus_completion)
297
297
  .await
298
298
  .map_err(|err| match err {
299
- CompleteNexusError::NexusNotEnabled {} => {
299
+ CompleteNexusError::NexusNotEnabled => {
300
300
  BridgeError::UnexpectedError(format!("{err}"))
301
301
  }
302
302
  CompleteNexusError::MalformedNexusCompletion { reason } => BridgeError::TypeError {
@@ -309,7 +309,7 @@ pub fn worker_complete_nexus_task(
309
309
 
310
310
  /// Request shutdown of the worker.
311
311
  /// Once complete Core will stop polling on new tasks and activations on worker's task queue.
312
- /// Caller should drain any pending tasks and activations and call worker_finalize_shutdown before breaking from
312
+ /// Caller should drain any pending tasks and activations and call `worker_finalize_shutdown` before breaking from
313
313
  /// the loop to ensure graceful shutdown.
314
314
  #[js_function]
315
315
  pub fn worker_initiate_shutdown(worker: OpaqueInboundHandle<Worker>) -> BridgeResult<()> {
@@ -672,10 +672,8 @@ mod config {
672
672
  self.local_activity_task_slot_supplier
673
673
  .into_slot_supplier(&mut rbo),
674
674
  );
675
- tuner_holder.nexus_slot_options(
676
- self.nexus_task_slot_supplier
677
- .into_slot_supplier(&mut rbo)
678
- );
675
+ tuner_holder
676
+ .nexus_slot_options(self.nexus_task_slot_supplier.into_slot_supplier(&mut rbo));
679
677
  if let Some(rbo) = rbo {
680
678
  tuner_holder.resource_based_options(rbo);
681
679
  }
@@ -819,7 +817,6 @@ mod custom_slot_supplier {
819
817
  Err(err) => {
820
818
  warn!("Error reserving slot: {err:?}");
821
819
  tokio::time::sleep(std::time::Duration::from_millis(1000)).await;
822
- continue;
823
820
  }
824
821
  }
825
822
  }
@@ -943,18 +940,18 @@ mod custom_slot_supplier {
943
940
  fn from(info: &'a CoreSlotInfo<'a>) -> Self {
944
941
  match info {
945
942
  CoreSlotInfo::Workflow(info) => Self::Workflow {
946
- workflow_type: info.workflow_type.to_string(),
943
+ workflow_type: info.workflow_type.clone(),
947
944
  is_sticky: info.is_sticky,
948
945
  },
949
946
  CoreSlotInfo::Activity(info) => Self::Activity {
950
- activity_type: info.activity_type.to_string(),
947
+ activity_type: info.activity_type.clone(),
951
948
  },
952
949
  CoreSlotInfo::LocalActivity(info) => Self::LocalActivity {
953
- activity_type: info.activity_type.to_string(),
950
+ activity_type: info.activity_type.clone(),
954
951
  },
955
952
  CoreSlotInfo::Nexus(info) => Self::Nexus {
956
- service: info.service.to_string(),
957
- operation: info.operation.to_string(),
953
+ service: info.service.clone(),
954
+ operation: info.operation.clone(),
958
955
  },
959
956
  }
960
957
  }
package/ts/native.ts CHANGED
@@ -100,7 +100,7 @@ export interface OtelMetricsExporterOptions {
100
100
 
101
101
  export declare function newClient(runtime: Runtime, clientOptions: ClientOptions): Promise<Client>;
102
102
 
103
- export declare function clientUpdateHeaders(client: Client, headers: Record<string, string>): void;
103
+ export declare function clientUpdateHeaders(client: Client, headers: Record<string, MetadataValue>): void;
104
104
 
105
105
  export declare function clientUpdateApiKey(client: Client, apiKey: string): void;
106
106
 
@@ -124,7 +124,7 @@ export interface ClientOptions {
124
124
  clientVersion: string;
125
125
  tls: Option<TLSConfig>;
126
126
  httpConnectProxy: Option<HttpConnectProxy>;
127
- headers: Option<Record<string, string>>;
127
+ headers: Option<Record<string, MetadataValue>>;
128
128
  apiKey: Option<string>;
129
129
  disableErrorCodeMetricTags: boolean;
130
130
  }
@@ -157,7 +157,7 @@ export interface RpcCall {
157
157
  rpc: string;
158
158
  req: Buffer;
159
159
  retry: boolean;
160
- metadata: Record<string, string>;
160
+ metadata: Record<string, MetadataValue>;
161
161
  timeout: Option<number>;
162
162
  }
163
163
 
@@ -191,6 +191,16 @@ export interface Worker {
191
191
  type: 'worker';
192
192
  }
193
193
 
194
+ export type MetadataValue =
195
+ | {
196
+ type: 'ascii';
197
+ value: string;
198
+ }
199
+ | {
200
+ type: 'binary';
201
+ value: Buffer;
202
+ };
203
+
194
204
  export interface WorkerOptions {
195
205
  identity: string;
196
206
  buildId: string;