@temporalio/core-bridge 1.5.2 → 1.7.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 +304 -112
- package/lib/index.d.ts +8 -6
- package/lib/index.js.map +1 -1
- package/package.json +9 -4
- 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/.buildkite/docker/Dockerfile +2 -2
- package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
- package/sdk-core/.buildkite/pipeline.yml +2 -4
- package/sdk-core/.cargo/config.toml +5 -2
- package/sdk-core/.github/workflows/heavy.yml +29 -0
- package/sdk-core/Cargo.toml +1 -1
- package/sdk-core/README.md +20 -10
- package/sdk-core/client/src/lib.rs +215 -39
- package/sdk-core/client/src/metrics.rs +17 -8
- package/sdk-core/client/src/raw.rs +4 -4
- package/sdk-core/client/src/retry.rs +32 -20
- package/sdk-core/core/Cargo.toml +25 -12
- package/sdk-core/core/src/abstractions/take_cell.rs +28 -0
- package/sdk-core/core/src/abstractions.rs +204 -14
- package/sdk-core/core/src/core_tests/activity_tasks.rs +143 -50
- package/sdk-core/core/src/core_tests/child_workflows.rs +6 -5
- package/sdk-core/core/src/core_tests/determinism.rs +165 -2
- package/sdk-core/core/src/core_tests/local_activities.rs +431 -43
- package/sdk-core/core/src/core_tests/queries.rs +34 -16
- package/sdk-core/core/src/core_tests/workers.rs +8 -5
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +588 -55
- package/sdk-core/core/src/ephemeral_server/mod.rs +113 -12
- package/sdk-core/core/src/internal_flags.rs +155 -0
- package/sdk-core/core/src/lib.rs +16 -9
- package/sdk-core/core/src/protosext/mod.rs +1 -1
- package/sdk-core/core/src/replay/mod.rs +16 -27
- package/sdk-core/core/src/telemetry/log_export.rs +1 -1
- package/sdk-core/core/src/telemetry/metrics.rs +69 -35
- package/sdk-core/core/src/telemetry/mod.rs +60 -21
- package/sdk-core/core/src/telemetry/prometheus_server.rs +19 -13
- package/sdk-core/core/src/test_help/mod.rs +73 -14
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +119 -160
- package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
- package/sdk-core/core/src/worker/activities/local_activities.rs +379 -129
- package/sdk-core/core/src/worker/activities.rs +350 -175
- package/sdk-core/core/src/worker/client/mocks.rs +22 -2
- package/sdk-core/core/src/worker/client.rs +18 -2
- package/sdk-core/core/src/worker/mod.rs +183 -64
- package/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
- package/sdk-core/core/src/worker/workflow/history_update.rs +916 -277
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +216 -183
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +9 -12
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +7 -9
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +160 -87
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +13 -14
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -9
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +14 -17
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +242 -110
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +27 -19
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +9 -11
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +321 -206
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +13 -18
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +20 -29
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +257 -51
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +310 -150
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +17 -20
- package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +31 -15
- package/sdk-core/core/src/worker/workflow/managed_run.rs +1052 -380
- package/sdk-core/core/src/worker/workflow/mod.rs +598 -390
- package/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
- package/sdk-core/core/src/worker/workflow/wft_extraction.rs +137 -0
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
- package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
- package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +469 -718
- package/sdk-core/core-api/Cargo.toml +2 -1
- package/sdk-core/core-api/src/errors.rs +1 -34
- package/sdk-core/core-api/src/lib.rs +19 -9
- package/sdk-core/core-api/src/telemetry.rs +4 -6
- package/sdk-core/core-api/src/worker.rs +19 -1
- package/sdk-core/etc/deps.svg +115 -140
- package/sdk-core/etc/regen-depgraph.sh +5 -0
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +86 -61
- package/sdk-core/fsm/rustfsm_trait/src/lib.rs +29 -71
- package/sdk-core/histories/ends_empty_wft_complete.bin +0 -0
- package/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
- package/sdk-core/histories/old_change_marker_format.bin +0 -0
- package/sdk-core/protos/api_upstream/.github/CODEOWNERS +2 -1
- package/sdk-core/protos/api_upstream/Makefile +6 -6
- package/sdk-core/protos/api_upstream/build/go.mod +7 -0
- package/sdk-core/protos/api_upstream/build/go.sum +5 -0
- package/sdk-core/protos/api_upstream/build/tools.go +29 -0
- package/sdk-core/protos/api_upstream/go.mod +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +9 -2
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +7 -26
- 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 +3 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +3 -7
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +8 -8
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +25 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +49 -26
- package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +5 -2
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
- package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
- package/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -28
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -4
- package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +7 -8
- package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +10 -7
- package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +19 -30
- package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
- package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
- package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +8 -0
- package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +67 -60
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +85 -84
- package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +9 -3
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
- package/sdk-core/sdk/Cargo.toml +5 -4
- package/sdk-core/sdk/src/lib.rs +108 -26
- package/sdk-core/sdk/src/workflow_context/options.rs +7 -1
- package/sdk-core/sdk/src/workflow_context.rs +24 -17
- package/sdk-core/sdk/src/workflow_future.rs +16 -15
- package/sdk-core/sdk-core-protos/Cargo.toml +5 -2
- package/sdk-core/sdk-core-protos/build.rs +36 -2
- package/sdk-core/sdk-core-protos/src/history_builder.rs +138 -106
- package/sdk-core/sdk-core-protos/src/history_info.rs +10 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +272 -87
- package/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
- package/sdk-core/test-utils/Cargo.toml +3 -1
- package/sdk-core/test-utils/src/canned_histories.rs +106 -296
- package/sdk-core/test-utils/src/histfetch.rs +1 -1
- package/sdk-core/test-utils/src/lib.rs +82 -23
- package/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
- package/sdk-core/test-utils/src/workflows.rs +29 -0
- package/sdk-core/tests/fuzzy_workflow.rs +130 -0
- package/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
- package/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
- package/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
- package/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
- package/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +161 -72
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +80 -3
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +94 -200
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +2 -4
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +34 -28
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +76 -7
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +7 -8
- package/sdk-core/tests/integ_tests/workflow_tests.rs +13 -14
- package/sdk-core/tests/main.rs +3 -13
- package/sdk-core/tests/runner.rs +75 -36
- package/sdk-core/tests/wf_input_replay.rs +32 -0
- package/src/conversions.rs +14 -8
- package/src/runtime.rs +9 -8
- package/ts/index.ts +8 -6
- package/sdk-core/bridge-ffi/Cargo.toml +0 -24
- package/sdk-core/bridge-ffi/LICENSE.txt +0 -23
- package/sdk-core/bridge-ffi/build.rs +0 -25
- package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -224
- package/sdk-core/bridge-ffi/src/lib.rs +0 -746
- package/sdk-core/bridge-ffi/src/wrappers.rs +0 -221
- package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
- package/sdk-core/sdk/src/conversions.rs +0 -8
package/sdk-core/sdk/Cargo.toml
CHANGED
|
@@ -14,21 +14,22 @@ categories = ["development-tools"]
|
|
|
14
14
|
|
|
15
15
|
[dependencies]
|
|
16
16
|
async-trait = "0.1"
|
|
17
|
+
thiserror = "1.0"
|
|
17
18
|
anyhow = "1.0"
|
|
18
|
-
base64 = "0.
|
|
19
|
+
base64 = "0.21"
|
|
19
20
|
crossbeam = "0.8"
|
|
20
21
|
derive_more = "0.99"
|
|
21
22
|
futures = "0.3"
|
|
22
23
|
once_cell = "1.10"
|
|
23
24
|
parking_lot = { version = "0.12", features = ["send_guard"] }
|
|
24
|
-
prost-types = "0.
|
|
25
|
+
prost-types = { version = "0.4", package = "prost-wkt-types" }
|
|
25
26
|
sha2 = "0.10"
|
|
26
27
|
serde = "1.0"
|
|
27
|
-
tokio = { version = "1.
|
|
28
|
+
tokio = { version = "1.26", features = ["rt", "rt-multi-thread", "parking_lot", "time", "fs"] }
|
|
28
29
|
tokio-util = { version = "0.7" }
|
|
29
30
|
tokio-stream = "0.1"
|
|
30
31
|
tonic = "0.8"
|
|
31
|
-
tracing =
|
|
32
|
+
tracing = "0.1"
|
|
32
33
|
|
|
33
34
|
[dependencies.temporal-sdk-core]
|
|
34
35
|
path = "../core"
|
package/sdk-core/sdk/src/lib.rs
CHANGED
|
@@ -46,7 +46,6 @@ extern crate tracing;
|
|
|
46
46
|
|
|
47
47
|
mod activity_context;
|
|
48
48
|
mod app_data;
|
|
49
|
-
mod conversions;
|
|
50
49
|
pub mod interceptors;
|
|
51
50
|
mod payload_converter;
|
|
52
51
|
mod workflow_context;
|
|
@@ -67,10 +66,12 @@ use anyhow::{anyhow, bail, Context};
|
|
|
67
66
|
use app_data::AppData;
|
|
68
67
|
use futures::{future::BoxFuture, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
|
|
69
68
|
use std::{
|
|
69
|
+
any::{Any, TypeId},
|
|
70
70
|
cell::RefCell,
|
|
71
71
|
collections::HashMap,
|
|
72
72
|
fmt::{Debug, Display, Formatter},
|
|
73
73
|
future::Future,
|
|
74
|
+
panic::AssertUnwindSafe,
|
|
74
75
|
sync::Arc,
|
|
75
76
|
};
|
|
76
77
|
use temporal_client::ClientOptionsBuilder;
|
|
@@ -87,7 +88,7 @@ use temporal_sdk_core_protos::{
|
|
|
87
88
|
common::NamespacedWorkflowExecution,
|
|
88
89
|
workflow_activation::{
|
|
89
90
|
resolve_child_workflow_execution_start::Status as ChildWorkflowStartStatus,
|
|
90
|
-
workflow_activation_job::Variant, WorkflowActivation,
|
|
91
|
+
workflow_activation_job::Variant, WorkflowActivation,
|
|
91
92
|
},
|
|
92
93
|
workflow_commands::{workflow_command, ContinueAsNewWorkflowExecution},
|
|
93
94
|
workflow_completion::WorkflowActivationCompletion,
|
|
@@ -307,22 +308,17 @@ impl Worker {
|
|
|
307
308
|
// makes tests which use mocks dramatically more manageable.
|
|
308
309
|
async {
|
|
309
310
|
if !act_half.activity_fns.is_empty() {
|
|
310
|
-
let shutdown_token = shutdown_token.clone();
|
|
311
311
|
loop {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
break;
|
|
316
|
-
}
|
|
317
|
-
act_half.activity_task_handler(
|
|
318
|
-
common.worker.clone(),
|
|
319
|
-
safe_app_data.clone(),
|
|
320
|
-
common.task_queue.clone(),
|
|
321
|
-
activity?
|
|
322
|
-
)?;
|
|
323
|
-
},
|
|
324
|
-
_ = shutdown_token.cancelled() => { break }
|
|
312
|
+
let activity = common.worker.poll_activity_task().await;
|
|
313
|
+
if matches!(activity, Err(PollActivityError::ShutDown)) {
|
|
314
|
+
break;
|
|
325
315
|
}
|
|
316
|
+
act_half.activity_task_handler(
|
|
317
|
+
common.worker.clone(),
|
|
318
|
+
safe_app_data.clone(),
|
|
319
|
+
common.task_queue.clone(),
|
|
320
|
+
activity?,
|
|
321
|
+
)?;
|
|
326
322
|
}
|
|
327
323
|
};
|
|
328
324
|
Result::<_, anyhow::Error>::Ok(())
|
|
@@ -336,6 +332,7 @@ impl Worker {
|
|
|
336
332
|
i.on_shutdown(self);
|
|
337
333
|
}
|
|
338
334
|
self.common.worker.shutdown().await;
|
|
335
|
+
debug!("Worker shutdown complete");
|
|
339
336
|
self.app_data = Some(
|
|
340
337
|
Arc::try_unwrap(safe_app_data)
|
|
341
338
|
.map_err(|_| anyhow!("some references of AppData exist on worker shutdown"))?,
|
|
@@ -394,10 +391,10 @@ impl WorkflowHalf {
|
|
|
394
391
|
|
|
395
392
|
// If the activation is to start a workflow, create a new workflow driver for it,
|
|
396
393
|
// using the function associated with that workflow id
|
|
397
|
-
if let Some(
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
{
|
|
394
|
+
if let Some(sw) = activation.jobs.iter().find_map(|j| match j.variant {
|
|
395
|
+
Some(Variant::StartWorkflow(ref sw)) => Some(sw),
|
|
396
|
+
_ => None,
|
|
397
|
+
}) {
|
|
401
398
|
let workflow_type = &sw.workflow_type;
|
|
402
399
|
let wf_fns_borrow = self.workflow_fns.borrow();
|
|
403
400
|
let wf_function = wf_fns_borrow
|
|
@@ -413,7 +410,7 @@ impl WorkflowHalf {
|
|
|
413
410
|
);
|
|
414
411
|
let jh = tokio::spawn(async move {
|
|
415
412
|
tokio::select! {
|
|
416
|
-
r = wff => r,
|
|
413
|
+
r = wff.fuse() => r,
|
|
417
414
|
// TODO: This probably shouldn't abort early, as it could cause an in-progress
|
|
418
415
|
// complete to abort. Send synthetic remove activation
|
|
419
416
|
_ = shutdown_token.cancelled() => {
|
|
@@ -486,15 +483,30 @@ impl ActivityHalf {
|
|
|
486
483
|
start,
|
|
487
484
|
);
|
|
488
485
|
tokio::spawn(async move {
|
|
489
|
-
let output = (act_fn.act_func)(ctx, arg)
|
|
486
|
+
let output = AssertUnwindSafe((act_fn.act_func)(ctx, arg))
|
|
487
|
+
.catch_unwind()
|
|
488
|
+
.await;
|
|
490
489
|
let result = match output {
|
|
491
|
-
|
|
492
|
-
|
|
490
|
+
Err(e) => ActivityExecutionResult::fail(Failure::application_failure(
|
|
491
|
+
format!("Activity function panicked: {}", panic_formatter(e)),
|
|
492
|
+
true,
|
|
493
|
+
)),
|
|
494
|
+
Ok(Ok(ActExitValue::Normal(p))) => ActivityExecutionResult::ok(p),
|
|
495
|
+
Ok(Ok(ActExitValue::WillCompleteAsync)) => {
|
|
493
496
|
ActivityExecutionResult::will_complete_async()
|
|
494
497
|
}
|
|
495
|
-
Err(err) => match err.downcast::<ActivityCancelledError>() {
|
|
498
|
+
Ok(Err(err)) => match err.downcast::<ActivityCancelledError>() {
|
|
496
499
|
Ok(ce) => ActivityExecutionResult::cancel_from_details(ce.details),
|
|
497
|
-
Err(other_err) =>
|
|
500
|
+
Err(other_err) => {
|
|
501
|
+
match other_err.downcast::<NonRetryableActivityError>() {
|
|
502
|
+
Ok(nre) => ActivityExecutionResult::fail(
|
|
503
|
+
Failure::application_failure_from_error(nre.into(), true),
|
|
504
|
+
),
|
|
505
|
+
Err(other_err) => ActivityExecutionResult::fail(
|
|
506
|
+
Failure::application_failure_from_error(other_err, false),
|
|
507
|
+
),
|
|
508
|
+
}
|
|
509
|
+
}
|
|
498
510
|
},
|
|
499
511
|
};
|
|
500
512
|
worker
|
|
@@ -537,11 +549,13 @@ pub enum TimerResult {
|
|
|
537
549
|
}
|
|
538
550
|
|
|
539
551
|
/// Successful result of sending a signal to an external workflow
|
|
552
|
+
#[derive(Debug)]
|
|
540
553
|
pub struct SignalExternalOk;
|
|
541
554
|
/// Result of awaiting on sending a signal to an external workflow
|
|
542
555
|
pub type SignalExternalWfResult = Result<SignalExternalOk, Failure>;
|
|
543
556
|
|
|
544
557
|
/// Successful result of sending a cancel request to an external workflow
|
|
558
|
+
#[derive(Debug)]
|
|
545
559
|
pub struct CancelExternalOk;
|
|
546
560
|
/// Result of awaiting on sending a cancel request to an external workflow
|
|
547
561
|
pub type CancelExternalWfResult = Result<CancelExternalOk, Failure>;
|
|
@@ -644,6 +658,20 @@ pub enum CancellableID {
|
|
|
644
658
|
},
|
|
645
659
|
}
|
|
646
660
|
|
|
661
|
+
impl CancellableID {
|
|
662
|
+
/// Returns the type-specific sequence number used for this command
|
|
663
|
+
pub fn seq_num(&self) -> u32 {
|
|
664
|
+
match self {
|
|
665
|
+
CancellableID::Timer(seq) => *seq,
|
|
666
|
+
CancellableID::Activity(seq) => *seq,
|
|
667
|
+
CancellableID::LocalActivity(seq) => *seq,
|
|
668
|
+
CancellableID::ChildWorkflow(seq) => *seq,
|
|
669
|
+
CancellableID::SignalExternalWorkflow(seq) => *seq,
|
|
670
|
+
CancellableID::ExternalWorkflow { seqnum, .. } => *seqnum,
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
647
675
|
#[derive(derive_more::From)]
|
|
648
676
|
#[allow(clippy::large_enum_variant)]
|
|
649
677
|
enum RustWfCmd {
|
|
@@ -749,6 +777,14 @@ pub struct ActivityFunction {
|
|
|
749
777
|
pub struct ActivityCancelledError {
|
|
750
778
|
details: Option<Payload>,
|
|
751
779
|
}
|
|
780
|
+
impl ActivityCancelledError {
|
|
781
|
+
/// Include some details as part of concluding the activity as cancelled
|
|
782
|
+
pub fn with_details(payload: Payload) -> Self {
|
|
783
|
+
Self {
|
|
784
|
+
details: Some(payload),
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
752
788
|
impl std::error::Error for ActivityCancelledError {}
|
|
753
789
|
impl Display for ActivityCancelledError {
|
|
754
790
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
@@ -756,6 +792,16 @@ impl Display for ActivityCancelledError {
|
|
|
756
792
|
}
|
|
757
793
|
}
|
|
758
794
|
|
|
795
|
+
/// Return this error to indicate that your activity non-retryable
|
|
796
|
+
/// this is a transparent wrapper around anyhow Error so essentially any type of error
|
|
797
|
+
/// could be used here.
|
|
798
|
+
///
|
|
799
|
+
/// In your activity function. Return something along the lines of:
|
|
800
|
+
/// `Err(NonRetryableActivityError(anyhow::anyhow!("This should *not* be retried")).into())`
|
|
801
|
+
#[derive(Debug, thiserror::Error)]
|
|
802
|
+
#[error(transparent)]
|
|
803
|
+
pub struct NonRetryableActivityError(pub anyhow::Error);
|
|
804
|
+
|
|
759
805
|
/// Closures / functions which can be turned into activity functions implement this trait
|
|
760
806
|
pub trait IntoActivityFunc<Args, Res, Out> {
|
|
761
807
|
/// Consume the closure or fn pointer and turned it into a boxed activity function
|
|
@@ -793,3 +839,39 @@ where
|
|
|
793
839
|
Arc::new(wrapper)
|
|
794
840
|
}
|
|
795
841
|
}
|
|
842
|
+
|
|
843
|
+
/// Attempts to turn caught panics into something printable
|
|
844
|
+
fn panic_formatter(panic: Box<dyn Any>) -> Box<dyn Display> {
|
|
845
|
+
_panic_formatter::<&str>(panic)
|
|
846
|
+
}
|
|
847
|
+
fn _panic_formatter<T: 'static + PrintablePanicType>(panic: Box<dyn Any>) -> Box<dyn Display> {
|
|
848
|
+
match panic.downcast::<T>() {
|
|
849
|
+
Ok(d) => d,
|
|
850
|
+
Err(orig) => {
|
|
851
|
+
if TypeId::of::<<T as PrintablePanicType>::NextType>()
|
|
852
|
+
== TypeId::of::<EndPrintingAttempts>()
|
|
853
|
+
{
|
|
854
|
+
return Box::new("Couldn't turn panic into a string");
|
|
855
|
+
}
|
|
856
|
+
_panic_formatter::<T::NextType>(orig)
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
trait PrintablePanicType: Display {
|
|
861
|
+
type NextType: PrintablePanicType;
|
|
862
|
+
}
|
|
863
|
+
impl PrintablePanicType for &str {
|
|
864
|
+
type NextType = String;
|
|
865
|
+
}
|
|
866
|
+
impl PrintablePanicType for String {
|
|
867
|
+
type NextType = EndPrintingAttempts;
|
|
868
|
+
}
|
|
869
|
+
struct EndPrintingAttempts {}
|
|
870
|
+
impl Display for EndPrintingAttempts {
|
|
871
|
+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
872
|
+
write!(f, "Will never be printed")
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
impl PrintablePanicType for EndPrintingAttempts {
|
|
876
|
+
type NextType = EndPrintingAttempts;
|
|
877
|
+
}
|
|
@@ -9,7 +9,10 @@ use temporal_sdk_core_protos::{
|
|
|
9
9
|
StartChildWorkflowExecution,
|
|
10
10
|
},
|
|
11
11
|
},
|
|
12
|
-
temporal::api::
|
|
12
|
+
temporal::api::{
|
|
13
|
+
common::v1::{Payload, RetryPolicy},
|
|
14
|
+
enums::v1::ParentClosePolicy,
|
|
15
|
+
},
|
|
13
16
|
};
|
|
14
17
|
|
|
15
18
|
// TODO: Before release, probably best to avoid using proto types entirely here. They're awkward.
|
|
@@ -180,6 +183,8 @@ pub struct ChildWorkflowOptions {
|
|
|
180
183
|
pub cancel_type: ChildWorkflowCancellationType,
|
|
181
184
|
/// Common options
|
|
182
185
|
pub options: WorkflowOptions,
|
|
186
|
+
/// How to respond to parent workflow ending
|
|
187
|
+
pub parent_close_policy: ParentClosePolicy,
|
|
183
188
|
}
|
|
184
189
|
|
|
185
190
|
impl IntoWorkflowCommand for ChildWorkflowOptions {
|
|
@@ -203,6 +208,7 @@ impl IntoWorkflowCommand for ChildWorkflowOptions {
|
|
|
203
208
|
workflow_task_timeout: self.options.task_timeout.and_then(|d| d.try_into().ok()),
|
|
204
209
|
search_attributes: self.options.search_attributes.unwrap_or_default(),
|
|
205
210
|
cron_schedule: self.options.cron_schedule.unwrap_or_default(),
|
|
211
|
+
parent_close_policy: self.parent_close_policy as i32,
|
|
206
212
|
..Default::default()
|
|
207
213
|
}
|
|
208
214
|
}
|
|
@@ -34,7 +34,8 @@ use temporal_sdk_core_protos::{
|
|
|
34
34
|
workflow_commands::{
|
|
35
35
|
request_cancel_external_workflow_execution as cancel_we,
|
|
36
36
|
signal_external_workflow_execution as sig_we, workflow_command,
|
|
37
|
-
|
|
37
|
+
CancelChildWorkflowExecution, ModifyWorkflowProperties,
|
|
38
|
+
RequestCancelExternalWorkflowExecution, SetPatchMarker,
|
|
38
39
|
SignalExternalWorkflowExecution, StartTimer, UpsertWorkflowSearchAttributes,
|
|
39
40
|
},
|
|
40
41
|
},
|
|
@@ -98,6 +99,7 @@ pub struct WfContextSharedData {
|
|
|
98
99
|
pub changes: HashMap<String, bool>,
|
|
99
100
|
pub is_replaying: bool,
|
|
100
101
|
pub wf_time: Option<SystemTime>,
|
|
102
|
+
pub history_length: u32,
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
// TODO: Dataconverter type interface to replace Payloads here. Possibly just use serde
|
|
@@ -148,6 +150,11 @@ impl WfContext {
|
|
|
148
150
|
self.shared.read().wf_time
|
|
149
151
|
}
|
|
150
152
|
|
|
153
|
+
/// Return the length of history so far at this point in the workflow
|
|
154
|
+
pub fn history_length(&self) -> u32 {
|
|
155
|
+
self.shared.read().history_length
|
|
156
|
+
}
|
|
157
|
+
|
|
151
158
|
pub(crate) fn get_shared_data(&self) -> Arc<RwLock<WfContextSharedData>> {
|
|
152
159
|
self.shared.clone()
|
|
153
160
|
}
|
|
@@ -550,16 +557,16 @@ impl<'a> Future for LATimerBackoffFut<'a> {
|
|
|
550
557
|
}
|
|
551
558
|
let poll_res = self.current_fut.poll_unpin(cx);
|
|
552
559
|
if let Poll::Ready(ref r) = poll_res {
|
|
553
|
-
// If we've already said we want to cancel, don't schedule the backoff timer. Just
|
|
554
|
-
// return cancel status. This can happen if cancel comes after the LA says it wants to
|
|
555
|
-
// back off but before we have scheduled the timer.
|
|
556
|
-
if self.did_cancel.load(Ordering::Acquire) {
|
|
557
|
-
return Poll::Ready(ActivityResolution {
|
|
558
|
-
status: Some(activity_resolution::Status::Cancelled(Default::default())),
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
|
|
562
560
|
if let Some(activity_resolution::Status::Backoff(b)) = r.status.as_ref() {
|
|
561
|
+
// If we've already said we want to cancel, don't schedule the backoff timer. Just
|
|
562
|
+
// return cancel status. This can happen if cancel comes after the LA says it wants
|
|
563
|
+
// to back off but before we have scheduled the timer.
|
|
564
|
+
if self.did_cancel.load(Ordering::Acquire) {
|
|
565
|
+
return Poll::Ready(ActivityResolution {
|
|
566
|
+
status: Some(activity_resolution::Status::Cancelled(Default::default())),
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
|
|
563
570
|
let timer_f = self.ctx.timer(
|
|
564
571
|
b.backoff_duration
|
|
565
572
|
.clone()
|
|
@@ -673,13 +680,13 @@ impl StartedChildWorkflow {
|
|
|
673
680
|
}
|
|
674
681
|
|
|
675
682
|
/// Cancel the child workflow
|
|
676
|
-
pub fn cancel(&self, cx: &WfContext)
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
+
pub fn cancel(&self, cx: &WfContext) {
|
|
684
|
+
cx.send(RustWfCmd::NewNonblockingCmd(
|
|
685
|
+
CancelChildWorkflowExecution {
|
|
686
|
+
child_workflow_seq: self.common.result_future.cancellable_id.seq_num(),
|
|
687
|
+
}
|
|
688
|
+
.into(),
|
|
689
|
+
));
|
|
683
690
|
}
|
|
684
691
|
|
|
685
692
|
/// Signal the child workflow
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
use crate::{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
WorkflowResult,
|
|
2
|
+
panic_formatter, workflow_context::WfContextSharedData, CancellableID, RustWfCmd, SignalData,
|
|
3
|
+
TimerResult, UnblockEvent, WfContext, WfExitValue, WorkflowFunction, WorkflowResult,
|
|
5
4
|
};
|
|
6
5
|
use anyhow::{anyhow, bail, Context as AnyhowContext, Error};
|
|
7
6
|
use crossbeam::channel::Receiver;
|
|
@@ -63,7 +62,9 @@ impl WorkflowFunction {
|
|
|
63
62
|
// We need to mark the workflow future as unconstrained, otherwise Tokio will impose
|
|
64
63
|
// an artificial limit on how many commands we can unblock in one poll round.
|
|
65
64
|
// TODO: Now we *need* deadlock detection or we could hose the whole system
|
|
66
|
-
inner: tokio::task::unconstrained((self.wf_func)(wf_context))
|
|
65
|
+
inner: tokio::task::unconstrained((self.wf_func)(wf_context))
|
|
66
|
+
.fuse()
|
|
67
|
+
.boxed(),
|
|
67
68
|
incoming_commands: cmd_receiver,
|
|
68
69
|
outgoing_completions,
|
|
69
70
|
incoming_activations,
|
|
@@ -132,10 +133,7 @@ impl WorkflowFuture {
|
|
|
132
133
|
fn fail_wft(&self, run_id: String, fail: Error) {
|
|
133
134
|
warn!("Workflow task failed for {}: {}", run_id, fail);
|
|
134
135
|
self.outgoing_completions
|
|
135
|
-
.send(WorkflowActivationCompletion::fail(
|
|
136
|
-
run_id,
|
|
137
|
-
anyhow_to_fail(fail),
|
|
138
|
-
))
|
|
136
|
+
.send(WorkflowActivationCompletion::fail(run_id, fail.into()))
|
|
139
137
|
.expect("Completion channel intact");
|
|
140
138
|
}
|
|
141
139
|
|
|
@@ -183,8 +181,11 @@ impl WorkflowFuture {
|
|
|
183
181
|
Box::new(result.context("Child Workflow execution must have a result")?),
|
|
184
182
|
))?,
|
|
185
183
|
Variant::UpdateRandomSeed(_) => (),
|
|
186
|
-
Variant::QueryWorkflow(
|
|
187
|
-
|
|
184
|
+
Variant::QueryWorkflow(q) => {
|
|
185
|
+
error!(
|
|
186
|
+
"Queries are not implemented in the Rust SDK. Got query '{}'",
|
|
187
|
+
q.query_id
|
|
188
|
+
);
|
|
188
189
|
}
|
|
189
190
|
Variant::CancelWorkflow(_) => {
|
|
190
191
|
// TODO: Cancel pending futures, etc
|
|
@@ -218,6 +219,9 @@ impl WorkflowFuture {
|
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
Variant::RemoveFromCache(_) => {
|
|
222
|
+
// TODO: Need to abort any spawned tasks, etc. See also cancel WF.
|
|
223
|
+
// How best to do this in executor agnostic way? Is that possible?
|
|
224
|
+
// -- tokio JoinSet does this in a nice way.
|
|
221
225
|
return Ok(true);
|
|
222
226
|
}
|
|
223
227
|
}
|
|
@@ -253,6 +257,7 @@ impl Future for WorkflowFuture {
|
|
|
253
257
|
let mut wlock = self.ctx_shared.write();
|
|
254
258
|
wlock.is_replaying = activation.is_replaying;
|
|
255
259
|
wlock.wf_time = activation.timestamp.try_into_or_none();
|
|
260
|
+
wlock.history_length = activation.history_length;
|
|
256
261
|
}
|
|
257
262
|
|
|
258
263
|
let mut die_of_eviction_when_done = false;
|
|
@@ -283,11 +288,7 @@ impl Future for WorkflowFuture {
|
|
|
283
288
|
.poll_unpin(cx)
|
|
284
289
|
{
|
|
285
290
|
Poll::Ready(Err(e)) => {
|
|
286
|
-
let errmsg = format!(
|
|
287
|
-
"Workflow function panicked: {:?}",
|
|
288
|
-
// Panics are typically strings
|
|
289
|
-
e.downcast::<String>()
|
|
290
|
-
);
|
|
291
|
+
let errmsg = format!("Workflow function panicked: {}", panic_formatter(e));
|
|
291
292
|
warn!("{}", errmsg);
|
|
292
293
|
self.outgoing_completions
|
|
293
294
|
.send(WorkflowActivationCompletion::fail(
|
|
@@ -12,13 +12,15 @@ categories = ["development-tools"]
|
|
|
12
12
|
|
|
13
13
|
[features]
|
|
14
14
|
history_builders = ["uuid", "rand"]
|
|
15
|
+
serde_serialize = []
|
|
15
16
|
|
|
16
17
|
[dependencies]
|
|
17
18
|
anyhow = "1.0"
|
|
18
|
-
base64 = "0.
|
|
19
|
+
base64 = "0.21"
|
|
19
20
|
derive_more = "0.99"
|
|
20
21
|
prost = "0.11"
|
|
21
|
-
prost-
|
|
22
|
+
prost-wkt = "0.4"
|
|
23
|
+
prost-wkt-types = "0.4"
|
|
22
24
|
rand = { version = "0.8", optional = true }
|
|
23
25
|
serde = { version = "1.0", features = ["derive"] }
|
|
24
26
|
serde_json = "1.0"
|
|
@@ -28,3 +30,4 @@ uuid = { version = "1.1", features = ["v4"], optional = true }
|
|
|
28
30
|
|
|
29
31
|
[build-dependencies]
|
|
30
32
|
tonic-build = "0.8"
|
|
33
|
+
prost-wkt-build = "0.4"
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
use std::{env, path::PathBuf};
|
|
2
|
+
|
|
1
3
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
2
4
|
println!("cargo:rerun-if-changed=../protos");
|
|
5
|
+
let out = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
6
|
+
let descriptor_file = out.join("descriptors.bin");
|
|
3
7
|
tonic_build::configure()
|
|
4
8
|
// We don't actually want to build the grpc definitions - we don't need them (for now).
|
|
5
9
|
// Just build the message structs.
|
|
@@ -74,7 +78,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
74
78
|
// All external data is useful to be able to JSON serialize, so it can render in web UI
|
|
75
79
|
.type_attribute(
|
|
76
80
|
".coresdk.external_data",
|
|
77
|
-
"#[derive(::serde::Serialize, ::serde::Deserialize)]",
|
|
81
|
+
"#[cfg_attr(not(feature = \"serde_serialize\"), derive(::serde::Serialize, ::serde::Deserialize))]",
|
|
82
|
+
)
|
|
83
|
+
.type_attribute(
|
|
84
|
+
".",
|
|
85
|
+
"#[cfg_attr(feature = \"serde_serialize\", derive(::serde::Serialize, ::serde::Deserialize))]",
|
|
78
86
|
)
|
|
79
87
|
.field_attribute(
|
|
80
88
|
"coresdk.external_data.LocalActivityMarkerData.complete_time",
|
|
@@ -88,10 +96,26 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
88
96
|
"coresdk.external_data.LocalActivityMarkerData.backoff",
|
|
89
97
|
"#[serde(with = \"opt_duration\")]",
|
|
90
98
|
)
|
|
99
|
+
.extern_path(
|
|
100
|
+
".google.protobuf.Any",
|
|
101
|
+
"::prost_wkt_types::Any"
|
|
102
|
+
)
|
|
103
|
+
.extern_path(
|
|
104
|
+
".google.protobuf.Timestamp",
|
|
105
|
+
"::prost_wkt_types::Timestamp"
|
|
106
|
+
)
|
|
107
|
+
.extern_path(
|
|
108
|
+
".google.protobuf.Duration",
|
|
109
|
+
"::prost_wkt_types::Duration"
|
|
110
|
+
)
|
|
111
|
+
.extern_path(
|
|
112
|
+
".google.protobuf.Value",
|
|
113
|
+
"::prost_wkt_types::Value"
|
|
114
|
+
)
|
|
115
|
+
.file_descriptor_set_path(#[allow(clippy::needless_borrow)] &descriptor_file)
|
|
91
116
|
.compile(
|
|
92
117
|
&[
|
|
93
118
|
"../protos/local/temporal/sdk/core/core_interface.proto",
|
|
94
|
-
"../protos/local/temporal/sdk/core/bridge/bridge.proto",
|
|
95
119
|
"../protos/api_upstream/temporal/api/workflowservice/v1/service.proto",
|
|
96
120
|
"../protos/api_upstream/temporal/api/operatorservice/v1/service.proto",
|
|
97
121
|
"../protos/testsrv_upstream/temporal/api/testservice/v1/service.proto",
|
|
@@ -104,5 +128,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
104
128
|
"../protos/grpc",
|
|
105
129
|
],
|
|
106
130
|
)?;
|
|
131
|
+
|
|
132
|
+
#[cfg(feature = "serde_serialize")]
|
|
133
|
+
{
|
|
134
|
+
use prost_wkt_build::{FileDescriptorSet, Message};
|
|
135
|
+
|
|
136
|
+
let descriptor_bytes = std::fs::read(descriptor_file)?;
|
|
137
|
+
let descriptor = FileDescriptorSet::decode(&descriptor_bytes[..])?;
|
|
138
|
+
prost_wkt_build::add_serde(out, descriptor);
|
|
139
|
+
}
|
|
140
|
+
|
|
107
141
|
Ok(())
|
|
108
142
|
}
|