@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.
- package/Cargo.lock +269 -236
- package/lib/native.d.ts +8 -1
- package/package.json +3 -3
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.cargo/config.toml +1 -1
- package/sdk-core/client/src/callback_based.rs +123 -0
- package/sdk-core/client/src/lib.rs +96 -28
- package/sdk-core/client/src/metrics.rs +33 -5
- package/sdk-core/client/src/raw.rs +40 -1
- package/sdk-core/client/src/retry.rs +12 -3
- package/sdk-core/core/src/lib.rs +4 -2
- package/sdk-core/core/src/pollers/poll_buffer.rs +62 -14
- package/sdk-core/core/src/worker/client.rs +9 -5
- package/sdk-core/core/src/worker/heartbeat.rs +3 -1
- package/sdk-core/core-api/src/worker.rs +2 -2
- package/sdk-core/core-c-bridge/Cargo.toml +2 -0
- package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +105 -0
- package/sdk-core/core-c-bridge/src/client.rs +265 -8
- package/sdk-core/core-c-bridge/src/tests/context.rs +11 -0
- package/sdk-core/core-c-bridge/src/tests/mod.rs +179 -3
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/CODEOWNERS +1 -1
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/README.md +1 -1
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -1
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.yaml +1 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +83 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +37 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/connectivityrule/v1/message.proto +64 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +3 -1
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +10 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +1 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +644 -9
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +635 -21
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +60 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +84 -15
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +11 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +5 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/worker_config.proto +36 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +29 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/worker/v1/message.proto +11 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +122 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +41 -0
- package/sdk-core/sdk-core-protos/src/lib.rs +5 -1
- package/sdk-core/test-utils/Cargo.toml +1 -0
- package/sdk-core/test-utils/src/lib.rs +90 -3
- package/sdk-core/tests/cloud_tests.rs +11 -74
- package/sdk-core/tests/integ_tests/client_tests.rs +14 -10
- package/sdk-core/tests/integ_tests/worker_tests.rs +8 -2
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +13 -0
- package/sdk-core/tests/integ_tests/workflow_tests/priority.rs +2 -108
- package/sdk-core/tests/main.rs +3 -0
- package/sdk-core/tests/shared_tests/mod.rs +43 -0
- package/sdk-core/tests/shared_tests/priority.rs +155 -0
- package/src/client.rs +151 -8
- package/src/worker.rs +72 -5
- 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(
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
414
|
-
SlotKind, WorkerConfig, WorkerConfigBuilder,
|
|
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
|
|
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 =
|