@temporalio/core-bridge 0.17.2 → 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 +45 -52
- 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 +264 -286
- 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 +34 -73
- 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 +305 -195
- 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 +19 -21
- 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 +344 -160
- 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 +297 -81
- package/sdk-core/{test_utils → core-api}/Cargo.toml +10 -7
- package/sdk-core/{src → core-api/src}/errors.rs +42 -90
- 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 +594 -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 -158
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
use crate::{
|
|
2
|
-
errors::ActivityHeartbeatError, pollers::ServerGatewayApis, task_token::TaskToken,
|
|
3
|
-
worker::activities::PendingActivityCancel,
|
|
4
|
-
};
|
|
1
|
+
use crate::{pollers::ServerGatewayApis, worker::activities::PendingActivityCancel, TaskToken};
|
|
5
2
|
use futures::StreamExt;
|
|
6
3
|
use std::{
|
|
7
4
|
collections::{hash_map::Entry, HashMap},
|
|
@@ -15,7 +12,7 @@ use temporal_sdk_core_protos::{
|
|
|
15
12
|
use tokio::{
|
|
16
13
|
sync::{
|
|
17
14
|
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
|
18
|
-
Mutex,
|
|
15
|
+
Mutex, Notify,
|
|
19
16
|
},
|
|
20
17
|
task::JoinHandle,
|
|
21
18
|
};
|
|
@@ -27,7 +24,7 @@ pub(crate) struct ActivityHeartbeatManager {
|
|
|
27
24
|
/// Cancellations that have been received when heartbeating are queued here and can be consumed
|
|
28
25
|
/// by [fetch_cancellations]
|
|
29
26
|
incoming_cancels: Mutex<UnboundedReceiver<PendingActivityCancel>>,
|
|
30
|
-
|
|
27
|
+
shutdown_token: CancellationToken,
|
|
31
28
|
/// Used during `shutdown` to await until all inflight requests are sent.
|
|
32
29
|
join_handle: Mutex<Option<JoinHandle<()>>>,
|
|
33
30
|
heartbeat_tx: UnboundedSender<HeartbeatAction>,
|
|
@@ -36,7 +33,10 @@ pub(crate) struct ActivityHeartbeatManager {
|
|
|
36
33
|
#[derive(Debug)]
|
|
37
34
|
enum HeartbeatAction {
|
|
38
35
|
SendHeartbeat(ValidActivityHeartbeat),
|
|
39
|
-
Evict
|
|
36
|
+
Evict {
|
|
37
|
+
token: TaskToken,
|
|
38
|
+
on_complete: Arc<Notify>,
|
|
39
|
+
},
|
|
40
40
|
CompleteReport(TaskToken),
|
|
41
41
|
CompleteThrottle(TaskToken),
|
|
42
42
|
}
|
|
@@ -53,12 +53,31 @@ enum HeartbeatExecutorAction {
|
|
|
53
53
|
/// Heartbeats are throttled for this task token, sleep until duration or wait to be cancelled
|
|
54
54
|
Sleep(TaskToken, Duration, CancellationToken),
|
|
55
55
|
/// Report heartbeat to the server
|
|
56
|
-
Report
|
|
56
|
+
Report {
|
|
57
|
+
task_token: TaskToken,
|
|
58
|
+
details: Vec<common::Payload>,
|
|
59
|
+
on_reported: Option<Arc<Notify>>,
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Errors thrown when heartbeating
|
|
64
|
+
#[derive(thiserror::Error, Debug)]
|
|
65
|
+
pub enum ActivityHeartbeatError {
|
|
66
|
+
/// Heartbeat referenced an activity that we don't think exists. It may have completed already.
|
|
67
|
+
#[error("Heartbeat has been sent for activity that either completed or never started on this worker.")]
|
|
68
|
+
UnknownActivity,
|
|
69
|
+
/// There was a set heartbeat timeout, but it was not parseable. A valid timeout is requried
|
|
70
|
+
/// to heartbeat.
|
|
71
|
+
#[error("Unable to parse activity heartbeat timeout.")]
|
|
72
|
+
InvalidHeartbeatTimeout,
|
|
73
|
+
/// Core is shutting down and thus new heartbeats are not accepted
|
|
74
|
+
#[error("New heartbeat requests are not accepted while shutting down")]
|
|
75
|
+
ShuttingDown,
|
|
57
76
|
}
|
|
58
77
|
|
|
59
|
-
///
|
|
60
|
-
///
|
|
61
|
-
///
|
|
78
|
+
/// Manages activity heartbeating for a worker. Allows sending new heartbeats or requesting and
|
|
79
|
+
/// awaiting for the shutdown. When shutdown is requested, signal gets sent to all processors, which
|
|
80
|
+
/// allows them to complete gracefully.
|
|
62
81
|
impl ActivityHeartbeatManager {
|
|
63
82
|
/// Records a new heartbeat, the first call will result in an immediate call to the server,
|
|
64
83
|
/// while rapid successive calls would accumulate for up to `delay` and then latest heartbeat
|
|
@@ -72,7 +91,7 @@ impl ActivityHeartbeatManager {
|
|
|
72
91
|
hb: ActivityHeartbeat,
|
|
73
92
|
throttle_interval: Duration,
|
|
74
93
|
) -> Result<(), ActivityHeartbeatError> {
|
|
75
|
-
if self.
|
|
94
|
+
if self.shutdown_token.is_cancelled() {
|
|
76
95
|
return Err(ActivityHeartbeatError::ShuttingDown);
|
|
77
96
|
}
|
|
78
97
|
self.heartbeat_tx
|
|
@@ -87,9 +106,15 @@ impl ActivityHeartbeatManager {
|
|
|
87
106
|
}
|
|
88
107
|
|
|
89
108
|
/// Tell the heartbeat manager we are done forever with a certain task, so it may be forgotten.
|
|
109
|
+
/// This will also force-flush the most recently provided details.
|
|
90
110
|
/// Record *should* not be called with the same TaskToken after calling this.
|
|
91
|
-
pub(super) fn evict(&self, task_token: TaskToken) {
|
|
92
|
-
let
|
|
111
|
+
pub(super) async fn evict(&self, task_token: TaskToken) {
|
|
112
|
+
let completed = Arc::new(Notify::new());
|
|
113
|
+
let _ = self.heartbeat_tx.send(HeartbeatAction::Evict {
|
|
114
|
+
token: task_token,
|
|
115
|
+
on_complete: completed.clone(),
|
|
116
|
+
});
|
|
117
|
+
completed.notified().await;
|
|
93
118
|
}
|
|
94
119
|
|
|
95
120
|
/// Returns a future that resolves any time there is a new activity cancel that must be
|
|
@@ -102,7 +127,7 @@ impl ActivityHeartbeatManager {
|
|
|
102
127
|
/// Initiates shutdown procedure by stopping lifecycle loop and awaiting for all in-flight
|
|
103
128
|
/// heartbeat requests to be flushed to the server.
|
|
104
129
|
pub(super) async fn shutdown(&self) {
|
|
105
|
-
let _ = self.
|
|
130
|
+
let _ = self.shutdown_token.cancel();
|
|
106
131
|
let mut handle = self.join_handle.lock().await;
|
|
107
132
|
if let Some(h) = handle.take() {
|
|
108
133
|
h.await.expect("shutdown should exit cleanly");
|
|
@@ -171,7 +196,11 @@ impl HeartbeatStreamState {
|
|
|
171
196
|
throttled_cancellation_token: None,
|
|
172
197
|
};
|
|
173
198
|
e.insert(state);
|
|
174
|
-
Some(HeartbeatExecutorAction::Report
|
|
199
|
+
Some(HeartbeatExecutorAction::Report {
|
|
200
|
+
task_token: hb.task_token,
|
|
201
|
+
details: hb.details,
|
|
202
|
+
on_reported: None,
|
|
203
|
+
})
|
|
175
204
|
}
|
|
176
205
|
Entry::Occupied(mut o) => {
|
|
177
206
|
let state = o.get_mut();
|
|
@@ -207,7 +236,11 @@ impl HeartbeatStreamState {
|
|
|
207
236
|
// Reset the cancellation token and schedule another report
|
|
208
237
|
state.throttled_cancellation_token = None;
|
|
209
238
|
state.last_send_requested = Instant::now();
|
|
210
|
-
Some(HeartbeatExecutorAction::Report
|
|
239
|
+
Some(HeartbeatExecutorAction::Report {
|
|
240
|
+
task_token: tt,
|
|
241
|
+
details,
|
|
242
|
+
on_reported: None,
|
|
243
|
+
})
|
|
211
244
|
} else {
|
|
212
245
|
// Nothing to report, forget this task token
|
|
213
246
|
e.remove();
|
|
@@ -218,15 +251,29 @@ impl HeartbeatStreamState {
|
|
|
218
251
|
}
|
|
219
252
|
}
|
|
220
253
|
|
|
221
|
-
/// Activity should not be tracked anymore, cancel throttle timer if running
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
254
|
+
/// Activity should not be tracked anymore, cancel throttle timer if running.
|
|
255
|
+
///
|
|
256
|
+
/// Will return a report action if there are recorded details present, to ensure we flush the
|
|
257
|
+
/// latest details before we cease tracking this activity.
|
|
258
|
+
fn evict(
|
|
259
|
+
&mut self,
|
|
260
|
+
tt: TaskToken,
|
|
261
|
+
on_complete: Arc<Notify>,
|
|
262
|
+
) -> Option<HeartbeatExecutorAction> {
|
|
263
|
+
if let Some(state) = self.tt_to_state.remove(&tt) {
|
|
264
|
+
if let Some(cancel_tok) = state.throttled_cancellation_token {
|
|
265
|
+
let _ = cancel_tok.cancel();
|
|
266
|
+
}
|
|
267
|
+
if let Some(last_deets) = state.last_recorded_details {
|
|
268
|
+
return Some(HeartbeatExecutorAction::Report {
|
|
269
|
+
task_token: tt,
|
|
270
|
+
details: last_deets,
|
|
271
|
+
on_reported: Some(on_complete),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// Since there's nothing to flush immediately report back that eviction is finished
|
|
276
|
+
on_complete.notify_one();
|
|
230
277
|
None
|
|
231
278
|
}
|
|
232
279
|
}
|
|
@@ -235,14 +282,14 @@ impl ActivityHeartbeatManager {
|
|
|
235
282
|
/// Creates a new instance of an activity heartbeat manager and returns a handle to the user,
|
|
236
283
|
/// which allows to send new heartbeats and initiate the shutdown.
|
|
237
284
|
pub fn new(sg: Arc<impl ServerGatewayApis + Send + Sync + 'static + ?Sized>) -> Self {
|
|
238
|
-
let (heartbeat_stream_state, heartbeat_tx_source,
|
|
285
|
+
let (heartbeat_stream_state, heartbeat_tx_source, shutdown_token) =
|
|
239
286
|
HeartbeatStreamState::new();
|
|
240
287
|
let (cancels_tx, cancels_rx) = unbounded_channel();
|
|
241
288
|
let heartbeat_tx = heartbeat_tx_source.clone();
|
|
242
289
|
|
|
243
290
|
let join_handle = tokio::spawn(
|
|
244
291
|
// The stream of incoming heartbeats uses unfold to carry state across each item in the
|
|
245
|
-
// stream The closure checks if, for any given activity, we should heartbeat or not
|
|
292
|
+
// stream. The closure checks if, for any given activity, we should heartbeat or not
|
|
246
293
|
// depending on its delay and when we last issued a heartbeat for it.
|
|
247
294
|
futures::stream::unfold(heartbeat_stream_state, move |mut hb_states| {
|
|
248
295
|
async move {
|
|
@@ -263,12 +310,13 @@ impl ActivityHeartbeatManager {
|
|
|
263
310
|
HeartbeatAction::SendHeartbeat(hb) => hb_states.record(hb),
|
|
264
311
|
HeartbeatAction::CompleteReport(tt) => hb_states.handle_report_completed(tt),
|
|
265
312
|
HeartbeatAction::CompleteThrottle(tt) => hb_states.handle_throttle_completed(tt),
|
|
266
|
-
HeartbeatAction::Evict
|
|
313
|
+
HeartbeatAction::Evict{ token, on_complete } => hb_states.evict(token, on_complete),
|
|
267
314
|
},
|
|
268
315
|
hb_states,
|
|
269
316
|
))
|
|
270
317
|
}
|
|
271
318
|
})
|
|
319
|
+
// Filters out `None`s
|
|
272
320
|
.filter_map(|opt| async { opt })
|
|
273
321
|
.for_each_concurrent(None, move |action| {
|
|
274
322
|
let heartbeat_tx = heartbeat_tx_source.clone();
|
|
@@ -284,7 +332,7 @@ impl ActivityHeartbeatManager {
|
|
|
284
332
|
},
|
|
285
333
|
};
|
|
286
334
|
}
|
|
287
|
-
HeartbeatExecutorAction::Report
|
|
335
|
+
HeartbeatExecutorAction::Report { task_token: tt, details, on_reported } => {
|
|
288
336
|
match sg
|
|
289
337
|
.record_activity_heartbeat(tt.clone(), details.into_payloads())
|
|
290
338
|
.await
|
|
@@ -301,9 +349,9 @@ impl ActivityHeartbeatManager {
|
|
|
301
349
|
);
|
|
302
350
|
}
|
|
303
351
|
}
|
|
304
|
-
// Send cancels for any activity that learns its workflow already
|
|
305
|
-
// (which is one thing not found implies - other reasons
|
|
306
|
-
// valid).
|
|
352
|
+
// Send cancels for any activity that learns its workflow already
|
|
353
|
+
// finished (which is one thing not found implies - other reasons
|
|
354
|
+
// would seem equally valid).
|
|
307
355
|
Err(s) if s.code() == tonic::Code::NotFound => {
|
|
308
356
|
cancels_tx
|
|
309
357
|
.send(PendingActivityCancel::new(
|
|
@@ -316,6 +364,9 @@ impl ActivityHeartbeatManager {
|
|
|
316
364
|
warn!("Error when recording heartbeat: {:?}", e);
|
|
317
365
|
}
|
|
318
366
|
};
|
|
367
|
+
if let Some(onrep) = on_reported {
|
|
368
|
+
onrep.notify_one();
|
|
369
|
+
}
|
|
319
370
|
let _ = heartbeat_tx.send(HeartbeatAction::CompleteReport(tt));
|
|
320
371
|
}
|
|
321
372
|
}
|
|
@@ -326,7 +377,7 @@ impl ActivityHeartbeatManager {
|
|
|
326
377
|
Self {
|
|
327
378
|
incoming_cancels: Mutex::new(cancels_rx),
|
|
328
379
|
join_handle: Mutex::new(Some(join_handle)),
|
|
329
|
-
|
|
380
|
+
shutdown_token,
|
|
330
381
|
heartbeat_tx,
|
|
331
382
|
}
|
|
332
383
|
}
|
|
@@ -335,8 +386,10 @@ impl ActivityHeartbeatManager {
|
|
|
335
386
|
#[cfg(test)]
|
|
336
387
|
mod test {
|
|
337
388
|
use super::*;
|
|
338
|
-
use crate::
|
|
389
|
+
use crate::test_help::TEST_Q;
|
|
339
390
|
use std::time::Duration;
|
|
391
|
+
|
|
392
|
+
use temporal_client::mocks::mock_gateway;
|
|
340
393
|
use temporal_sdk_core_protos::{
|
|
341
394
|
coresdk::common::Payload,
|
|
342
395
|
temporal::api::workflowservice::v1::RecordActivityTaskHeartbeatResponse,
|
|
@@ -347,7 +400,7 @@ mod test {
|
|
|
347
400
|
/// every 1/2 of the heartbeat timeout.
|
|
348
401
|
#[tokio::test]
|
|
349
402
|
async fn process_heartbeats_and_shutdown() {
|
|
350
|
-
let mut mock_gateway =
|
|
403
|
+
let mut mock_gateway = mock_gateway();
|
|
351
404
|
mock_gateway
|
|
352
405
|
.expect_record_activity_heartbeat()
|
|
353
406
|
.returning(|_, _| Ok(RecordActivityTaskHeartbeatResponse::default()))
|
|
@@ -368,7 +421,7 @@ mod test {
|
|
|
368
421
|
|
|
369
422
|
#[tokio::test]
|
|
370
423
|
async fn send_heartbeats_less_frequently_than_throttle_interval() {
|
|
371
|
-
let mut mock_gateway =
|
|
424
|
+
let mut mock_gateway = mock_gateway();
|
|
372
425
|
mock_gateway
|
|
373
426
|
.expect_record_activity_heartbeat()
|
|
374
427
|
.returning(|_, _| Ok(RecordActivityTaskHeartbeatResponse::default()))
|
|
@@ -388,7 +441,7 @@ mod test {
|
|
|
388
441
|
/// interactions with the server - one immediately and one after 500ms after the throttle_interval.
|
|
389
442
|
#[tokio::test]
|
|
390
443
|
async fn process_tight_loop_and_shutdown() {
|
|
391
|
-
let mut mock_gateway =
|
|
444
|
+
let mut mock_gateway = mock_gateway();
|
|
392
445
|
mock_gateway
|
|
393
446
|
.expect_record_activity_heartbeat()
|
|
394
447
|
.returning(|_, _| Ok(RecordActivityTaskHeartbeatResponse::default()))
|
|
@@ -407,7 +460,7 @@ mod test {
|
|
|
407
460
|
/// This test reports one heartbeat and waits for the throttle_interval to elapse before sending another
|
|
408
461
|
#[tokio::test]
|
|
409
462
|
async fn report_heartbeat_after_timeout() {
|
|
410
|
-
let mut mock_gateway =
|
|
463
|
+
let mut mock_gateway = mock_gateway();
|
|
411
464
|
mock_gateway
|
|
412
465
|
.expect_record_activity_heartbeat()
|
|
413
466
|
.returning(|_, _| Ok(RecordActivityTaskHeartbeatResponse::default()))
|
|
@@ -424,7 +477,7 @@ mod test {
|
|
|
424
477
|
|
|
425
478
|
#[tokio::test]
|
|
426
479
|
async fn evict_works() {
|
|
427
|
-
let mut mock_gateway =
|
|
480
|
+
let mut mock_gateway = mock_gateway();
|
|
428
481
|
mock_gateway
|
|
429
482
|
.expect_record_activity_heartbeat()
|
|
430
483
|
.returning(|_, _| Ok(RecordActivityTaskHeartbeatResponse::default()))
|
|
@@ -434,7 +487,7 @@ mod test {
|
|
|
434
487
|
record_heartbeat(&hm, fake_task_token.clone(), 0, Duration::from_millis(100));
|
|
435
488
|
// Let it propagate
|
|
436
489
|
sleep(Duration::from_millis(10)).await;
|
|
437
|
-
hm.evict(fake_task_token.clone().into());
|
|
490
|
+
hm.evict(fake_task_token.clone().into()).await;
|
|
438
491
|
record_heartbeat(&hm, fake_task_token, 0, Duration::from_millis(100));
|
|
439
492
|
// Let it propagate
|
|
440
493
|
sleep(Duration::from_millis(10)).await;
|
|
@@ -445,7 +498,7 @@ mod test {
|
|
|
445
498
|
/// Recording new heartbeats after shutdown is not allowed, and will result in error.
|
|
446
499
|
#[tokio::test]
|
|
447
500
|
async fn record_after_shutdown() {
|
|
448
|
-
let mut mock_gateway =
|
|
501
|
+
let mut mock_gateway = mock_gateway();
|
|
449
502
|
mock_gateway
|
|
450
503
|
.expect_record_activity_heartbeat()
|
|
451
504
|
.returning(|_, _| Ok(RecordActivityTaskHeartbeatResponse::default()))
|