@temporalio/core-bridge 1.12.2 → 1.13.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 (61) hide show
  1. package/Cargo.lock +269 -236
  2. package/lib/native.d.ts +8 -1
  3. package/package.json +3 -3
  4. package/releases/aarch64-apple-darwin/index.node +0 -0
  5. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  6. package/releases/x86_64-apple-darwin/index.node +0 -0
  7. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  8. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  9. package/sdk-core/.cargo/config.toml +1 -1
  10. package/sdk-core/client/src/callback_based.rs +123 -0
  11. package/sdk-core/client/src/lib.rs +96 -28
  12. package/sdk-core/client/src/metrics.rs +33 -5
  13. package/sdk-core/client/src/raw.rs +40 -1
  14. package/sdk-core/client/src/retry.rs +12 -3
  15. package/sdk-core/core/src/lib.rs +4 -2
  16. package/sdk-core/core/src/pollers/poll_buffer.rs +62 -14
  17. package/sdk-core/core/src/worker/client.rs +9 -5
  18. package/sdk-core/core/src/worker/heartbeat.rs +3 -1
  19. package/sdk-core/core-api/src/worker.rs +2 -2
  20. package/sdk-core/core-c-bridge/Cargo.toml +2 -0
  21. package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +105 -0
  22. package/sdk-core/core-c-bridge/src/client.rs +265 -8
  23. package/sdk-core/core-c-bridge/src/tests/context.rs +11 -0
  24. package/sdk-core/core-c-bridge/src/tests/mod.rs +179 -3
  25. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/CODEOWNERS +1 -1
  26. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/README.md +1 -1
  27. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -1
  28. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.yaml +1 -0
  29. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +83 -0
  30. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +37 -0
  31. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/connectivityrule/v1/message.proto +64 -0
  32. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +3 -1
  33. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +10 -0
  34. package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +1 -0
  35. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +644 -9
  36. package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +635 -21
  37. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +60 -2
  38. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +84 -15
  39. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -0
  40. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +11 -0
  41. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +5 -0
  42. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +1 -1
  43. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/worker_config.proto +36 -0
  44. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +29 -0
  45. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/worker/v1/message.proto +11 -1
  46. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +122 -4
  47. package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +41 -0
  48. package/sdk-core/sdk-core-protos/src/lib.rs +5 -1
  49. package/sdk-core/test-utils/Cargo.toml +1 -0
  50. package/sdk-core/test-utils/src/lib.rs +90 -3
  51. package/sdk-core/tests/cloud_tests.rs +11 -74
  52. package/sdk-core/tests/integ_tests/client_tests.rs +14 -10
  53. package/sdk-core/tests/integ_tests/worker_tests.rs +8 -2
  54. package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +13 -0
  55. package/sdk-core/tests/integ_tests/workflow_tests/priority.rs +2 -108
  56. package/sdk-core/tests/main.rs +3 -0
  57. package/sdk-core/tests/shared_tests/mod.rs +43 -0
  58. package/sdk-core/tests/shared_tests/priority.rs +155 -0
  59. package/src/client.rs +151 -8
  60. package/src/worker.rs +72 -5
  61. package/ts/native.ts +13 -1
@@ -0,0 +1,155 @@
1
+ use std::time::Duration;
2
+ use temporal_client::{
3
+ GetWorkflowResultOpts, Priority, WfClientExt, WorkflowClientTrait, WorkflowOptions,
4
+ };
5
+ use temporal_sdk::{ActContext, ActivityOptions, ChildWorkflowOptions, WfContext};
6
+ use temporal_sdk_core_protos::{
7
+ coresdk::AsJsonPayloadExt,
8
+ temporal::api::{common, history::v1::history_event::Attributes},
9
+ };
10
+ use temporal_sdk_core_test_utils::CoreWfStarter;
11
+
12
+ pub(crate) async fn priority_values_sent_to_server() {
13
+ let mut starter = if let Some(wfs) =
14
+ CoreWfStarter::new_cloud_or_local("priority_values_sent_to_server", ">=1.29.0-139.2").await
15
+ {
16
+ wfs
17
+ } else {
18
+ return;
19
+ };
20
+ starter.workflow_options.priority = Some(Priority {
21
+ priority_key: 1,
22
+ fairness_key: "fair-wf".to_string(),
23
+ fairness_weight: 4.2,
24
+ });
25
+ let mut worker = starter.worker().await;
26
+ let child_type = "child-wf";
27
+
28
+ worker.register_wf(starter.get_task_queue(), move |ctx: WfContext| async move {
29
+ let child = ctx.child_workflow(ChildWorkflowOptions {
30
+ workflow_id: format!("{}-child", ctx.task_queue()),
31
+ workflow_type: child_type.to_owned(),
32
+ options: WorkflowOptions {
33
+ priority: Some(Priority {
34
+ priority_key: 4,
35
+ fairness_key: "fair-child".to_string(),
36
+ fairness_weight: 1.23,
37
+ }),
38
+ ..Default::default()
39
+ },
40
+ ..Default::default()
41
+ });
42
+
43
+ let started = child
44
+ .start(&ctx)
45
+ .await
46
+ .into_started()
47
+ .expect("Child should start OK");
48
+ let activity = ctx.activity(ActivityOptions {
49
+ activity_type: "echo".to_owned(),
50
+ input: "hello".as_json_payload().unwrap(),
51
+ start_to_close_timeout: Some(Duration::from_secs(5)),
52
+ priority: Some(Priority {
53
+ priority_key: 5,
54
+ fairness_key: "fair-act".to_string(),
55
+ fairness_weight: 1.1,
56
+ }),
57
+ // Currently no priority info attached to eagerly run activities
58
+ do_not_eagerly_execute: true,
59
+ ..Default::default()
60
+ });
61
+ started.result().await;
62
+ activity.await.unwrap_ok_payload();
63
+ Ok(().into())
64
+ });
65
+ worker.register_wf(child_type.to_owned(), |ctx: WfContext| async move {
66
+ assert_eq!(
67
+ ctx.workflow_initial_info().priority,
68
+ Some(common::v1::Priority {
69
+ priority_key: 4,
70
+ fairness_key: "fair-child".to_string(),
71
+ fairness_weight: 1.23
72
+ })
73
+ );
74
+ Ok(().into())
75
+ });
76
+ worker.register_activity("echo", |ctx: ActContext, echo_me: String| async move {
77
+ assert_eq!(
78
+ ctx.get_info().priority,
79
+ Priority {
80
+ priority_key: 5,
81
+ fairness_key: "fair-act".to_string(),
82
+ fairness_weight: 1.1
83
+ }
84
+ );
85
+ Ok(echo_me)
86
+ });
87
+
88
+ starter
89
+ .start_with_worker(starter.get_task_queue(), &mut worker)
90
+ .await;
91
+ worker.run_until_done().await.unwrap();
92
+
93
+ let client = starter.get_client().await;
94
+ let handle = client.get_untyped_workflow_handle(starter.get_task_queue(), "");
95
+ let res = handle
96
+ .get_workflow_result(GetWorkflowResultOpts::default())
97
+ .await
98
+ .unwrap();
99
+ // Expect workflow success
100
+ res.unwrap_success();
101
+ let history = client
102
+ .get_workflow_execution_history(starter.get_task_queue().to_owned(), None, vec![])
103
+ .await
104
+ .unwrap()
105
+ .history
106
+ .unwrap();
107
+ let workflow_init_event = history
108
+ .events
109
+ .iter()
110
+ .find_map(|e| {
111
+ if let Attributes::WorkflowExecutionStartedEventAttributes(e) =
112
+ e.attributes.as_ref().unwrap()
113
+ {
114
+ Some(e)
115
+ } else {
116
+ None
117
+ }
118
+ })
119
+ .unwrap();
120
+ assert_eq!(
121
+ workflow_init_event.priority.as_ref().unwrap().priority_key,
122
+ 1
123
+ );
124
+ let child_init_event = history
125
+ .events
126
+ .iter()
127
+ .find_map(|e| {
128
+ if let Attributes::StartChildWorkflowExecutionInitiatedEventAttributes(e) =
129
+ e.attributes.as_ref().unwrap()
130
+ {
131
+ Some(e)
132
+ } else {
133
+ None
134
+ }
135
+ })
136
+ .unwrap();
137
+ assert_eq!(child_init_event.priority.as_ref().unwrap().priority_key, 4);
138
+ let activity_sched_event = history
139
+ .events
140
+ .iter()
141
+ .find_map(|e| {
142
+ if let Attributes::ActivityTaskScheduledEventAttributes(e) =
143
+ e.attributes.as_ref().unwrap()
144
+ {
145
+ Some(e)
146
+ } else {
147
+ None
148
+ }
149
+ })
150
+ .unwrap();
151
+ assert_eq!(
152
+ activity_sched_event.priority.as_ref().unwrap().priority_key,
153
+ 5
154
+ );
155
+ }
package/src/client.rs CHANGED
@@ -8,9 +8,7 @@ use tonic::metadata::MetadataKey;
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::{
12
- ClientInitError, ConfiguredClient, TemporalServiceClientWithMetrics, WorkflowService,
13
- };
11
+ use temporal_client::{ClientInitError, ConfiguredClient, TemporalServiceClientWithMetrics};
14
12
 
15
13
  use crate::runtime::Runtime;
16
14
  use crate::{helpers::*, runtime::RuntimeExt as _};
@@ -19,7 +17,22 @@ pub fn init(cx: &mut neon::prelude::ModuleContext) -> neon::prelude::NeonResult<
19
17
  cx.export_function("newClient", client_new)?;
20
18
  cx.export_function("clientUpdateHeaders", client_update_headers)?;
21
19
  cx.export_function("clientUpdateApiKey", client_update_api_key)?;
22
- cx.export_function("clientSendRequest", client_send_request)?;
20
+ cx.export_function(
21
+ "clientSendWorkflowServiceRequest",
22
+ client_send_workflow_service_request,
23
+ )?;
24
+ cx.export_function(
25
+ "clientSendOperatorServiceRequest",
26
+ client_send_operator_service_request,
27
+ )?;
28
+ cx.export_function(
29
+ "clientSendTestServiceRequest",
30
+ client_send_test_service_request,
31
+ )?;
32
+ cx.export_function(
33
+ "clientSendHealthServiceRequest",
34
+ client_send_health_service_request,
35
+ )?;
23
36
  cx.export_function("clientClose", client_close)?;
24
37
 
25
38
  Ok(())
@@ -113,9 +126,9 @@ pub struct RpcCall {
113
126
  pub timeout: Option<Duration>,
114
127
  }
115
128
 
116
- /// Send a request using the provided Client
129
+ /// Send a request to the Workflow Service using the provided Client
117
130
  #[js_function]
118
- pub fn client_send_request(
131
+ pub fn client_send_workflow_service_request(
119
132
  client: OpaqueInboundHandle<Client>,
120
133
  call: RpcCall,
121
134
  ) -> BridgeResult<BridgeFuture<Vec<u8>>> {
@@ -124,7 +137,50 @@ pub fn client_send_request(
124
137
  let core_client = client.core_client.clone();
125
138
 
126
139
  // FIXME: "large future with a size of 18560 bytes"
127
- core_runtime.future_to_promise(async move { client_invoke(core_client, call).await })
140
+ core_runtime
141
+ .future_to_promise(async move { client_invoke_workflow_service(core_client, call).await })
142
+ }
143
+
144
+ /// Send a request to the Operator Service using the provided Client
145
+ #[js_function]
146
+ pub fn client_send_operator_service_request(
147
+ client: OpaqueInboundHandle<Client>,
148
+ call: RpcCall,
149
+ ) -> BridgeResult<BridgeFuture<Vec<u8>>> {
150
+ let client = client.borrow()?;
151
+ let core_runtime = client.core_runtime.clone();
152
+ let core_client = client.core_client.clone();
153
+
154
+ core_runtime
155
+ .future_to_promise(async move { client_invoke_operator_service(core_client, call).await })
156
+ }
157
+
158
+ /// Send a request to the Test Service using the provided Client
159
+ #[js_function]
160
+ pub fn client_send_test_service_request(
161
+ client: OpaqueInboundHandle<Client>,
162
+ call: RpcCall,
163
+ ) -> BridgeResult<BridgeFuture<Vec<u8>>> {
164
+ let client = client.borrow()?;
165
+ let core_runtime = client.core_runtime.clone();
166
+ let core_client = client.core_client.clone();
167
+
168
+ core_runtime
169
+ .future_to_promise(async move { client_invoke_test_service(core_client, call).await })
170
+ }
171
+
172
+ /// Send a request to the Health Service using the provided Client
173
+ #[js_function]
174
+ pub fn client_send_health_service_request(
175
+ client: OpaqueInboundHandle<Client>,
176
+ call: RpcCall,
177
+ ) -> BridgeResult<BridgeFuture<Vec<u8>>> {
178
+ let client = client.borrow()?;
179
+ let core_runtime = client.core_runtime.clone();
180
+ let core_client = client.core_client.clone();
181
+
182
+ core_runtime
183
+ .future_to_promise(async move { client_invoke_health_service(core_client, call).await })
128
184
  }
129
185
 
130
186
  /// Indicates that a gRPC request failed
@@ -171,7 +227,12 @@ macro_rules! rpc_call {
171
227
 
172
228
  // FIXME: "this function may allocate 1400106 bytes on the stack"
173
229
  #[allow(clippy::too_many_lines)]
174
- async fn client_invoke(mut retry_client: CoreClient, call: RpcCall) -> BridgeResult<Vec<u8>> {
230
+ async fn client_invoke_workflow_service(
231
+ mut retry_client: CoreClient,
232
+ call: RpcCall,
233
+ ) -> BridgeResult<Vec<u8>> {
234
+ use temporal_client::WorkflowService;
235
+
175
236
  match call.rpc.as_str() {
176
237
  "CountWorkflowExecutions" => {
177
238
  rpc_call!(retry_client, call, count_workflow_executions)
@@ -220,6 +281,7 @@ async fn client_invoke(mut retry_client: CoreClient, call: RpcCall) -> BridgeRes
220
281
  rpc_call!(retry_client, call, describe_workflow_rule)
221
282
  }
222
283
  "ExecuteMultiOperation" => rpc_call!(retry_client, call, execute_multi_operation),
284
+ "FetchWorkerConfig" => rpc_call!(retry_client, call, fetch_worker_config),
223
285
  "GetClusterInfo" => rpc_call!(retry_client, call, get_cluster_info),
224
286
  "GetCurrentDeployment" => rpc_call!(retry_client, call, get_current_deployment),
225
287
  "GetDeploymentReachability" => {
@@ -399,6 +461,7 @@ async fn client_invoke(mut retry_client: CoreClient, call: RpcCall) -> BridgeRes
399
461
  rpc_call!(retry_client, call, update_namespace)
400
462
  }
401
463
  "UpdateSchedule" => rpc_call!(retry_client, call, update_schedule),
464
+ "UpdateWorkerConfig" => rpc_call!(retry_client, call, update_worker_config),
402
465
  "UpdateWorkerDeploymentVersionMetadata" => {
403
466
  rpc_call!(
404
467
  retry_client,
@@ -406,6 +469,9 @@ async fn client_invoke(mut retry_client: CoreClient, call: RpcCall) -> BridgeRes
406
469
  update_worker_deployment_version_metadata
407
470
  )
408
471
  }
472
+ "UpdateTaskQueueConfig" => {
473
+ rpc_call!(retry_client, call, update_task_queue_config)
474
+ }
409
475
  "UpdateWorkflowExecution" => {
410
476
  rpc_call!(retry_client, call, update_workflow_execution)
411
477
  }
@@ -425,6 +491,83 @@ async fn client_invoke(mut retry_client: CoreClient, call: RpcCall) -> BridgeRes
425
491
  }
426
492
  }
427
493
 
494
+ async fn client_invoke_operator_service(
495
+ mut retry_client: CoreClient,
496
+ call: RpcCall,
497
+ ) -> BridgeResult<Vec<u8>> {
498
+ use temporal_client::OperatorService;
499
+
500
+ match call.rpc.as_str() {
501
+ "AddOrUpdateRemoteCluster" => {
502
+ rpc_call!(retry_client, call, add_or_update_remote_cluster)
503
+ }
504
+ "AddSearchAttributes" => {
505
+ rpc_call!(retry_client, call, add_search_attributes)
506
+ }
507
+ "CreateNexusEndpoint" => rpc_call!(retry_client, call, create_nexus_endpoint),
508
+ "DeleteNamespace" => {
509
+ rpc_call!(retry_client, call, delete_namespace)
510
+ }
511
+ "DeleteNexusEndpoint" => rpc_call!(retry_client, call, delete_nexus_endpoint),
512
+ "GetNexusEndpoint" => rpc_call!(retry_client, call, get_nexus_endpoint),
513
+ "ListClusters" => rpc_call!(retry_client, call, list_clusters),
514
+ "ListNexusEndpoints" => rpc_call!(retry_client, call, list_nexus_endpoints),
515
+ "ListSearchAttributes" => {
516
+ rpc_call!(retry_client, call, list_search_attributes)
517
+ }
518
+ "RemoveRemoteCluster" => {
519
+ rpc_call!(retry_client, call, remove_remote_cluster)
520
+ }
521
+ "RemoveSearchAttributes" => {
522
+ rpc_call!(retry_client, call, remove_search_attributes)
523
+ }
524
+ "UpdateNexusEndpoint" => rpc_call!(retry_client, call, update_nexus_endpoint),
525
+ _ => Err(BridgeError::TypeError {
526
+ field: None,
527
+ message: format!("Unknown RPC call {}", call.rpc),
528
+ }),
529
+ }
530
+ }
531
+
532
+ async fn client_invoke_test_service(
533
+ mut retry_client: CoreClient,
534
+ call: RpcCall,
535
+ ) -> BridgeResult<Vec<u8>> {
536
+ use temporal_client::TestService;
537
+
538
+ match call.rpc.as_str() {
539
+ "GetCurrentTime" => rpc_call!(retry_client, call, get_current_time),
540
+ "LockTimeSkipping" => rpc_call!(retry_client, call, lock_time_skipping),
541
+ "SleepUntil" => rpc_call!(retry_client, call, sleep_until),
542
+ "Sleep" => rpc_call!(retry_client, call, sleep),
543
+ "UnlockTimeSkippingWithSleep" => {
544
+ rpc_call!(retry_client, call, unlock_time_skipping_with_sleep)
545
+ }
546
+ "UnlockTimeSkipping" => rpc_call!(retry_client, call, unlock_time_skipping),
547
+ _ => Err(BridgeError::TypeError {
548
+ field: None,
549
+ message: format!("Unknown RPC call {}", call.rpc),
550
+ }),
551
+ }
552
+ }
553
+
554
+ async fn client_invoke_health_service(
555
+ mut retry_client: CoreClient,
556
+ call: RpcCall,
557
+ ) -> BridgeResult<Vec<u8>> {
558
+ use temporal_client::HealthService;
559
+
560
+ match call.rpc.as_str() {
561
+ "Check" => rpc_call!(retry_client, call, check),
562
+ // Intentionally ignore 'watch' because it's a streaming method, which is not currently
563
+ // supported by the macro and client-side code, and not needed anyway for any SDK use case.
564
+ _ => Err(BridgeError::TypeError {
565
+ field: None,
566
+ message: format!("Unknown RPC call {}", call.rpc),
567
+ }),
568
+ }
569
+ }
570
+
428
571
  fn rpc_req<P: prost::Message + Default>(call: RpcCall) -> BridgeResult<tonic::Request<P>> {
429
572
  let proto = P::decode(&*call.req).map_err(|err| BridgeError::TypeError {
430
573
  field: None,
package/src/worker.rs CHANGED
@@ -10,12 +10,12 @@ use temporal_sdk_core::{
10
10
  CoreRuntime,
11
11
  api::{
12
12
  Worker as CoreWorkerTrait,
13
- errors::{CompleteActivityError, CompleteWfError, PollError},
13
+ errors::{CompleteActivityError, CompleteNexusError, CompleteWfError, PollError},
14
14
  },
15
15
  init_replay_worker, init_worker,
16
16
  protos::{
17
17
  coresdk::{
18
- ActivityHeartbeat, ActivityTaskCompletion,
18
+ ActivityHeartbeat, ActivityTaskCompletion, nexus::NexusTaskCompletion,
19
19
  workflow_completion::WorkflowActivationCompletion,
20
20
  },
21
21
  temporal::api::history::v1::History,
@@ -52,6 +52,9 @@ pub fn init(cx: &mut ModuleContext) -> NeonResult<()> {
52
52
  worker_record_activity_heartbeat,
53
53
  )?;
54
54
 
55
+ cx.export_function("workerPollNexusTask", worker_poll_nexus_task)?;
56
+ cx.export_function("workerCompleteNexusTask", worker_complete_nexus_task)?;
57
+
55
58
  cx.export_function("workerInitiateShutdown", worker_initiate_shutdown)?;
56
59
  cx.export_function("workerFinalizeShutdown", worker_finalize_shutdown)?;
57
60
 
@@ -247,6 +250,63 @@ pub fn worker_record_activity_heartbeat(
247
250
  Ok(())
248
251
  }
249
252
 
253
+ /// Initiate a single nexus task poll request.
254
+ /// There should be only one concurrent poll request for this type.
255
+ #[js_function]
256
+ pub fn worker_poll_nexus_task(
257
+ worker: OpaqueInboundHandle<Worker>,
258
+ ) -> BridgeResult<BridgeFuture<Vec<u8>>> {
259
+ let worker_ref = worker.borrow()?;
260
+ let worker = worker_ref.core_worker.clone();
261
+ let runtime = worker_ref.core_runtime.clone();
262
+
263
+ runtime.future_to_promise(async move {
264
+ let result = worker.poll_nexus_task().await;
265
+
266
+ match result {
267
+ Ok(task) => Ok(task.encode_to_vec()),
268
+ Err(err) => match err {
269
+ PollError::ShutDown => Err(BridgeError::WorkerShutdown)?,
270
+ PollError::TonicError(status) => {
271
+ Err(BridgeError::TransportError(status.message().to_string()))?
272
+ }
273
+ },
274
+ }
275
+ })
276
+ }
277
+
278
+ /// Submit an nexus task completion to core.
279
+ #[js_function]
280
+ pub fn worker_complete_nexus_task(
281
+ worker: OpaqueInboundHandle<Worker>,
282
+ completion: Vec<u8>,
283
+ ) -> BridgeResult<BridgeFuture<()>> {
284
+ let nexus_completion = NexusTaskCompletion::decode_length_delimited(completion.as_slice())
285
+ .map_err(|err| BridgeError::TypeError {
286
+ field: None,
287
+ message: format!("Cannot decode Completion from buffer: {err:?}"),
288
+ })?;
289
+
290
+ let worker_ref = worker.borrow()?;
291
+ let worker = worker_ref.core_worker.clone();
292
+ let runtime = worker_ref.core_runtime.clone();
293
+
294
+ runtime.future_to_promise(async move {
295
+ worker
296
+ .complete_nexus_task(nexus_completion)
297
+ .await
298
+ .map_err(|err| match err {
299
+ CompleteNexusError::NexusNotEnabled {} => {
300
+ BridgeError::UnexpectedError(format!("{err}"))
301
+ }
302
+ CompleteNexusError::MalformedNexusCompletion { reason } => BridgeError::TypeError {
303
+ field: None,
304
+ message: format!("Malformed nexus Completion: {reason:?}"),
305
+ },
306
+ })
307
+ })
308
+ }
309
+
250
310
  /// Request shutdown of the worker.
251
311
  /// Once complete Core will stop polling on new tasks and activations on worker's task queue.
252
312
  /// Caller should drain any pending tasks and activations and call worker_finalize_shutdown before breaking from
@@ -410,9 +470,9 @@ mod config {
410
470
  ResourceBasedSlotsOptions, ResourceBasedSlotsOptionsBuilder, ResourceSlotOptions,
411
471
  SlotSupplierOptions as CoreSlotSupplierOptions, TunerHolder, TunerHolderOptionsBuilder,
412
472
  api::worker::{
413
- ActivitySlotKind, LocalActivitySlotKind, PollerBehavior as CorePollerBehavior,
414
- SlotKind, WorkerConfig, WorkerConfigBuilder, WorkerConfigBuilderError,
415
- WorkerDeploymentOptions as CoreWorkerDeploymentOptions,
473
+ ActivitySlotKind, LocalActivitySlotKind, NexusSlotKind,
474
+ PollerBehavior as CorePollerBehavior, SlotKind, WorkerConfig, WorkerConfigBuilder,
475
+ WorkerConfigBuilderError, WorkerDeploymentOptions as CoreWorkerDeploymentOptions,
416
476
  WorkerDeploymentVersion as CoreWorkerDeploymentVersion, WorkflowSlotKind,
417
477
  },
418
478
  protos::temporal::api::enums::v1::VersioningBehavior as CoreVersioningBehavior,
@@ -439,6 +499,7 @@ mod config {
439
499
  non_sticky_to_sticky_poll_ratio: f32,
440
500
  workflow_task_poller_behavior: PollerBehavior,
441
501
  activity_task_poller_behavior: PollerBehavior,
502
+ nexus_task_poller_behavior: PollerBehavior,
442
503
  enable_non_local_activities: bool,
443
504
  sticky_queue_schedule_to_start_timeout: Duration,
444
505
  max_cached_workflows: usize,
@@ -505,6 +566,7 @@ mod config {
505
566
  .nonsticky_to_sticky_poll_ratio(self.non_sticky_to_sticky_poll_ratio)
506
567
  .workflow_task_poller_behavior(self.workflow_task_poller_behavior)
507
568
  .activity_task_poller_behavior(self.activity_task_poller_behavior)
569
+ .nexus_task_poller_behavior(self.nexus_task_poller_behavior)
508
570
  .no_remote_activities(!self.enable_non_local_activities)
509
571
  .sticky_queue_schedule_to_start_timeout(self.sticky_queue_schedule_to_start_timeout)
510
572
  .max_cached_workflows(self.max_cached_workflows)
@@ -590,6 +652,7 @@ mod config {
590
652
  workflow_task_slot_supplier: SlotSupplier<WorkflowSlotKind>,
591
653
  activity_task_slot_supplier: SlotSupplier<ActivitySlotKind>,
592
654
  local_activity_task_slot_supplier: SlotSupplier<LocalActivitySlotKind>,
655
+ nexus_task_slot_supplier: SlotSupplier<NexusSlotKind>,
593
656
  }
594
657
 
595
658
  impl WorkerTuner {
@@ -609,6 +672,10 @@ mod config {
609
672
  self.local_activity_task_slot_supplier
610
673
  .into_slot_supplier(&mut rbo),
611
674
  );
675
+ tuner_holder.nexus_slot_options(
676
+ self.nexus_task_slot_supplier
677
+ .into_slot_supplier(&mut rbo)
678
+ );
612
679
  if let Some(rbo) = rbo {
613
680
  tuner_holder.resource_based_options(rbo);
614
681
  }
package/ts/native.ts CHANGED
@@ -104,7 +104,13 @@ export declare function clientUpdateHeaders(client: Client, headers: Record<stri
104
104
 
105
105
  export declare function clientUpdateApiKey(client: Client, apiKey: string): void;
106
106
 
107
- export declare function clientSendRequest(client: Client, call: RpcCall): Promise<Buffer>;
107
+ export declare function clientSendWorkflowServiceRequest(client: Client, call: RpcCall): Promise<Buffer>;
108
+
109
+ export declare function clientSendOperatorServiceRequest(client: Client, call: RpcCall): Promise<Buffer>;
110
+
111
+ export declare function clientSendTestServiceRequest(client: Client, call: RpcCall): Promise<Buffer>;
112
+
113
+ export declare function clientSendHealthServiceRequest(client: Client, call: RpcCall): Promise<Buffer>;
108
114
 
109
115
  export declare function clientClose(client: Client): void;
110
116
 
@@ -173,6 +179,10 @@ export declare function workerCompleteActivityTask(worker: Worker, result: Buffe
173
179
 
174
180
  export declare function workerRecordActivityHeartbeat(worker: Worker, heartbeat: Buffer): void;
175
181
 
182
+ export declare function workerPollNexusTask(worker: Worker): Promise<Buffer>;
183
+
184
+ export declare function workerCompleteNexusTask(worker: Worker, result: Buffer): Promise<void>;
185
+
176
186
  export declare function workerInitiateShutdown(worker: Worker): void;
177
187
 
178
188
  export declare function workerFinalizeShutdown(worker: Worker): Promise<void>;
@@ -192,6 +202,7 @@ export interface WorkerOptions {
192
202
  nonStickyToStickyPollRatio: number;
193
203
  workflowTaskPollerBehavior: PollerBehavior;
194
204
  activityTaskPollerBehavior: PollerBehavior;
205
+ nexusTaskPollerBehavior: PollerBehavior;
195
206
  enableNonLocalActivities: boolean;
196
207
  stickyQueueScheduleToStartTimeout: number;
197
208
  maxCachedWorkflows: number;
@@ -235,6 +246,7 @@ export interface WorkerTunerOptions {
235
246
  workflowTaskSlotSupplier: SlotSupplierOptions;
236
247
  activityTaskSlotSupplier: SlotSupplierOptions;
237
248
  localActivityTaskSlotSupplier: SlotSupplierOptions;
249
+ nexusTaskSlotSupplier: SlotSupplierOptions;
238
250
  }
239
251
 
240
252
  export type SlotSupplierOptions =