@temporalio/core-bridge 1.7.4 → 1.8.1
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 +245 -247
- package/Cargo.toml +1 -1
- package/lib/errors.d.ts +9 -0
- package/lib/errors.js +13 -0
- package/lib/errors.js.map +1 -1
- package/lib/index.d.ts +19 -3
- package/lib/index.js.map +1 -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/.github/workflows/heavy.yml +1 -1
- package/sdk-core/.github/workflows/semgrep.yml +25 -0
- package/sdk-core/README.md +2 -0
- package/sdk-core/cargo-tokio-console.sh +5 -0
- package/sdk-core/client/src/lib.rs +6 -41
- package/sdk-core/client/src/raw.rs +9 -0
- package/sdk-core/client/src/retry.rs +0 -16
- package/sdk-core/core/Cargo.toml +9 -5
- package/sdk-core/core/src/abstractions.rs +7 -75
- package/sdk-core/core/src/core_tests/activity_tasks.rs +16 -8
- package/sdk-core/core/src/core_tests/local_activities.rs +97 -5
- package/sdk-core/core/src/core_tests/mod.rs +1 -1
- package/sdk-core/core/src/core_tests/workers.rs +16 -16
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +247 -28
- package/sdk-core/core/src/lib.rs +2 -3
- package/sdk-core/core/src/pollers/mod.rs +30 -3
- package/sdk-core/core/src/pollers/poll_buffer.rs +166 -77
- package/sdk-core/core/src/protosext/mod.rs +4 -8
- package/sdk-core/core/src/replay/mod.rs +1 -1
- package/sdk-core/core/src/telemetry/metrics.rs +9 -0
- package/sdk-core/core/src/telemetry/mod.rs +3 -0
- package/sdk-core/core/src/test_help/mod.rs +9 -16
- package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +6 -31
- package/sdk-core/core/src/worker/activities/local_activities.rs +214 -110
- package/sdk-core/core/src/worker/activities.rs +72 -47
- package/sdk-core/core/src/worker/client/mocks.rs +1 -1
- package/sdk-core/core/src/worker/client.rs +45 -32
- package/sdk-core/core/src/worker/mod.rs +170 -122
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +0 -4
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +9 -2
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +9 -2
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +6 -3
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +74 -22
- package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +3 -2
- package/sdk-core/core/src/worker/workflow/managed_run.rs +16 -3
- package/sdk-core/core/src/worker/workflow/mod.rs +13 -22
- package/sdk-core/core/src/worker/workflow/run_cache.rs +5 -0
- package/sdk-core/core/src/worker/workflow/wft_extraction.rs +4 -7
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +38 -8
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +1 -0
- package/sdk-core/core-api/src/worker.rs +43 -2
- package/sdk-core/protos/api_upstream/Makefile +1 -1
- package/sdk-core/protos/api_upstream/buf.yaml +1 -6
- package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +12 -0
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +11 -0
- package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +9 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +19 -0
- package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +5 -0
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +36 -4
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +24 -7
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +4 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +76 -44
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +23 -1
- package/sdk-core/protos/google/rpc/status.proto +52 -0
- package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +16 -0
- package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +4 -0
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +6 -0
- package/sdk-core/sdk/src/lib.rs +31 -10
- package/sdk-core/sdk/src/workflow_future.rs +7 -5
- package/sdk-core/sdk-core-protos/src/history_builder.rs +2 -0
- package/sdk-core/sdk-core-protos/src/history_info.rs +1 -0
- package/sdk-core/sdk-core-protos/src/lib.rs +82 -73
- package/sdk-core/test-utils/Cargo.toml +1 -1
- package/sdk-core/test-utils/src/lib.rs +50 -37
- package/sdk-core/tests/integ_tests/metrics_tests.rs +143 -10
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +26 -15
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +2 -2
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +5 -1
- package/sdk-core/tests/integ_tests/workflow_tests.rs +1 -0
- package/src/conversions.rs +9 -2
- package/src/runtime.rs +5 -7
- package/ts/errors.ts +15 -0
- package/ts/index.ts +22 -4
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
use assert_matches::assert_matches;
|
|
1
2
|
use std::{sync::Arc, time::Duration};
|
|
2
3
|
use temporal_client::{WorkflowClientTrait, WorkflowOptions, WorkflowService};
|
|
3
4
|
use temporal_sdk_core::{init_worker, CoreRuntime};
|
|
@@ -5,14 +6,24 @@ use temporal_sdk_core_api::{telemetry::MetricsExporter, worker::WorkerConfigBuil
|
|
|
5
6
|
use temporal_sdk_core_protos::{
|
|
6
7
|
coresdk::{
|
|
7
8
|
activity_result::ActivityExecutionResult,
|
|
8
|
-
|
|
9
|
+
workflow_activation::{workflow_activation_job, WorkflowActivationJob},
|
|
10
|
+
workflow_commands::{
|
|
11
|
+
workflow_command, CancelWorkflowExecution, CompleteWorkflowExecution,
|
|
12
|
+
ContinueAsNewWorkflowExecution, FailWorkflowExecution, QueryResult, QuerySuccess,
|
|
13
|
+
ScheduleActivity, ScheduleLocalActivity,
|
|
14
|
+
},
|
|
9
15
|
workflow_completion::WorkflowActivationCompletion,
|
|
10
16
|
ActivityTaskCompletion,
|
|
11
17
|
},
|
|
12
|
-
temporal::api::{
|
|
18
|
+
temporal::api::{
|
|
19
|
+
enums::v1::WorkflowIdReusePolicy, failure::v1::Failure, query::v1::WorkflowQuery,
|
|
20
|
+
workflowservice::v1::ListNamespacesRequest,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
use temporal_sdk_core_test_utils::{
|
|
24
|
+
get_integ_server_options, get_integ_telem_options, CoreWfStarter, NAMESPACE,
|
|
13
25
|
};
|
|
14
|
-
use
|
|
15
|
-
use tokio::sync::Barrier;
|
|
26
|
+
use tokio::{join, sync::Barrier};
|
|
16
27
|
|
|
17
28
|
static ANY_PORT: &str = "127.0.0.1:0";
|
|
18
29
|
|
|
@@ -59,10 +70,12 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
59
70
|
.namespace(NAMESPACE)
|
|
60
71
|
.task_queue(tq)
|
|
61
72
|
.worker_build_id("test_build_id")
|
|
62
|
-
.max_cached_workflows(
|
|
73
|
+
.max_cached_workflows(2_usize)
|
|
63
74
|
.max_outstanding_activities(1_usize)
|
|
64
75
|
.max_outstanding_local_activities(1_usize)
|
|
65
|
-
|
|
76
|
+
// Need to use two for WFTs because there are a minimum of 2 pollers b/c of sticky polling
|
|
77
|
+
.max_outstanding_workflow_tasks(2_usize)
|
|
78
|
+
.max_concurrent_wft_polls(1_usize)
|
|
66
79
|
.build()
|
|
67
80
|
.unwrap();
|
|
68
81
|
|
|
@@ -146,7 +159,7 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
146
159
|
assert!(body.contains(&format!(
|
|
147
160
|
"temporal_worker_task_slots_available{{namespace=\"{NAMESPACE}\",\
|
|
148
161
|
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
149
|
-
worker_type=\"WorkflowWorker\"}}
|
|
162
|
+
worker_type=\"WorkflowWorker\"}} 2"
|
|
150
163
|
)));
|
|
151
164
|
|
|
152
165
|
// Start a workflow so that a task will get delivered
|
|
@@ -174,7 +187,7 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
174
187
|
assert!(body.contains(&format!(
|
|
175
188
|
"temporal_worker_task_slots_available{{namespace=\"{NAMESPACE}\",\
|
|
176
189
|
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
177
|
-
worker_type=\"WorkflowWorker\"}}
|
|
190
|
+
worker_type=\"WorkflowWorker\"}} 1"
|
|
178
191
|
)));
|
|
179
192
|
assert!(body.contains(&format!(
|
|
180
193
|
"temporal_worker_task_slots_available{{namespace=\"{NAMESPACE}\",\
|
|
@@ -197,7 +210,7 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
197
210
|
assert!(body.contains(&format!(
|
|
198
211
|
"temporal_worker_task_slots_available{{namespace=\"{NAMESPACE}\",\
|
|
199
212
|
service_name=\"temporal-core-sdk\",task_queue=\"one_slot_worker_tq\",\
|
|
200
|
-
worker_type=\"WorkflowWorker\"}}
|
|
213
|
+
worker_type=\"WorkflowWorker\"}} 2"
|
|
201
214
|
)));
|
|
202
215
|
assert!(body.contains(&format!(
|
|
203
216
|
"temporal_worker_task_slots_available{{namespace=\"{NAMESPACE}\",\
|
|
@@ -235,5 +248,125 @@ async fn one_slot_worker_reports_available_slot() {
|
|
|
235
248
|
worker_type=\"LocalActivityWorker\"}} 1"
|
|
236
249
|
)));
|
|
237
250
|
};
|
|
238
|
-
|
|
251
|
+
join!(wf_polling, act_polling, testing);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
#[rstest::rstest]
|
|
255
|
+
#[tokio::test]
|
|
256
|
+
async fn query_of_closed_workflow_doesnt_tick_terminal_metric(
|
|
257
|
+
#[values(
|
|
258
|
+
CompleteWorkflowExecution { result: None }.into(),
|
|
259
|
+
FailWorkflowExecution {
|
|
260
|
+
failure: Some(Failure::application_failure("I'm ded".to_string(), false)),
|
|
261
|
+
}.into(),
|
|
262
|
+
ContinueAsNewWorkflowExecution::default().into(),
|
|
263
|
+
CancelWorkflowExecution { }.into()
|
|
264
|
+
)]
|
|
265
|
+
completion: workflow_command::Variant,
|
|
266
|
+
) {
|
|
267
|
+
let mut telemopts = get_integ_telem_options();
|
|
268
|
+
telemopts.metrics = Some(MetricsExporter::Prometheus(ANY_PORT.parse().unwrap()));
|
|
269
|
+
let rt = CoreRuntime::new_assume_tokio(telemopts).unwrap();
|
|
270
|
+
let addr = rt.telemetry().prom_port().unwrap();
|
|
271
|
+
let mut starter =
|
|
272
|
+
CoreWfStarter::new_with_runtime("query_of_closed_workflow_doesnt_tick_terminal_metric", rt);
|
|
273
|
+
// Disable cache to ensure replay happens completely
|
|
274
|
+
starter.max_cached_workflows(0);
|
|
275
|
+
let worker = starter.get_worker().await;
|
|
276
|
+
let run_id = starter.start_wf().await;
|
|
277
|
+
let task = worker.poll_workflow_activation().await.unwrap();
|
|
278
|
+
// Immediately complete the workflow
|
|
279
|
+
worker
|
|
280
|
+
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
281
|
+
task.run_id,
|
|
282
|
+
completion.clone(),
|
|
283
|
+
))
|
|
284
|
+
.await
|
|
285
|
+
.unwrap();
|
|
286
|
+
|
|
287
|
+
let metric_name = match &completion {
|
|
288
|
+
workflow_command::Variant::CompleteWorkflowExecution(_) => "temporal_workflow_completed",
|
|
289
|
+
workflow_command::Variant::FailWorkflowExecution(_) => "temporal_workflow_failed",
|
|
290
|
+
workflow_command::Variant::ContinueAsNewWorkflowExecution(_) => {
|
|
291
|
+
"temporal_workflow_continue_as_new"
|
|
292
|
+
}
|
|
293
|
+
workflow_command::Variant::CancelWorkflowExecution(_) => "temporal_workflow_canceled",
|
|
294
|
+
_ => unreachable!(),
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// Verify there is one tick for the completion metric
|
|
298
|
+
let body = get_text(format!("http://{addr}/metrics")).await;
|
|
299
|
+
let matching_line = body
|
|
300
|
+
.lines()
|
|
301
|
+
.find(|l| l.starts_with(metric_name))
|
|
302
|
+
.expect("Must find matching metric");
|
|
303
|
+
assert!(matching_line.ends_with('1'));
|
|
304
|
+
|
|
305
|
+
// Handle cache eviction
|
|
306
|
+
let task = worker.poll_workflow_activation().await.unwrap();
|
|
307
|
+
worker
|
|
308
|
+
.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
|
|
309
|
+
.await
|
|
310
|
+
.unwrap();
|
|
311
|
+
|
|
312
|
+
// Query the now-closed workflow
|
|
313
|
+
let client = starter.get_client().await;
|
|
314
|
+
let queryer = async {
|
|
315
|
+
client
|
|
316
|
+
.query_workflow_execution(
|
|
317
|
+
starter.get_wf_id().to_string(),
|
|
318
|
+
run_id,
|
|
319
|
+
WorkflowQuery {
|
|
320
|
+
query_type: "fake_query".to_string(),
|
|
321
|
+
query_args: None,
|
|
322
|
+
header: None,
|
|
323
|
+
},
|
|
324
|
+
)
|
|
325
|
+
.await
|
|
326
|
+
.unwrap();
|
|
327
|
+
};
|
|
328
|
+
let query_reply = async {
|
|
329
|
+
// Need to re-complete b/c replay
|
|
330
|
+
let task = worker.poll_workflow_activation().await.unwrap();
|
|
331
|
+
worker
|
|
332
|
+
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
333
|
+
task.run_id,
|
|
334
|
+
completion,
|
|
335
|
+
))
|
|
336
|
+
.await
|
|
337
|
+
.unwrap();
|
|
338
|
+
|
|
339
|
+
let task = worker.poll_workflow_activation().await.unwrap();
|
|
340
|
+
let query = assert_matches!(
|
|
341
|
+
task.jobs.as_slice(),
|
|
342
|
+
[WorkflowActivationJob {
|
|
343
|
+
variant: Some(workflow_activation_job::Variant::QueryWorkflow(q)),
|
|
344
|
+
}] => q
|
|
345
|
+
);
|
|
346
|
+
worker
|
|
347
|
+
.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
348
|
+
task.run_id,
|
|
349
|
+
QueryResult {
|
|
350
|
+
query_id: query.query_id.clone(),
|
|
351
|
+
variant: Some(
|
|
352
|
+
QuerySuccess {
|
|
353
|
+
response: Some("hi".into()),
|
|
354
|
+
}
|
|
355
|
+
.into(),
|
|
356
|
+
),
|
|
357
|
+
}
|
|
358
|
+
.into(),
|
|
359
|
+
))
|
|
360
|
+
.await
|
|
361
|
+
.unwrap()
|
|
362
|
+
};
|
|
363
|
+
join!(query_reply, queryer);
|
|
364
|
+
|
|
365
|
+
// Verify there is still only one tick
|
|
366
|
+
let body = get_text(format!("http://{addr}/metrics")).await;
|
|
367
|
+
let matching_line = body
|
|
368
|
+
.lines()
|
|
369
|
+
.find(|l| l.starts_with(metric_name))
|
|
370
|
+
.expect("Must find matching metric");
|
|
371
|
+
assert!(matching_line.ends_with('1'));
|
|
239
372
|
}
|
|
@@ -17,7 +17,9 @@ use temporal_sdk_core_protos::{
|
|
|
17
17
|
workflow_activation::{
|
|
18
18
|
workflow_activation_job, FireTimer, ResolveActivity, WorkflowActivationJob,
|
|
19
19
|
},
|
|
20
|
-
workflow_commands::{
|
|
20
|
+
workflow_commands::{
|
|
21
|
+
ActivityCancellationType, RequestCancelActivity, ScheduleActivity, StartTimer,
|
|
22
|
+
},
|
|
21
23
|
workflow_completion::WorkflowActivationCompletion,
|
|
22
24
|
ActivityHeartbeat, ActivityTaskCompletion, AsJsonPayloadExt, FromJsonPayloadExt,
|
|
23
25
|
IntoCompletion,
|
|
@@ -728,17 +730,24 @@ async fn activity_cancelled_after_heartbeat_times_out() {
|
|
|
728
730
|
let activity_id = "act-1";
|
|
729
731
|
let task = core.poll_workflow_activation().await.unwrap();
|
|
730
732
|
// Complete workflow task and schedule activity
|
|
731
|
-
core.complete_workflow_activation(
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
activity_id,
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
733
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
|
|
734
|
+
task.run_id,
|
|
735
|
+
ScheduleActivity {
|
|
736
|
+
seq: 0,
|
|
737
|
+
activity_id: activity_id.to_string(),
|
|
738
|
+
activity_type: "dontcare".to_string(),
|
|
739
|
+
task_queue: task_q.clone(),
|
|
740
|
+
schedule_to_close_timeout: Some(prost_dur!(from_secs(10))),
|
|
741
|
+
heartbeat_timeout: Some(prost_dur!(from_secs(1))),
|
|
742
|
+
retry_policy: Some(RetryPolicy {
|
|
743
|
+
maximum_attempts: 2,
|
|
744
|
+
initial_interval: Some(prost_dur!(from_secs(5))),
|
|
745
|
+
..Default::default()
|
|
746
|
+
}),
|
|
747
|
+
..Default::default()
|
|
748
|
+
}
|
|
749
|
+
.into(),
|
|
750
|
+
))
|
|
742
751
|
.await
|
|
743
752
|
.unwrap();
|
|
744
753
|
// Poll activity and verify that it's been scheduled
|
|
@@ -753,8 +762,8 @@ async fn activity_cancelled_after_heartbeat_times_out() {
|
|
|
753
762
|
|
|
754
763
|
// Verify activity got cancelled
|
|
755
764
|
let cancel_task = core.poll_activity_task().await.unwrap();
|
|
756
|
-
assert_eq!(cancel_task.task_token, task.task_token.clone());
|
|
757
765
|
assert_matches!(cancel_task.variant, Some(act_task::Variant::Cancel(_)));
|
|
766
|
+
assert_eq!(cancel_task.task_token, task.task_token.clone());
|
|
758
767
|
|
|
759
768
|
// Complete activity with cancelled result
|
|
760
769
|
core.complete_activity_task(ActivityTaskCompletion {
|
|
@@ -770,7 +779,7 @@ async fn activity_cancelled_after_heartbeat_times_out() {
|
|
|
770
779
|
starter
|
|
771
780
|
.get_client()
|
|
772
781
|
.await
|
|
773
|
-
.terminate_workflow_execution(task_q
|
|
782
|
+
.terminate_workflow_execution(task_q, None)
|
|
774
783
|
.await
|
|
775
784
|
.unwrap();
|
|
776
785
|
}
|
|
@@ -905,7 +914,9 @@ async fn it_can_complete_async() {
|
|
|
905
914
|
async fn graceful_shutdown() {
|
|
906
915
|
let wf_name = "graceful_shutdown";
|
|
907
916
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
908
|
-
starter
|
|
917
|
+
starter
|
|
918
|
+
.worker_config
|
|
919
|
+
.graceful_shutdown_period(Some(Duration::from_millis(500)));
|
|
909
920
|
let mut worker = starter.worker().await;
|
|
910
921
|
let client = starter.get_client().await;
|
|
911
922
|
worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
|
|
@@ -43,8 +43,8 @@ async fn continue_as_new_multiple_concurrent() {
|
|
|
43
43
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
44
44
|
starter
|
|
45
45
|
.no_remote_activities()
|
|
46
|
-
.max_cached_workflows(
|
|
47
|
-
.max_wft(
|
|
46
|
+
.max_cached_workflows(5)
|
|
47
|
+
.max_wft(5);
|
|
48
48
|
let mut worker = starter.worker().await;
|
|
49
49
|
worker.register_wf(wf_name.to_string(), continue_as_new_wf);
|
|
50
50
|
|
|
@@ -55,7 +55,11 @@ async fn timer_workflow_timeout_on_sticky() {
|
|
|
55
55
|
async fn cache_miss_ok() {
|
|
56
56
|
let wf_name = "cache_miss_ok";
|
|
57
57
|
let mut starter = CoreWfStarter::new(wf_name);
|
|
58
|
-
starter
|
|
58
|
+
starter
|
|
59
|
+
.no_remote_activities()
|
|
60
|
+
.max_wft(2)
|
|
61
|
+
.max_cached_workflows(0);
|
|
62
|
+
starter.worker_config.max_concurrent_wft_polls(1_usize);
|
|
59
63
|
let mut worker = starter.worker().await;
|
|
60
64
|
|
|
61
65
|
let barr: &'static Barrier = Box::leak(Box::new(Barrier::new(2)));
|
|
@@ -434,6 +434,7 @@ async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
|
|
|
434
434
|
// Test needs eviction on and a short timeout
|
|
435
435
|
.max_cached_workflows(0)
|
|
436
436
|
.max_wft(1);
|
|
437
|
+
wf_starter.worker_config.max_concurrent_wft_polls(1_usize);
|
|
437
438
|
wf_starter.workflow_options.task_timeout = Some(Duration::from_secs(1));
|
|
438
439
|
let core = wf_starter.get_worker().await;
|
|
439
440
|
let client = wf_starter.get_client().await;
|
package/src/conversions.rs
CHANGED
|
@@ -294,6 +294,10 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
|
|
|
294
294
|
js_value_getter!(cx, self, "maxConcurrentLocalActivityExecutions", JsNumber) as usize;
|
|
295
295
|
let max_outstanding_workflow_tasks =
|
|
296
296
|
js_value_getter!(cx, self, "maxConcurrentWorkflowTaskExecutions", JsNumber) as usize;
|
|
297
|
+
let max_concurrent_wft_polls =
|
|
298
|
+
js_value_getter!(cx, self, "maxConcurrentWorkflowTaskPolls", JsNumber) as usize;
|
|
299
|
+
let max_concurrent_at_polls =
|
|
300
|
+
js_value_getter!(cx, self, "maxConcurrentActivityTaskPolls", JsNumber) as usize;
|
|
297
301
|
let sticky_queue_schedule_to_start_timeout = Duration::from_millis(js_value_getter!(
|
|
298
302
|
cx,
|
|
299
303
|
self,
|
|
@@ -319,10 +323,10 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
|
|
|
319
323
|
|
|
320
324
|
let max_worker_activities_per_second =
|
|
321
325
|
js_optional_getter!(cx, self, "maxActivitiesPerSecond", JsNumber)
|
|
322
|
-
.map(|num| num.value(cx)
|
|
326
|
+
.map(|num| num.value(cx));
|
|
323
327
|
let max_task_queue_activities_per_second =
|
|
324
328
|
js_optional_getter!(cx, self, "maxTaskQueueActivitiesPerSecond", JsNumber)
|
|
325
|
-
.map(|num| num.value(cx)
|
|
329
|
+
.map(|num| num.value(cx));
|
|
326
330
|
|
|
327
331
|
let graceful_shutdown_period =
|
|
328
332
|
js_optional_getter!(cx, self, "shutdownGraceTimeMs", JsNumber)
|
|
@@ -331,10 +335,13 @@ impl ObjectHandleConversionsExt for Handle<'_, JsObject> {
|
|
|
331
335
|
match WorkerConfigBuilder::default()
|
|
332
336
|
.worker_build_id(js_value_getter!(cx, self, "buildId", JsString))
|
|
333
337
|
.client_identity_override(Some(js_value_getter!(cx, self, "identity", JsString)))
|
|
338
|
+
.use_worker_versioning(js_value_getter!(cx, self, "useVersioning", JsBoolean))
|
|
334
339
|
.no_remote_activities(!enable_remote_activities)
|
|
335
340
|
.max_outstanding_workflow_tasks(max_outstanding_workflow_tasks)
|
|
336
341
|
.max_outstanding_activities(max_outstanding_activities)
|
|
337
342
|
.max_outstanding_local_activities(max_outstanding_local_activities)
|
|
343
|
+
.max_concurrent_wft_polls(max_concurrent_wft_polls)
|
|
344
|
+
.max_concurrent_at_polls(max_concurrent_at_polls)
|
|
338
345
|
.max_cached_workflows(max_cached_workflows)
|
|
339
346
|
.sticky_queue_schedule_to_start_timeout(sticky_queue_schedule_to_start_timeout)
|
|
340
347
|
.graceful_shutdown_period(graceful_shutdown_period)
|
package/src/runtime.rs
CHANGED
|
@@ -120,8 +120,9 @@ pub fn start_bridge_loop(
|
|
|
120
120
|
) {
|
|
121
121
|
let mut tokio_builder = tokio::runtime::Builder::new_multi_thread();
|
|
122
122
|
tokio_builder.enable_all().thread_name("core");
|
|
123
|
-
let core_runtime =
|
|
124
|
-
CoreRuntime::new(telemetry_options, tokio_builder).expect("Failed to create CoreRuntime")
|
|
123
|
+
let core_runtime = Arc::new(
|
|
124
|
+
CoreRuntime::new(telemetry_options, tokio_builder).expect("Failed to create CoreRuntime"),
|
|
125
|
+
);
|
|
125
126
|
|
|
126
127
|
core_runtime.tokio_handle().block_on(async {
|
|
127
128
|
loop {
|
|
@@ -144,14 +145,11 @@ pub fn start_bridge_loop(
|
|
|
144
145
|
headers,
|
|
145
146
|
callback,
|
|
146
147
|
} => {
|
|
147
|
-
|
|
148
|
-
// directly at the moment, when we repurpose the client to be used by a Worker,
|
|
149
|
-
// `init_worker` will attach the correct metrics meter for us.
|
|
148
|
+
let runtime_clone = core_runtime.clone();
|
|
150
149
|
core_runtime.tokio_handle().spawn(async move {
|
|
151
|
-
let metrics_meter = None;
|
|
152
150
|
match options
|
|
153
151
|
.connect_no_namespace(
|
|
154
|
-
|
|
152
|
+
runtime_clone.metric_meter().as_deref(),
|
|
155
153
|
headers.map(|h| Arc::new(RwLock::new(h))),
|
|
156
154
|
)
|
|
157
155
|
.await
|
package/ts/errors.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import { IllegalStateError } from '@temporalio/common';
|
|
2
2
|
|
|
3
|
+
const isShutdownError: unique symbol = Symbol.for('__temporal_isShutdownError');
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* The worker has been shut down
|
|
5
7
|
*/
|
|
6
8
|
export class ShutdownError extends Error {
|
|
7
9
|
public readonly name = 'ShutdownError';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Marker to determine whether an error is an instance of TerminatedFailure.
|
|
13
|
+
*/
|
|
14
|
+
protected readonly [isShutdownError] = true;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Instanceof check that works when multiple versions of @temporalio/core-bridge are installed.
|
|
18
|
+
*/
|
|
19
|
+
static is(error: unknown): error is ShutdownError {
|
|
20
|
+
return error instanceof ShutdownError || (error as any)?.[isShutdownError] === true;
|
|
21
|
+
}
|
|
8
22
|
}
|
|
9
23
|
|
|
10
24
|
/**
|
|
@@ -21,6 +35,7 @@ export class TransportError extends Error {
|
|
|
21
35
|
export class UnexpectedError extends Error {
|
|
22
36
|
public readonly name = 'UnexpectedError';
|
|
23
37
|
}
|
|
38
|
+
|
|
24
39
|
export { IllegalStateError };
|
|
25
40
|
|
|
26
41
|
export function convertFromNamedError(e: unknown, keepStackTrace: boolean): unknown {
|
package/ts/index.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { SpanContext } from '@opentelemetry/api';
|
|
2
|
+
import { LogLevel, Duration } from '@temporalio/common';
|
|
2
3
|
import type { TLSConfig } from '@temporalio/common/lib/internal-non-workflow';
|
|
3
4
|
|
|
4
5
|
export { TLSConfig };
|
|
5
6
|
|
|
7
|
+
/** @deprecated Import from @temporalio/common instead */
|
|
8
|
+
export { LogLevel };
|
|
9
|
+
|
|
6
10
|
type Shadow<Base, New> = Base extends object
|
|
7
11
|
? New extends object
|
|
8
12
|
? {
|
|
@@ -118,7 +122,7 @@ export interface OtelCollectorExporter {
|
|
|
118
122
|
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
119
123
|
* @defaults 1 second
|
|
120
124
|
*/
|
|
121
|
-
metricsExportInterval?:
|
|
125
|
+
metricsExportInterval?: Duration;
|
|
122
126
|
};
|
|
123
127
|
}
|
|
124
128
|
|
|
@@ -266,6 +270,13 @@ export interface WorkerOptions {
|
|
|
266
270
|
* A string that should be unique to the exact worker code/binary being executed
|
|
267
271
|
*/
|
|
268
272
|
buildId: string;
|
|
273
|
+
/**
|
|
274
|
+
* If set true, this worker opts into the worker versioning feature. This ensures it only receives
|
|
275
|
+
* workflow tasks for workflows which it claims to be compatible with.
|
|
276
|
+
*
|
|
277
|
+
* For more information, see https://docs.temporal.io/workers#worker-versioning
|
|
278
|
+
*/
|
|
279
|
+
useVersioning: boolean;
|
|
269
280
|
|
|
270
281
|
/**
|
|
271
282
|
* The task queue the worker will pull from
|
|
@@ -276,6 +287,16 @@ export interface WorkerOptions {
|
|
|
276
287
|
maxConcurrentWorkflowTaskExecutions: number;
|
|
277
288
|
maxConcurrentLocalActivityExecutions: number;
|
|
278
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Maximum number of Workflow tasks to poll concurrently.
|
|
292
|
+
*/
|
|
293
|
+
maxConcurrentWorkflowTaskPolls: number;
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Maximum number of Activity tasks to poll concurrently.
|
|
297
|
+
*/
|
|
298
|
+
maxConcurrentActivityTaskPolls: number;
|
|
299
|
+
|
|
279
300
|
/**
|
|
280
301
|
* If set to `false` this worker will only handle workflow tasks and local activities, it will not
|
|
281
302
|
* poll for activity tasks.
|
|
@@ -323,9 +344,6 @@ export interface WorkerOptions {
|
|
|
323
344
|
maxActivitiesPerSecond?: number;
|
|
324
345
|
}
|
|
325
346
|
|
|
326
|
-
/** Log level - must match rust log level names */
|
|
327
|
-
export type LogLevel = 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
|
|
328
|
-
|
|
329
347
|
export interface LogEntry {
|
|
330
348
|
/** Log message */
|
|
331
349
|
message: string;
|