@temporalio/core-bridge 0.16.4 → 0.18.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 +339 -226
- package/Cargo.toml +7 -3
- package/common.js +50 -0
- package/index.d.ts +7 -0
- package/index.js +12 -0
- package/package.json +7 -4
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/{index.node → releases/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/scripts/build.js +10 -50
- package/sdk-core/.buildkite/docker/Dockerfile +1 -1
- package/sdk-core/.buildkite/docker/docker-compose.yaml +2 -2
- package/sdk-core/.buildkite/pipeline.yml +2 -0
- package/sdk-core/Cargo.toml +1 -88
- package/sdk-core/README.md +30 -6
- package/sdk-core/bridge-ffi/Cargo.toml +24 -0
- package/sdk-core/bridge-ffi/LICENSE.txt +23 -0
- package/sdk-core/bridge-ffi/build.rs +25 -0
- package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +216 -0
- package/sdk-core/bridge-ffi/src/lib.rs +829 -0
- package/sdk-core/bridge-ffi/src/wrappers.rs +193 -0
- package/sdk-core/client/Cargo.toml +32 -0
- package/sdk-core/{src/pollers/gateway.rs → client/src/lib.rs} +101 -195
- package/sdk-core/client/src/metrics.rs +89 -0
- package/sdk-core/client/src/mocks.rs +167 -0
- package/sdk-core/{src/pollers → client/src}/retry.rs +172 -14
- package/sdk-core/core/Cargo.toml +96 -0
- package/sdk-core/{src → core/src}/core_tests/activity_tasks.rs +193 -37
- package/sdk-core/{src → core/src}/core_tests/child_workflows.rs +14 -14
- package/sdk-core/{src → core/src}/core_tests/determinism.rs +8 -8
- package/sdk-core/core/src/core_tests/local_activities.rs +328 -0
- package/sdk-core/{src → core/src}/core_tests/mod.rs +6 -9
- package/sdk-core/{src → core/src}/core_tests/queries.rs +54 -54
- package/sdk-core/{src → core/src}/core_tests/replay_flag.rs +8 -12
- package/sdk-core/{src → core/src}/core_tests/workers.rs +120 -33
- package/sdk-core/{src → core/src}/core_tests/workflow_cancels.rs +16 -26
- package/sdk-core/{src → core/src}/core_tests/workflow_tasks.rs +280 -292
- package/sdk-core/core/src/lib.rs +374 -0
- package/sdk-core/{src → core/src}/log_export.rs +3 -27
- package/sdk-core/core/src/pending_activations.rs +162 -0
- package/sdk-core/{src → core/src}/pollers/mod.rs +4 -22
- package/sdk-core/{src → core/src}/pollers/poll_buffer.rs +1 -1
- package/sdk-core/core/src/protosext/mod.rs +396 -0
- package/sdk-core/core/src/replay/mod.rs +210 -0
- package/sdk-core/core/src/retry_logic.rs +144 -0
- package/sdk-core/{src → core/src}/telemetry/metrics.rs +3 -58
- package/sdk-core/{src → core/src}/telemetry/mod.rs +8 -8
- package/sdk-core/{src → core/src}/telemetry/prometheus_server.rs +0 -0
- package/sdk-core/{src → core/src}/test_help/mod.rs +35 -83
- package/sdk-core/{src → core/src}/worker/activities/activity_heartbeat_manager.rs +95 -42
- package/sdk-core/core/src/worker/activities/local_activities.rs +973 -0
- package/sdk-core/{src → core/src}/worker/activities.rs +52 -33
- package/sdk-core/{src → core/src}/worker/dispatcher.rs +8 -6
- package/sdk-core/{src → core/src}/worker/mod.rs +347 -221
- package/sdk-core/core/src/worker/wft_delivery.rs +81 -0
- package/sdk-core/{src → core/src}/workflow/bridge.rs +5 -2
- package/sdk-core/{src → core/src}/workflow/driven_workflow.rs +17 -7
- package/sdk-core/{src → core/src}/workflow/history_update.rs +33 -7
- package/sdk-core/{src → core/src/workflow}/machines/activity_state_machine.rs +26 -26
- package/sdk-core/{src → core/src/workflow}/machines/cancel_external_state_machine.rs +8 -11
- package/sdk-core/{src → core/src/workflow}/machines/cancel_workflow_state_machine.rs +19 -21
- package/sdk-core/{src → core/src/workflow}/machines/child_workflow_state_machine.rs +20 -31
- package/sdk-core/{src → core/src/workflow}/machines/complete_workflow_state_machine.rs +3 -5
- package/sdk-core/{src → core/src/workflow}/machines/continue_as_new_workflow_state_machine.rs +18 -18
- package/sdk-core/{src → core/src/workflow}/machines/fail_workflow_state_machine.rs +5 -6
- package/sdk-core/core/src/workflow/machines/local_activity_state_machine.rs +1451 -0
- package/sdk-core/{src → core/src/workflow}/machines/mod.rs +54 -107
- package/sdk-core/{src → core/src/workflow}/machines/mutable_side_effect_state_machine.rs +0 -0
- package/sdk-core/{src → core/src/workflow}/machines/patch_state_machine.rs +29 -30
- package/sdk-core/{src → core/src/workflow}/machines/side_effect_state_machine.rs +0 -0
- package/sdk-core/{src → core/src/workflow}/machines/signal_external_state_machine.rs +17 -19
- package/sdk-core/{src → core/src/workflow}/machines/timer_state_machine.rs +20 -21
- package/sdk-core/{src → core/src/workflow}/machines/transition_coverage.rs +5 -2
- package/sdk-core/{src → core/src/workflow}/machines/upsert_search_attributes_state_machine.rs +0 -0
- package/sdk-core/core/src/workflow/machines/workflow_machines/local_acts.rs +96 -0
- package/sdk-core/{src → core/src/workflow}/machines/workflow_machines.rs +357 -171
- package/sdk-core/{src → core/src/workflow}/machines/workflow_task_state_machine.rs +1 -1
- package/sdk-core/{src → core/src}/workflow/mod.rs +200 -39
- package/sdk-core/{src → core/src}/workflow/workflow_tasks/cache_manager.rs +0 -0
- package/sdk-core/{src → core/src}/workflow/workflow_tasks/concurrency_manager.rs +38 -5
- package/sdk-core/{src → core/src}/workflow/workflow_tasks/mod.rs +317 -103
- package/sdk-core/{test_utils → core-api}/Cargo.toml +10 -7
- package/sdk-core/{src → core-api/src}/errors.rs +42 -92
- package/sdk-core/core-api/src/lib.rs +158 -0
- package/sdk-core/{src/worker/config.rs → core-api/src/worker.rs} +18 -23
- package/sdk-core/etc/deps.svg +156 -0
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +5 -5
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +3 -5
- package/sdk-core/fsm/rustfsm_trait/src/lib.rs +7 -1
- package/sdk-core/histories/fail_wf_task.bin +0 -0
- package/sdk-core/histories/timer_workflow_history.bin +0 -0
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +44 -13
- package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +19 -1
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +1 -1
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +9 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +13 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +14 -7
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +176 -18
- package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +11 -0
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +3 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +156 -7
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +135 -104
- package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
- package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +78 -0
- package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +205 -0
- package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +61 -0
- package/sdk-core/protos/local/{child_workflow.proto → temporal/sdk/core/child_workflow/child_workflow.proto} +1 -1
- package/sdk-core/protos/local/{common.proto → temporal/sdk/core/common/common.proto} +5 -3
- package/sdk-core/protos/local/{core_interface.proto → temporal/sdk/core/core_interface.proto} +10 -10
- package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
- package/sdk-core/protos/local/{workflow_activation.proto → temporal/sdk/core/workflow_activation/workflow_activation.proto} +35 -11
- package/sdk-core/protos/local/{workflow_commands.proto → temporal/sdk/core/workflow_commands/workflow_commands.proto} +55 -4
- package/sdk-core/protos/local/{workflow_completion.proto → temporal/sdk/core/workflow_completion/workflow_completion.proto} +3 -3
- package/sdk-core/sdk/Cargo.toml +32 -0
- package/sdk-core/{src/prototype_rust_sdk → sdk/src}/conversions.rs +0 -0
- package/sdk-core/sdk/src/lib.rs +699 -0
- package/sdk-core/sdk/src/payload_converter.rs +11 -0
- package/sdk-core/sdk/src/workflow_context/options.rs +180 -0
- package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_context.rs +201 -124
- package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_future.rs +63 -30
- package/sdk-core/sdk-core-protos/Cargo.toml +10 -0
- package/sdk-core/sdk-core-protos/build.rs +28 -6
- package/sdk-core/sdk-core-protos/src/constants.rs +7 -0
- package/sdk-core/{src/test_help → sdk-core-protos/src}/history_builder.rs +134 -49
- package/sdk-core/sdk-core-protos/src/history_info.rs +216 -0
- package/sdk-core/sdk-core-protos/src/lib.rs +601 -168
- package/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
- package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
- package/sdk-core/test-utils/Cargo.toml +32 -0
- package/sdk-core/{src/test_help → test-utils/src}/canned_histories.rs +59 -78
- package/sdk-core/test-utils/src/histfetch.rs +28 -0
- package/sdk-core/{test_utils → test-utils}/src/lib.rs +131 -68
- package/sdk-core/tests/integ_tests/client_tests.rs +1 -1
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +11 -7
- package/sdk-core/tests/integ_tests/polling_tests.rs +12 -11
- package/sdk-core/tests/integ_tests/queries_tests.rs +82 -78
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +91 -71
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +3 -4
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +2 -4
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -6
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +4 -6
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -4
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +496 -0
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +5 -8
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +125 -0
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +7 -13
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +33 -5
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +12 -16
- package/sdk-core/tests/integ_tests/workflow_tests.rs +85 -82
- package/sdk-core/tests/load_tests.rs +6 -6
- package/sdk-core/tests/main.rs +2 -2
- package/src/conversions.rs +24 -21
- package/src/errors.rs +8 -0
- package/src/lib.rs +323 -211
- package/sdk-core/protos/local/activity_result.proto +0 -46
- package/sdk-core/protos/local/activity_task.proto +0 -66
- package/sdk-core/src/core_tests/retry.rs +0 -147
- package/sdk-core/src/lib.rs +0 -403
- package/sdk-core/src/machines/local_activity_state_machine.rs +0 -117
- package/sdk-core/src/pending_activations.rs +0 -249
- package/sdk-core/src/protosext/mod.rs +0 -160
- package/sdk-core/src/prototype_rust_sdk.rs +0 -412
- package/sdk-core/src/task_token.rs +0 -20
- package/sdk-core/src/test_help/history_info.rs +0 -157
|
@@ -1,25 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
mod options;
|
|
2
|
+
|
|
3
|
+
pub use options::{ActivityOptions, ChildWorkflowOptions, LocalActivityOptions};
|
|
4
|
+
|
|
5
|
+
use crate::{
|
|
6
|
+
workflow_context::options::IntoWorkflowCommand, CancelExternalWfResult, CancellableID,
|
|
7
|
+
CommandCreateRequest, CommandSubscribeChildWorkflowCompletion, RustWfCmd,
|
|
8
|
+
SignalExternalWfResult, TimerResult, UnblockEvent, Unblockable,
|
|
5
9
|
};
|
|
6
10
|
use crossbeam::channel::{Receiver, Sender};
|
|
7
11
|
use futures::{task::Context, FutureExt, Stream};
|
|
8
12
|
use parking_lot::RwLock;
|
|
9
13
|
use std::{
|
|
10
|
-
collections::HashMap,
|
|
11
|
-
|
|
14
|
+
collections::HashMap,
|
|
15
|
+
future::Future,
|
|
16
|
+
marker::PhantomData,
|
|
17
|
+
pin::Pin,
|
|
18
|
+
sync::{
|
|
19
|
+
atomic::{AtomicBool, Ordering},
|
|
20
|
+
Arc,
|
|
21
|
+
},
|
|
22
|
+
task::Poll,
|
|
23
|
+
time::{Duration, SystemTime},
|
|
12
24
|
};
|
|
13
25
|
use temporal_sdk_core_protos::coresdk::{
|
|
14
|
-
activity_result::
|
|
15
|
-
child_workflow::
|
|
26
|
+
activity_result::{activity_resolution, ActivityResolution},
|
|
27
|
+
child_workflow::ChildWorkflowResult,
|
|
16
28
|
common::{NamespacedWorkflowExecution, Payload},
|
|
17
29
|
workflow_activation::resolve_child_workflow_execution_start::Status as ChildWorkflowStartStatus,
|
|
18
30
|
workflow_commands::{
|
|
19
31
|
request_cancel_external_workflow_execution as cancel_we,
|
|
20
|
-
signal_external_workflow_execution as sig_we, workflow_command,
|
|
21
|
-
RequestCancelExternalWorkflowExecution,
|
|
22
|
-
|
|
32
|
+
signal_external_workflow_execution as sig_we, workflow_command,
|
|
33
|
+
RequestCancelExternalWorkflowExecution, SetPatchMarker, SignalExternalWorkflowExecution,
|
|
34
|
+
StartTimer,
|
|
23
35
|
},
|
|
24
36
|
};
|
|
25
37
|
use tokio::sync::{mpsc, oneshot, watch};
|
|
@@ -28,12 +40,17 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
|
|
|
28
40
|
/// Used within workflows to issue commands, get info, etc.
|
|
29
41
|
pub struct WfContext {
|
|
30
42
|
namespace: String,
|
|
43
|
+
task_queue: String,
|
|
31
44
|
args: Vec<Payload>,
|
|
32
45
|
|
|
33
46
|
chan: Sender<RustWfCmd>,
|
|
34
47
|
am_cancelled: watch::Receiver<bool>,
|
|
35
48
|
shared: Arc<RwLock<WfContextSharedData>>,
|
|
36
49
|
|
|
50
|
+
seq_nums: RwLock<WfCtxProtectedDat>,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
struct WfCtxProtectedDat {
|
|
37
54
|
next_timer_sequence_number: u32,
|
|
38
55
|
next_activity_sequence_number: u32,
|
|
39
56
|
next_child_workflow_sequence_number: u32,
|
|
@@ -41,11 +58,40 @@ pub struct WfContext {
|
|
|
41
58
|
next_signal_external_wf_sequence_number: u32,
|
|
42
59
|
}
|
|
43
60
|
|
|
61
|
+
impl WfCtxProtectedDat {
|
|
62
|
+
fn next_timer_seq(&mut self) -> u32 {
|
|
63
|
+
let seq = self.next_timer_sequence_number;
|
|
64
|
+
self.next_timer_sequence_number += 1;
|
|
65
|
+
seq
|
|
66
|
+
}
|
|
67
|
+
fn next_activity_seq(&mut self) -> u32 {
|
|
68
|
+
let seq = self.next_activity_sequence_number;
|
|
69
|
+
self.next_activity_sequence_number += 1;
|
|
70
|
+
seq
|
|
71
|
+
}
|
|
72
|
+
fn next_child_workflow_seq(&mut self) -> u32 {
|
|
73
|
+
let seq = self.next_child_workflow_sequence_number;
|
|
74
|
+
self.next_child_workflow_sequence_number += 1;
|
|
75
|
+
seq
|
|
76
|
+
}
|
|
77
|
+
fn next_cancel_external_wf_seq(&mut self) -> u32 {
|
|
78
|
+
let seq = self.next_cancel_external_wf_sequence_number;
|
|
79
|
+
self.next_cancel_external_wf_sequence_number += 1;
|
|
80
|
+
seq
|
|
81
|
+
}
|
|
82
|
+
fn next_signal_external_wf_seq(&mut self) -> u32 {
|
|
83
|
+
let seq = self.next_signal_external_wf_sequence_number;
|
|
84
|
+
self.next_signal_external_wf_sequence_number += 1;
|
|
85
|
+
seq
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
44
89
|
#[derive(Clone, Debug, Default)]
|
|
45
90
|
pub struct WfContextSharedData {
|
|
46
91
|
/// Maps change ids -> resolved status
|
|
47
92
|
pub changes: HashMap<String, bool>,
|
|
48
93
|
pub is_replaying: bool,
|
|
94
|
+
pub wf_time: Option<SystemTime>,
|
|
49
95
|
}
|
|
50
96
|
|
|
51
97
|
// TODO: Dataconverter type interface to replace Payloads here. Possibly just use serde
|
|
@@ -55,6 +101,7 @@ impl WfContext {
|
|
|
55
101
|
/// sent from the workflow.
|
|
56
102
|
pub(super) fn new(
|
|
57
103
|
namespace: String,
|
|
104
|
+
task_queue: String,
|
|
58
105
|
args: Vec<Payload>,
|
|
59
106
|
am_cancelled: watch::Receiver<bool>,
|
|
60
107
|
) -> (Self, Receiver<RustWfCmd>) {
|
|
@@ -63,15 +110,18 @@ impl WfContext {
|
|
|
63
110
|
(
|
|
64
111
|
Self {
|
|
65
112
|
namespace,
|
|
113
|
+
task_queue,
|
|
66
114
|
args,
|
|
67
115
|
chan,
|
|
68
116
|
am_cancelled,
|
|
69
117
|
shared: Arc::new(RwLock::new(Default::default())),
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
118
|
+
seq_nums: RwLock::new(WfCtxProtectedDat {
|
|
119
|
+
next_timer_sequence_number: 1,
|
|
120
|
+
next_activity_sequence_number: 1,
|
|
121
|
+
next_child_workflow_sequence_number: 1,
|
|
122
|
+
next_cancel_external_wf_sequence_number: 1,
|
|
123
|
+
next_signal_external_wf_sequence_number: 1,
|
|
124
|
+
}),
|
|
75
125
|
},
|
|
76
126
|
rx,
|
|
77
127
|
)
|
|
@@ -87,6 +137,11 @@ impl WfContext {
|
|
|
87
137
|
self.args.as_slice()
|
|
88
138
|
}
|
|
89
139
|
|
|
140
|
+
/// Return the current time according to the workflow (which is not wall-clock time).
|
|
141
|
+
pub fn workflow_time(&self) -> Option<SystemTime> {
|
|
142
|
+
self.shared.read().wf_time
|
|
143
|
+
}
|
|
144
|
+
|
|
90
145
|
pub(crate) fn get_shared_data(&self) -> Arc<RwLock<WfContextSharedData>> {
|
|
91
146
|
self.shared.clone()
|
|
92
147
|
}
|
|
@@ -103,9 +158,8 @@ impl WfContext {
|
|
|
103
158
|
}
|
|
104
159
|
|
|
105
160
|
/// Request to create a timer
|
|
106
|
-
pub fn timer(&
|
|
107
|
-
let seq = self.
|
|
108
|
-
self.next_timer_sequence_number += 1;
|
|
161
|
+
pub fn timer(&self, duration: Duration) -> impl CancellableFuture<TimerResult> {
|
|
162
|
+
let seq = self.seq_nums.write().next_timer_seq();
|
|
109
163
|
let (cmd, unblocker) = CancellableWFCommandFut::new(CancellableID::Timer(seq));
|
|
110
164
|
self.send(
|
|
111
165
|
CommandCreateRequest {
|
|
@@ -122,13 +176,18 @@ impl WfContext {
|
|
|
122
176
|
}
|
|
123
177
|
|
|
124
178
|
/// Request to run an activity
|
|
125
|
-
pub fn activity(
|
|
126
|
-
|
|
127
|
-
|
|
179
|
+
pub fn activity(
|
|
180
|
+
&self,
|
|
181
|
+
mut opts: ActivityOptions,
|
|
182
|
+
) -> impl CancellableFuture<ActivityResolution> {
|
|
183
|
+
if opts.task_queue.is_empty() {
|
|
184
|
+
opts.task_queue = self.task_queue.clone()
|
|
185
|
+
}
|
|
186
|
+
let seq = self.seq_nums.write().next_activity_seq();
|
|
128
187
|
let (cmd, unblocker) = CancellableWFCommandFut::new(CancellableID::Activity(seq));
|
|
129
188
|
self.send(
|
|
130
189
|
CommandCreateRequest {
|
|
131
|
-
cmd: opts.
|
|
190
|
+
cmd: opts.into_command(seq).into(),
|
|
132
191
|
unblocker,
|
|
133
192
|
}
|
|
134
193
|
.into(),
|
|
@@ -136,8 +195,33 @@ impl WfContext {
|
|
|
136
195
|
cmd
|
|
137
196
|
}
|
|
138
197
|
|
|
139
|
-
/// Request to
|
|
140
|
-
pub fn
|
|
198
|
+
/// Request to run a local activity
|
|
199
|
+
pub fn local_activity(
|
|
200
|
+
&self,
|
|
201
|
+
opts: LocalActivityOptions,
|
|
202
|
+
) -> impl CancellableFuture<ActivityResolution> + '_ {
|
|
203
|
+
LATimerBackoffFut::new(opts, self)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/// Request to run a local activity with no implementation of timer-backoff based retrying.
|
|
207
|
+
fn local_activity_no_timer_retry(
|
|
208
|
+
&self,
|
|
209
|
+
opts: LocalActivityOptions,
|
|
210
|
+
) -> impl CancellableFuture<ActivityResolution> {
|
|
211
|
+
let seq = self.seq_nums.write().next_activity_seq();
|
|
212
|
+
let (cmd, unblocker) = CancellableWFCommandFut::new(CancellableID::LocalActivity(seq));
|
|
213
|
+
self.send(
|
|
214
|
+
CommandCreateRequest {
|
|
215
|
+
cmd: opts.into_command(seq).into(),
|
|
216
|
+
unblocker,
|
|
217
|
+
}
|
|
218
|
+
.into(),
|
|
219
|
+
);
|
|
220
|
+
cmd
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/// Creates a child workflow stub with the provided options
|
|
224
|
+
pub fn child_workflow(&self, opts: ChildWorkflowOptions) -> ChildWorkflow {
|
|
141
225
|
ChildWorkflow { opts }
|
|
142
226
|
}
|
|
143
227
|
|
|
@@ -180,7 +264,7 @@ impl WfContext {
|
|
|
180
264
|
/// Send a signal to an external workflow. May resolve as a failure if the signal didn't work
|
|
181
265
|
/// or was cancelled.
|
|
182
266
|
pub fn signal_workflow(
|
|
183
|
-
&
|
|
267
|
+
&self,
|
|
184
268
|
workflow_id: impl Into<String>,
|
|
185
269
|
run_id: impl Into<String>,
|
|
186
270
|
signal_name: impl Into<String>,
|
|
@@ -196,7 +280,7 @@ impl WfContext {
|
|
|
196
280
|
|
|
197
281
|
/// Return a stream that produces values when the named signal is sent to this workflow
|
|
198
282
|
pub fn make_signal_channel(
|
|
199
|
-
&
|
|
283
|
+
&self,
|
|
200
284
|
signal_name: impl Into<String>,
|
|
201
285
|
) -> impl Stream<Item = Vec<Payload>> {
|
|
202
286
|
let (tx, rx) = mpsc::unbounded_channel();
|
|
@@ -211,14 +295,12 @@ impl WfContext {
|
|
|
211
295
|
|
|
212
296
|
/// Request the cancellation of an external workflow. May resolve as a failure if the workflow
|
|
213
297
|
/// was not found or the cancel was otherwise unsendable.
|
|
214
|
-
/// TODO: Own result type
|
|
215
298
|
pub fn cancel_external(
|
|
216
|
-
&
|
|
299
|
+
&self,
|
|
217
300
|
target: NamespacedWorkflowExecution,
|
|
218
301
|
) -> impl Future<Output = CancelExternalWfResult> {
|
|
219
302
|
let target = cancel_we::Target::WorkflowExecution(target);
|
|
220
|
-
let seq = self.
|
|
221
|
-
self.next_cancel_external_wf_sequence_number += 1;
|
|
303
|
+
let seq = self.seq_nums.write().next_cancel_external_wf_seq();
|
|
222
304
|
let (cmd, unblocker) = WFCommandFut::new();
|
|
223
305
|
self.send(
|
|
224
306
|
CommandCreateRequest {
|
|
@@ -235,13 +317,12 @@ impl WfContext {
|
|
|
235
317
|
}
|
|
236
318
|
|
|
237
319
|
fn send_signal_wf(
|
|
238
|
-
&
|
|
320
|
+
&self,
|
|
239
321
|
signal_name: impl Into<String>,
|
|
240
322
|
payload: impl Into<Payload>,
|
|
241
323
|
target: sig_we::Target,
|
|
242
324
|
) -> impl CancellableFuture<SignalExternalWfResult> {
|
|
243
|
-
let seq = self.
|
|
244
|
-
self.next_signal_external_wf_sequence_number += 1;
|
|
325
|
+
let seq = self.seq_nums.write().next_signal_external_wf_seq();
|
|
245
326
|
let (cmd, unblocker) =
|
|
246
327
|
CancellableWFCommandFut::new(CancellableID::SignalExternalWorkflow(seq));
|
|
247
328
|
self.send(
|
|
@@ -261,7 +342,7 @@ impl WfContext {
|
|
|
261
342
|
}
|
|
262
343
|
|
|
263
344
|
/// Cancel any cancellable operation by ID
|
|
264
|
-
fn cancel(&
|
|
345
|
+
fn cancel(&self, cancellable_id: CancellableID) {
|
|
265
346
|
self.send(RustWfCmd::Cancel(cancellable_id));
|
|
266
347
|
}
|
|
267
348
|
|
|
@@ -274,7 +355,7 @@ impl WfContext {
|
|
|
274
355
|
/// Used in the prototype SDK for cancelling operations like timers and activities.
|
|
275
356
|
pub trait CancellableFuture<T>: Future<Output = T> {
|
|
276
357
|
/// Cancel this Future
|
|
277
|
-
fn cancel(&self, cx: &
|
|
358
|
+
fn cancel(&self, cx: &WfContext);
|
|
278
359
|
}
|
|
279
360
|
|
|
280
361
|
struct WFCommandFut<T, D> {
|
|
@@ -362,98 +443,96 @@ impl<T, D> CancellableFuture<T> for CancellableWFCommandFut<T, D>
|
|
|
362
443
|
where
|
|
363
444
|
T: Unblockable<OtherDat = D>,
|
|
364
445
|
{
|
|
365
|
-
fn cancel(&self, cx: &
|
|
446
|
+
fn cancel(&self, cx: &WfContext) {
|
|
366
447
|
cx.cancel(self.cancellable_id.clone());
|
|
367
448
|
}
|
|
368
449
|
}
|
|
369
450
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
pub activity_id: Option<String>,
|
|
379
|
-
/// Type of activity to schedule
|
|
380
|
-
pub activity_type: String,
|
|
381
|
-
/// Task queue to schedule the activity in
|
|
382
|
-
pub task_queue: String,
|
|
383
|
-
/// Time that the Activity Task can stay in the Task Queue before it is picked up by a Worker.
|
|
384
|
-
/// Do not specify this timeout unless using host specific Task Queues for Activity Tasks are
|
|
385
|
-
/// being used for routing.
|
|
386
|
-
/// `schedule_to_start_timeout` is always non-retryable.
|
|
387
|
-
/// Retrying after this timeout doesn't make sense as it would just put the Activity Task back
|
|
388
|
-
/// into the same Task Queue.
|
|
389
|
-
pub schedule_to_start_timeout: Option<Duration>,
|
|
390
|
-
/// Maximum time of a single Activity execution attempt.
|
|
391
|
-
/// Note that the Temporal Server doesn't detect Worker process failures directly.
|
|
392
|
-
/// It relies on this timeout to detect that an Activity that didn't complete on time.
|
|
393
|
-
/// So this timeout should be as short as the longest possible execution of the Activity body.
|
|
394
|
-
/// Potentially long running Activities must specify `heartbeat_timeout` and heartbeat from the
|
|
395
|
-
/// activity periodically for timely failure detection.
|
|
396
|
-
/// Either this option or `schedule_to_close_timeout` is required.
|
|
397
|
-
pub start_to_close_timeout: Option<Duration>,
|
|
398
|
-
/// Total time that a workflow is willing to wait for Activity to complete.
|
|
399
|
-
/// `schedule_to_close_timeout` limits the total time of an Activity's execution including
|
|
400
|
-
/// retries (use `start_to_close_timeout` to limit the time of a single attempt).
|
|
401
|
-
/// Either this option or `start_to_close_timeout` is required.
|
|
402
|
-
pub schedule_to_close_timeout: Option<Duration>,
|
|
403
|
-
/// Heartbeat interval. Activity must heartbeat before this interval passes after a last
|
|
404
|
-
/// heartbeat or activity start.
|
|
405
|
-
pub heartbeat_timeout: Option<Duration>,
|
|
406
|
-
/// Determines what the SDK does when the Activity is cancelled.
|
|
407
|
-
pub cancellation_type: ActivityCancellationType,
|
|
408
|
-
// Add more fields here as needed
|
|
451
|
+
struct LATimerBackoffFut<'a> {
|
|
452
|
+
la_opts: LocalActivityOptions,
|
|
453
|
+
current_fut: Pin<Box<dyn CancellableFuture<ActivityResolution> + Send + Unpin + 'a>>,
|
|
454
|
+
timer_fut: Option<Pin<Box<dyn CancellableFuture<TimerResult> + Send + Unpin + 'a>>>,
|
|
455
|
+
ctx: &'a WfContext,
|
|
456
|
+
next_attempt: u32,
|
|
457
|
+
next_sched_time: Option<prost_types::Timestamp>,
|
|
458
|
+
did_cancel: AtomicBool,
|
|
409
459
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
activity_type: self.activity_type.clone(),
|
|
421
|
-
task_queue: self.task_queue.clone(),
|
|
422
|
-
schedule_to_close_timeout: self.schedule_to_close_timeout.map(Into::into),
|
|
423
|
-
schedule_to_start_timeout: self.schedule_to_start_timeout.map(Into::into),
|
|
424
|
-
start_to_close_timeout: self.start_to_close_timeout.map(Into::into),
|
|
425
|
-
heartbeat_timeout: self.heartbeat_timeout.map(Into::into),
|
|
426
|
-
cancellation_type: self.cancellation_type as i32,
|
|
427
|
-
..Default::default()
|
|
460
|
+
impl<'a> LATimerBackoffFut<'a> {
|
|
461
|
+
pub(crate) fn new(opts: LocalActivityOptions, ctx: &'a WfContext) -> Self {
|
|
462
|
+
Self {
|
|
463
|
+
la_opts: opts.clone(),
|
|
464
|
+
current_fut: Box::pin(ctx.local_activity_no_timer_retry(opts)),
|
|
465
|
+
timer_fut: None,
|
|
466
|
+
ctx,
|
|
467
|
+
next_attempt: 1,
|
|
468
|
+
next_sched_time: None,
|
|
469
|
+
did_cancel: AtomicBool::new(false),
|
|
428
470
|
}
|
|
429
471
|
}
|
|
430
472
|
}
|
|
473
|
+
impl<'a> Unpin for LATimerBackoffFut<'a> {}
|
|
474
|
+
impl<'a> Future for LATimerBackoffFut<'a> {
|
|
475
|
+
type Output = ActivityResolution;
|
|
431
476
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
477
|
+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
478
|
+
// If the timer exists, wait for it first
|
|
479
|
+
if let Some(tf) = self.timer_fut.as_mut() {
|
|
480
|
+
return match tf.poll_unpin(cx) {
|
|
481
|
+
Poll::Ready(tr) => {
|
|
482
|
+
self.timer_fut = None;
|
|
483
|
+
// Schedule next LA if this timer wasn't cancelled
|
|
484
|
+
if let TimerResult::Fired = tr {
|
|
485
|
+
let mut opts = self.la_opts.clone();
|
|
486
|
+
opts.attempt = Some(self.next_attempt);
|
|
487
|
+
opts.original_schedule_time = self.next_sched_time.clone();
|
|
488
|
+
self.current_fut = Box::pin(self.ctx.local_activity_no_timer_retry(opts));
|
|
489
|
+
Poll::Pending
|
|
490
|
+
} else {
|
|
491
|
+
Poll::Ready(ActivityResolution {
|
|
492
|
+
status: Some(
|
|
493
|
+
activity_resolution::Status::Cancelled(Default::default()),
|
|
494
|
+
),
|
|
495
|
+
})
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
Poll::Pending => Poll::Pending,
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
let poll_res = self.current_fut.poll_unpin(cx);
|
|
502
|
+
if let Poll::Ready(ref r) = poll_res {
|
|
503
|
+
// If we've already said we want to cancel, don't schedule the backoff timer. Just
|
|
504
|
+
// return cancel status. This can happen if cancel comes after the LA says it wants to
|
|
505
|
+
// back off but before we have scheduled the timer.
|
|
506
|
+
if self.did_cancel.load(Ordering::Acquire) {
|
|
507
|
+
return Poll::Ready(ActivityResolution {
|
|
508
|
+
status: Some(activity_resolution::Status::Cancelled(Default::default())),
|
|
509
|
+
});
|
|
510
|
+
}
|
|
444
511
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
512
|
+
if let Some(activity_resolution::Status::Backoff(b)) = r.status.as_ref() {
|
|
513
|
+
let timer_f = self.ctx.timer(
|
|
514
|
+
b.backoff_duration
|
|
515
|
+
.clone()
|
|
516
|
+
.expect("Duration is set")
|
|
517
|
+
.try_into()
|
|
518
|
+
.expect("duration converts ok"),
|
|
519
|
+
);
|
|
520
|
+
self.timer_fut = Some(Box::pin(timer_f));
|
|
521
|
+
self.next_attempt = b.attempt;
|
|
522
|
+
self.next_sched_time = b.original_schedule_time.clone();
|
|
523
|
+
return Poll::Pending;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
poll_res
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
impl<'a> CancellableFuture<ActivityResolution> for LATimerBackoffFut<'a> {
|
|
530
|
+
fn cancel(&self, ctx: &WfContext) {
|
|
531
|
+
self.did_cancel.store(true, Ordering::Release);
|
|
532
|
+
if let Some(tf) = self.timer_fut.as_ref() {
|
|
533
|
+
tf.cancel(ctx);
|
|
456
534
|
}
|
|
535
|
+
self.current_fut.cancel(ctx);
|
|
457
536
|
}
|
|
458
537
|
}
|
|
459
538
|
|
|
@@ -494,14 +573,12 @@ pub struct StartedChildWorkflow {
|
|
|
494
573
|
|
|
495
574
|
impl ChildWorkflow {
|
|
496
575
|
/// Start the child workflow, the returned Future is cancellable.
|
|
497
|
-
pub fn start(self, cx: &
|
|
498
|
-
let child_seq = cx.
|
|
499
|
-
cx.next_child_workflow_sequence_number += 1;
|
|
576
|
+
pub fn start(self, cx: &WfContext) -> impl CancellableFuture<PendingChildWorkflow> {
|
|
577
|
+
let child_seq = cx.seq_nums.write().next_child_workflow_seq();
|
|
500
578
|
// Immediately create the command/future for the result, otherwise if the user does
|
|
501
579
|
// not await the result until *after* we receive an activation for it, there will be nothing
|
|
502
580
|
// to match when unblocking.
|
|
503
|
-
let cancel_seq = cx.
|
|
504
|
-
cx.next_cancel_external_wf_sequence_number += 1;
|
|
581
|
+
let cancel_seq = cx.seq_nums.write().next_cancel_external_wf_seq();
|
|
505
582
|
let (result_cmd, unblocker) =
|
|
506
583
|
CancellableWFCommandFut::new(CancellableID::ExternalWorkflow {
|
|
507
584
|
seqnum: cancel_seq,
|
|
@@ -546,7 +623,7 @@ impl StartedChildWorkflow {
|
|
|
546
623
|
}
|
|
547
624
|
|
|
548
625
|
/// Cancel the child workflow
|
|
549
|
-
pub fn cancel(&self, cx: &
|
|
626
|
+
pub fn cancel(&self, cx: &WfContext) -> impl Future<Output = CancelExternalWfResult> {
|
|
550
627
|
let target = NamespacedWorkflowExecution {
|
|
551
628
|
namespace: cx.namespace().to_string(),
|
|
552
629
|
workflow_id: self.common.workflow_id.clone(),
|
|
@@ -558,7 +635,7 @@ impl StartedChildWorkflow {
|
|
|
558
635
|
/// Signal the child workflow
|
|
559
636
|
pub fn signal(
|
|
560
637
|
&self,
|
|
561
|
-
cx: &
|
|
638
|
+
cx: &WfContext,
|
|
562
639
|
signal_name: impl Into<String>,
|
|
563
640
|
payload: impl Into<Payload>,
|
|
564
641
|
) -> impl CancellableFuture<SignalExternalWfResult> {
|