@temporalio/core-bridge 1.11.2 → 1.11.4
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 +396 -489
- package/Cargo.toml +3 -2
- package/lib/errors.d.ts +2 -0
- package/lib/errors.js +7 -3
- package/lib/errors.js.map +1 -1
- package/lib/index.d.ts +8 -2
- package/lib/index.js.map +1 -1
- package/lib/worker-tuner.d.ts +111 -1
- package/package.json +3 -3
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.github/workflows/per-pr.yml +3 -3
- package/sdk-core/Cargo.toml +0 -1
- package/sdk-core/client/Cargo.toml +1 -2
- package/sdk-core/client/src/lib.rs +21 -13
- package/sdk-core/client/src/metrics.rs +1 -1
- package/sdk-core/client/src/raw.rs +46 -1
- package/sdk-core/core/Cargo.toml +7 -7
- package/sdk-core/core/benches/workflow_replay.rs +1 -1
- package/sdk-core/core/src/abstractions/take_cell.rs +1 -1
- package/sdk-core/core/src/abstractions.rs +98 -10
- package/sdk-core/core/src/core_tests/activity_tasks.rs +8 -2
- package/sdk-core/core/src/core_tests/local_activities.rs +1 -1
- package/sdk-core/core/src/core_tests/mod.rs +3 -3
- package/sdk-core/core/src/core_tests/updates.rs +104 -9
- package/sdk-core/core/src/core_tests/workers.rs +72 -3
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +6 -7
- package/sdk-core/core/src/debug_client.rs +78 -0
- package/sdk-core/core/src/ephemeral_server/mod.rs +15 -5
- package/sdk-core/core/src/lib.rs +30 -4
- package/sdk-core/core/src/pollers/mod.rs +1 -1
- package/sdk-core/core/src/pollers/poll_buffer.rs +7 -7
- package/sdk-core/core/src/replay/mod.rs +4 -4
- package/sdk-core/core/src/telemetry/log_export.rs +2 -2
- package/sdk-core/core/src/telemetry/metrics.rs +69 -1
- package/sdk-core/core/src/telemetry/otel.rs +2 -2
- package/sdk-core/core/src/test_help/mod.rs +3 -3
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +3 -3
- package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +1 -1
- package/sdk-core/core/src/worker/activities/local_activities.rs +68 -24
- package/sdk-core/core/src/worker/activities.rs +26 -15
- package/sdk-core/core/src/worker/client/mocks.rs +10 -4
- package/sdk-core/core/src/worker/client.rs +17 -0
- package/sdk-core/core/src/worker/mod.rs +71 -13
- package/sdk-core/core/src/worker/slot_provider.rs +5 -7
- package/sdk-core/core/src/worker/tuner/fixed_size.rs +4 -3
- package/sdk-core/core/src/worker/tuner/resource_based.rs +171 -32
- package/sdk-core/core/src/worker/tuner.rs +18 -6
- package/sdk-core/core/src/worker/workflow/history_update.rs +43 -13
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +6 -6
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +6 -5
- package/sdk-core/core/src/worker/workflow/managed_run.rs +3 -3
- package/sdk-core/core/src/worker/workflow/mod.rs +13 -7
- package/sdk-core/core/src/worker/workflow/wft_extraction.rs +7 -7
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +2 -2
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +11 -11
- package/sdk-core/core-api/Cargo.toml +1 -0
- package/sdk-core/core-api/src/worker.rs +84 -30
- package/sdk-core/sdk/Cargo.toml +1 -2
- package/sdk-core/sdk/src/lib.rs +1 -1
- package/sdk-core/sdk/src/workflow_context.rs +9 -8
- package/sdk-core/sdk/src/workflow_future.rs +19 -14
- package/sdk-core/sdk-core-protos/Cargo.toml +2 -0
- package/sdk-core/sdk-core-protos/build.rs +6 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +1 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +3207 -158
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +2934 -118
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/activity/v1/message.proto +67 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +47 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +6 -7
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/reset.proto +5 -3
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +3 -3
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/update.proto +14 -13
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +1 -3
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +22 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +13 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +26 -6
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/schedule/v1/message.proto +5 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +6 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +46 -12
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/update/v1/message.proto +18 -19
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +27 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +192 -19
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +279 -12
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/common/common.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/core_interface.proto +17 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +1 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +30 -6
- package/sdk-core/test-utils/Cargo.toml +1 -2
- package/sdk-core/test-utils/src/lib.rs +2 -2
- package/sdk-core/tests/heavy_tests.rs +1 -1
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +2 -2
- package/sdk-core/tests/integ_tests/metrics_tests.rs +144 -7
- package/sdk-core/tests/integ_tests/queries_tests.rs +1 -1
- package/sdk-core/tests/integ_tests/update_tests.rs +109 -5
- package/sdk-core/tests/integ_tests/worker_tests.rs +44 -8
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests.rs +3 -2
- package/src/conversions/slot_supplier_bridge.rs +287 -0
- package/src/conversions.rs +23 -15
- package/src/helpers.rs +35 -1
- package/src/runtime.rs +7 -3
- package/src/worker.rs +1 -1
- package/ts/errors.ts +9 -2
- package/ts/index.ts +19 -4
- package/ts/worker-tuner.ts +123 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/.gitmodules +0 -3
package/sdk-core/core/src/lib.rs
CHANGED
|
@@ -12,6 +12,8 @@ extern crate tracing;
|
|
|
12
12
|
extern crate core;
|
|
13
13
|
|
|
14
14
|
mod abstractions;
|
|
15
|
+
#[cfg(feature = "debug-plugin")]
|
|
16
|
+
pub mod debug_client;
|
|
15
17
|
#[cfg(feature = "ephemeral-server")]
|
|
16
18
|
pub mod ephemeral_server;
|
|
17
19
|
mod internal_flags;
|
|
@@ -54,7 +56,7 @@ use crate::{
|
|
|
54
56
|
worker::client::WorkerClientBag,
|
|
55
57
|
};
|
|
56
58
|
use anyhow::bail;
|
|
57
|
-
use
|
|
59
|
+
use futures_util::Stream;
|
|
58
60
|
use std::sync::Arc;
|
|
59
61
|
use temporal_client::{ConfiguredClient, TemporalServiceClientWithMetrics};
|
|
60
62
|
use temporal_sdk_core_api::{
|
|
@@ -198,6 +200,23 @@ pub struct CoreRuntime {
|
|
|
198
200
|
runtime_handle: tokio::runtime::Handle,
|
|
199
201
|
}
|
|
200
202
|
|
|
203
|
+
/// Wraps a [tokio::runtime::Builder] to allow layering multiple on_thread_start functions
|
|
204
|
+
pub struct TokioRuntimeBuilder<F> {
|
|
205
|
+
/// The underlying tokio runtime builder
|
|
206
|
+
pub inner: tokio::runtime::Builder,
|
|
207
|
+
/// A function to be called when setting the runtime builder's on thread start
|
|
208
|
+
pub lang_on_thread_start: Option<F>,
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
impl Default for TokioRuntimeBuilder<Box<dyn Fn() + Send + Sync>> {
|
|
212
|
+
fn default() -> Self {
|
|
213
|
+
TokioRuntimeBuilder {
|
|
214
|
+
inner: tokio::runtime::Builder::new_multi_thread(),
|
|
215
|
+
lang_on_thread_start: None,
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
201
220
|
impl CoreRuntime {
|
|
202
221
|
/// Create a new core runtime with the provided telemetry options and tokio runtime builder.
|
|
203
222
|
/// Also initialize telemetry for the thread this is being called on.
|
|
@@ -212,18 +231,25 @@ impl CoreRuntime {
|
|
|
212
231
|
/// # Panics
|
|
213
232
|
/// If a tokio runtime has already been initialized. To re-use an existing runtime, call
|
|
214
233
|
/// [CoreRuntime::new_assume_tokio].
|
|
215
|
-
pub fn new(
|
|
234
|
+
pub fn new<F>(
|
|
216
235
|
telemetry_options: TelemetryOptions,
|
|
217
|
-
mut tokio_builder:
|
|
218
|
-
) -> Result<Self, anyhow::Error>
|
|
236
|
+
mut tokio_builder: TokioRuntimeBuilder<F>,
|
|
237
|
+
) -> Result<Self, anyhow::Error>
|
|
238
|
+
where
|
|
239
|
+
F: Fn() + Send + Sync + 'static,
|
|
240
|
+
{
|
|
219
241
|
let telemetry = telemetry_init(telemetry_options)?;
|
|
220
242
|
let subscriber = telemetry.trace_subscriber();
|
|
221
243
|
let runtime = tokio_builder
|
|
244
|
+
.inner
|
|
222
245
|
.enable_all()
|
|
223
246
|
.on_thread_start(move || {
|
|
224
247
|
if let Some(sub) = subscriber.as_ref() {
|
|
225
248
|
set_trace_subscriber_for_current_thread(sub.clone());
|
|
226
249
|
}
|
|
250
|
+
if let Some(lang_on_thread_start) = tokio_builder.lang_on_thread_start.as_ref() {
|
|
251
|
+
lang_on_thread_start();
|
|
252
|
+
}
|
|
227
253
|
})
|
|
228
254
|
.build()?;
|
|
229
255
|
let _rg = runtime.enter();
|
|
@@ -14,7 +14,7 @@ use temporal_sdk_core_protos::temporal::api::workflowservice::v1::{
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
#[cfg(test)]
|
|
17
|
-
use
|
|
17
|
+
use futures_util::Future;
|
|
18
18
|
#[cfg(test)]
|
|
19
19
|
pub(crate) use poll_buffer::MockPermittedPollBuffer;
|
|
20
20
|
use temporal_sdk_core_api::worker::{ActivitySlotKind, WorkflowSlotKind};
|
|
@@ -3,8 +3,7 @@ use crate::{
|
|
|
3
3
|
pollers::{self, Poller},
|
|
4
4
|
worker::client::WorkerClient,
|
|
5
5
|
};
|
|
6
|
-
use
|
|
7
|
-
use futures_util::{future::BoxFuture, FutureExt};
|
|
6
|
+
use futures_util::{future::BoxFuture, stream::FuturesUnordered, FutureExt, StreamExt};
|
|
8
7
|
use governor::{Quota, RateLimiter};
|
|
9
8
|
use std::{
|
|
10
9
|
fmt::Debug,
|
|
@@ -73,7 +72,7 @@ where
|
|
|
73
72
|
{
|
|
74
73
|
pub(crate) fn new<FT, DelayFut>(
|
|
75
74
|
poll_fn: impl Fn() -> FT + Send + Sync + 'static,
|
|
76
|
-
permit_dealer:
|
|
75
|
+
permit_dealer: MeteredPermitDealer<SK>,
|
|
77
76
|
max_pollers: usize,
|
|
78
77
|
shutdown: CancellationToken,
|
|
79
78
|
num_pollers_handler: Option<impl Fn(usize) + Send + Sync + 'static>,
|
|
@@ -85,6 +84,7 @@ where
|
|
|
85
84
|
{
|
|
86
85
|
let (tx, rx) = unbounded_channel();
|
|
87
86
|
let (starter, wait_for_start) = broadcast::channel(1);
|
|
87
|
+
let permit_dealer = Arc::new(permit_dealer);
|
|
88
88
|
let active_pollers = Arc::new(AtomicUsize::new(0));
|
|
89
89
|
let join_handles = FuturesUnordered::new();
|
|
90
90
|
let pf = Arc::new(poll_fn);
|
|
@@ -243,7 +243,7 @@ pub(crate) fn new_workflow_task_buffer(
|
|
|
243
243
|
client: Arc<dyn WorkerClient>,
|
|
244
244
|
task_queue: TaskQueue,
|
|
245
245
|
concurrent_pollers: usize,
|
|
246
|
-
permit_dealer:
|
|
246
|
+
permit_dealer: MeteredPermitDealer<WorkflowSlotKind>,
|
|
247
247
|
shutdown: CancellationToken,
|
|
248
248
|
num_pollers_handler: Option<impl Fn(usize) + Send + Sync + 'static>,
|
|
249
249
|
) -> PollWorkflowTaskBuffer {
|
|
@@ -268,7 +268,7 @@ pub(crate) fn new_activity_task_buffer(
|
|
|
268
268
|
client: Arc<dyn WorkerClient>,
|
|
269
269
|
task_queue: String,
|
|
270
270
|
concurrent_pollers: usize,
|
|
271
|
-
semaphore:
|
|
271
|
+
semaphore: MeteredPermitDealer<ActivitySlotKind>,
|
|
272
272
|
max_tps: Option<f64>,
|
|
273
273
|
shutdown: CancellationToken,
|
|
274
274
|
num_pollers_handler: Option<impl Fn(usize) + Send + Sync + 'static>,
|
|
@@ -337,7 +337,7 @@ mod tests {
|
|
|
337
337
|
abstractions::tests::fixed_size_permit_dealer,
|
|
338
338
|
worker::client::mocks::mock_manual_workflow_client,
|
|
339
339
|
};
|
|
340
|
-
use
|
|
340
|
+
use futures_util::FutureExt;
|
|
341
341
|
use std::time::Duration;
|
|
342
342
|
use temporal_sdk_core_protos::temporal::api::enums::v1::TaskQueueKind;
|
|
343
343
|
use tokio::{select, sync::mpsc::channel};
|
|
@@ -364,7 +364,7 @@ mod tests {
|
|
|
364
364
|
normal_name: "".to_string(),
|
|
365
365
|
},
|
|
366
366
|
1,
|
|
367
|
-
|
|
367
|
+
fixed_size_permit_dealer(10),
|
|
368
368
|
CancellationToken::new(),
|
|
369
369
|
None::<fn(usize)>,
|
|
370
370
|
);
|
|
@@ -9,9 +9,9 @@ use crate::{
|
|
|
9
9
|
},
|
|
10
10
|
Worker,
|
|
11
11
|
};
|
|
12
|
-
use
|
|
13
|
-
use once_cell::sync::OnceCell;
|
|
12
|
+
use futures_util::{FutureExt, Stream, StreamExt};
|
|
14
13
|
use parking_lot::Mutex;
|
|
14
|
+
use std::sync::OnceLock;
|
|
15
15
|
use std::{
|
|
16
16
|
pin::Pin,
|
|
17
17
|
sync::Arc,
|
|
@@ -179,7 +179,7 @@ impl Stream for HistoryFeederStream {
|
|
|
179
179
|
pub(crate) struct Historator {
|
|
180
180
|
iter: Pin<Box<dyn Stream<Item = HistoryForReplay> + Send>>,
|
|
181
181
|
allow_stream: UnboundedReceiverStream<String>,
|
|
182
|
-
worker_closer: Arc<
|
|
182
|
+
worker_closer: Arc<OnceLock<CancellationToken>>,
|
|
183
183
|
dat: Arc<Mutex<HistoratorDat>>,
|
|
184
184
|
replay_done_tx: UnboundedSender<String>,
|
|
185
185
|
}
|
|
@@ -192,7 +192,7 @@ impl Historator {
|
|
|
192
192
|
Self {
|
|
193
193
|
iter: Box::pin(histories.fuse()),
|
|
194
194
|
allow_stream: UnboundedReceiverStream::new(replay_done_rx),
|
|
195
|
-
worker_closer: Arc::new(
|
|
195
|
+
worker_closer: Arc::new(OnceLock::new()),
|
|
196
196
|
dat,
|
|
197
197
|
replay_done_tx,
|
|
198
198
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
use
|
|
1
|
+
use futures_channel::mpsc::{channel, Receiver, Sender};
|
|
2
2
|
use parking_lot::Mutex;
|
|
3
3
|
use ringbuf::{consumer::Consumer, producer::Producer, traits::Split, HeapRb};
|
|
4
4
|
use std::{collections::HashMap, fmt, sync::Arc, time::SystemTime};
|
|
@@ -219,7 +219,7 @@ mod tests {
|
|
|
219
219
|
telemetry::{construct_filter_string, CoreLogStreamConsumer},
|
|
220
220
|
telemetry_init,
|
|
221
221
|
};
|
|
222
|
-
use
|
|
222
|
+
use futures_util::stream::StreamExt;
|
|
223
223
|
use std::{
|
|
224
224
|
fmt,
|
|
225
225
|
sync::{Arc, Mutex},
|
|
@@ -42,6 +42,12 @@ struct Instruments {
|
|
|
42
42
|
act_execution_failed: Arc<dyn Counter>,
|
|
43
43
|
act_sched_to_start_latency: Arc<dyn HistogramDuration>,
|
|
44
44
|
act_exec_latency: Arc<dyn HistogramDuration>,
|
|
45
|
+
act_exec_succeeded_latency: Arc<dyn HistogramDuration>,
|
|
46
|
+
la_execution_cancelled: Arc<dyn Counter>,
|
|
47
|
+
la_execution_failed: Arc<dyn Counter>,
|
|
48
|
+
la_exec_latency: Arc<dyn HistogramDuration>,
|
|
49
|
+
la_exec_succeeded_latency: Arc<dyn HistogramDuration>,
|
|
50
|
+
la_total: Arc<dyn Counter>,
|
|
45
51
|
worker_registered: Arc<dyn Counter>,
|
|
46
52
|
num_pollers: Arc<dyn Gauge>,
|
|
47
53
|
task_slots_available: Arc<dyn Gauge>,
|
|
@@ -177,6 +183,13 @@ impl MetricsContext {
|
|
|
177
183
|
self.instruments.act_execution_failed.add(1, &self.kvs);
|
|
178
184
|
}
|
|
179
185
|
|
|
186
|
+
/// Record end-to-end (sched-to-complete) time for successful activity executions
|
|
187
|
+
pub(crate) fn act_execution_succeeded(&self, dur: Duration) {
|
|
188
|
+
self.instruments
|
|
189
|
+
.act_exec_succeeded_latency
|
|
190
|
+
.record(dur, &self.kvs);
|
|
191
|
+
}
|
|
192
|
+
|
|
180
193
|
/// Record activity task schedule to start time in millis
|
|
181
194
|
pub(crate) fn act_sched_to_start_latency(&self, dur: Duration) {
|
|
182
195
|
self.instruments
|
|
@@ -190,6 +203,28 @@ impl MetricsContext {
|
|
|
190
203
|
self.instruments.act_exec_latency.record(dur, &self.kvs);
|
|
191
204
|
}
|
|
192
205
|
|
|
206
|
+
pub(crate) fn la_execution_cancelled(&self) {
|
|
207
|
+
self.instruments.la_execution_cancelled.add(1, &self.kvs);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
pub(crate) fn la_execution_failed(&self) {
|
|
211
|
+
self.instruments.la_execution_failed.add(1, &self.kvs);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
pub(crate) fn la_exec_latency(&self, dur: Duration) {
|
|
215
|
+
self.instruments.la_exec_latency.record(dur, &self.kvs);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
pub(crate) fn la_exec_succeeded_latency(&self, dur: Duration) {
|
|
219
|
+
self.instruments
|
|
220
|
+
.la_exec_succeeded_latency
|
|
221
|
+
.record(dur, &self.kvs);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
pub(crate) fn la_executed(&self) {
|
|
225
|
+
self.instruments.la_total.add(1, &self.kvs);
|
|
226
|
+
}
|
|
227
|
+
|
|
193
228
|
/// A worker was registered
|
|
194
229
|
pub(crate) fn worker_registered(&self) {
|
|
195
230
|
self.instruments.worker_registered.add(1, &self.kvs);
|
|
@@ -316,6 +351,39 @@ impl Instruments {
|
|
|
316
351
|
unit: "duration".into(),
|
|
317
352
|
description: "Histogram of activity execution latencies".into(),
|
|
318
353
|
}),
|
|
354
|
+
act_exec_succeeded_latency: meter.histogram_duration(MetricParameters {
|
|
355
|
+
name: "activity_succeed_endtoend_latency".into(),
|
|
356
|
+
unit: "duration".into(),
|
|
357
|
+
description: "Histogram of activity execution latencies for successful activities"
|
|
358
|
+
.into(),
|
|
359
|
+
}),
|
|
360
|
+
la_execution_cancelled: meter.counter(MetricParameters {
|
|
361
|
+
name: "local_activity_execution_cancelled".into(),
|
|
362
|
+
description: "Count of local activity executions that were cancelled".into(),
|
|
363
|
+
unit: "".into(),
|
|
364
|
+
}),
|
|
365
|
+
la_execution_failed: meter.counter(MetricParameters {
|
|
366
|
+
name: "local_activity_execution_failed".into(),
|
|
367
|
+
description: "Count of local activity executions that failed".into(),
|
|
368
|
+
unit: "".into(),
|
|
369
|
+
}),
|
|
370
|
+
la_exec_latency: meter.histogram_duration(MetricParameters {
|
|
371
|
+
name: "local_activity_execution_latency".into(),
|
|
372
|
+
unit: "duration".into(),
|
|
373
|
+
description: "Histogram of local activity execution latencies".into(),
|
|
374
|
+
}),
|
|
375
|
+
la_exec_succeeded_latency: meter.histogram_duration(MetricParameters {
|
|
376
|
+
name: "local_activity_succeed_endtoend_latency".into(),
|
|
377
|
+
unit: "duration".into(),
|
|
378
|
+
description:
|
|
379
|
+
"Histogram of local activity execution latencies for successful local activities"
|
|
380
|
+
.into(),
|
|
381
|
+
}),
|
|
382
|
+
la_total: meter.counter(MetricParameters {
|
|
383
|
+
name: "local_activity_total".into(),
|
|
384
|
+
description: "Count of local activities executed".into(),
|
|
385
|
+
unit: "".into(),
|
|
386
|
+
}),
|
|
319
387
|
// name kept as worker start for compat with old sdk / what users expect
|
|
320
388
|
worker_registered: meter.counter(MetricParameters {
|
|
321
389
|
name: "worker_start".into(),
|
|
@@ -807,7 +875,7 @@ mod tests {
|
|
|
807
875
|
a1.set(Arc::new(DummyCustomAttrs(1))).unwrap();
|
|
808
876
|
// Verify all metrics are created. This number will need to get updated any time a metric
|
|
809
877
|
// is added.
|
|
810
|
-
let num_metrics =
|
|
878
|
+
let num_metrics = 30;
|
|
811
879
|
#[allow(clippy::needless_range_loop)] // Sorry clippy, this reads easier.
|
|
812
880
|
for metric_num in 1..=num_metrics {
|
|
813
881
|
let hole = assert_matches!(&events[metric_num],
|
|
@@ -335,9 +335,9 @@ impl GaugeF64 for MemoryGauge<f64> {
|
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
fn default_resource_instance() -> &'static Resource {
|
|
338
|
-
use
|
|
338
|
+
use std::sync::OnceLock;
|
|
339
339
|
|
|
340
|
-
static INSTANCE:
|
|
340
|
+
static INSTANCE: OnceLock<Resource> = OnceLock::new();
|
|
341
341
|
INSTANCE.get_or_init(|| {
|
|
342
342
|
let resource = Resource::default();
|
|
343
343
|
if resource.get(Key::from("service.name")) == Some(Value::from("unknown_service")) {
|
|
@@ -15,7 +15,7 @@ use crate::{
|
|
|
15
15
|
};
|
|
16
16
|
use async_trait::async_trait;
|
|
17
17
|
use bimap::BiMap;
|
|
18
|
-
use
|
|
18
|
+
use futures_util::{future::BoxFuture, stream, stream::BoxStream, FutureExt, Stream, StreamExt};
|
|
19
19
|
use mockall::TimesRange;
|
|
20
20
|
use parking_lot::RwLock;
|
|
21
21
|
use std::{
|
|
@@ -1014,9 +1014,9 @@ macro_rules! job_assert {
|
|
|
1014
1014
|
#[macro_export]
|
|
1015
1015
|
macro_rules! advance_fut {
|
|
1016
1016
|
($fut:ident) => {
|
|
1017
|
-
::
|
|
1017
|
+
::futures_util::pin_mut!($fut);
|
|
1018
1018
|
{
|
|
1019
|
-
let waker = ::
|
|
1019
|
+
let waker = ::futures_util::task::noop_waker();
|
|
1020
1020
|
let mut cx = core::task::Context::from_waker(&waker);
|
|
1021
1021
|
for _ in 0..10 {
|
|
1022
1022
|
assert_matches!($fut.poll_unpin(&mut cx), core::task::Poll::Pending);
|
|
@@ -3,7 +3,7 @@ use crate::{
|
|
|
3
3
|
worker::{activities::PendingActivityCancel, client::WorkerClient},
|
|
4
4
|
TaskToken,
|
|
5
5
|
};
|
|
6
|
-
use
|
|
6
|
+
use futures_util::StreamExt;
|
|
7
7
|
use std::{
|
|
8
8
|
collections::{hash_map::Entry, HashMap},
|
|
9
9
|
sync::Arc,
|
|
@@ -94,7 +94,7 @@ impl ActivityHeartbeatManager {
|
|
|
94
94
|
// The stream of incoming heartbeats uses unfold to carry state across each item in the
|
|
95
95
|
// stream. The closure checks if, for any given activity, we should heartbeat or not
|
|
96
96
|
// depending on its delay and when we last issued a heartbeat for it.
|
|
97
|
-
|
|
97
|
+
futures_util::stream::unfold(heartbeat_stream_state, move |mut hb_states| {
|
|
98
98
|
async move {
|
|
99
99
|
let hb = tokio::select! {
|
|
100
100
|
biased;
|
|
@@ -140,7 +140,7 @@ impl ActivityHeartbeatManager {
|
|
|
140
140
|
.record_activity_heartbeat(tt.clone(), details.into_payloads())
|
|
141
141
|
.await
|
|
142
142
|
{
|
|
143
|
-
Ok(RecordActivityTaskHeartbeatResponse { cancel_requested }) => {
|
|
143
|
+
Ok(RecordActivityTaskHeartbeatResponse { cancel_requested, activity_paused: _ }) => {
|
|
144
144
|
if cancel_requested {
|
|
145
145
|
cancels_tx
|
|
146
146
|
.send(PendingActivityCancel::new(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
use crate::{pollers::BoxedActPoller, worker::activities::PermittedTqResp, MetricsContext};
|
|
2
|
-
use
|
|
2
|
+
use futures_util::{stream, Stream};
|
|
3
3
|
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::PollActivityTaskQueueResponse;
|
|
4
4
|
use tokio::select;
|
|
5
5
|
use tokio_util::sync::CancellationToken;
|
|
@@ -2,25 +2,27 @@ use crate::{
|
|
|
2
2
|
abstractions::{dbg_panic, MeteredPermitDealer, OwnedMeteredSemPermit, UsedMeteredSemPermit},
|
|
3
3
|
protosext::ValidScheduleLA,
|
|
4
4
|
retry_logic::RetryPolicyExt,
|
|
5
|
+
telemetry::metrics::{activity_type, workflow_type},
|
|
5
6
|
worker::workflow::HeartbeatTimeoutMsg,
|
|
6
7
|
MetricsContext, TaskToken,
|
|
7
8
|
};
|
|
8
|
-
use
|
|
9
|
-
|
|
9
|
+
use futures_util::{
|
|
10
|
+
future, future::AbortRegistration, stream, stream::BoxStream, Stream, StreamExt,
|
|
11
|
+
};
|
|
10
12
|
use parking_lot::{Mutex, MutexGuard};
|
|
11
13
|
use std::{
|
|
12
14
|
collections::{hash_map::Entry, HashMap},
|
|
13
15
|
fmt::{Debug, Formatter},
|
|
14
16
|
pin::Pin,
|
|
15
|
-
sync::Arc,
|
|
16
17
|
task::{Context, Poll},
|
|
17
18
|
time::{Duration, Instant, SystemTime},
|
|
18
19
|
};
|
|
19
|
-
use temporal_sdk_core_api::worker::
|
|
20
|
+
use temporal_sdk_core_api::worker::LocalActivitySlotKind;
|
|
20
21
|
use temporal_sdk_core_protos::{
|
|
21
22
|
coresdk::{
|
|
22
23
|
activity_result::{Cancellation, Failure as ActFail, Success},
|
|
23
24
|
activity_task::{activity_task, ActivityCancelReason, ActivityTask, Cancel, Start},
|
|
25
|
+
LocalActivitySlotInfo,
|
|
24
26
|
},
|
|
25
27
|
temporal::api::{
|
|
26
28
|
common::v1::WorkflowExecution,
|
|
@@ -173,6 +175,9 @@ pub(crate) struct LocalActivityManager {
|
|
|
173
175
|
rcvs: tokio::sync::Mutex<RcvChans>,
|
|
174
176
|
shutdown_complete_tok: CancellationToken,
|
|
175
177
|
dat: Mutex<LAMData>,
|
|
178
|
+
/// Note that these metrics do *not* include the `worker_type` label, as every metric
|
|
179
|
+
/// emitted here is already specific to local activities via the metric name.
|
|
180
|
+
metrics: MetricsContext,
|
|
176
181
|
}
|
|
177
182
|
|
|
178
183
|
struct LocalActivityInfo {
|
|
@@ -205,20 +210,19 @@ impl LAMData {
|
|
|
205
210
|
|
|
206
211
|
impl LocalActivityManager {
|
|
207
212
|
pub(crate) fn new(
|
|
208
|
-
slot_supplier: Arc<dyn SlotSupplier<SlotKind = LocalActivitySlotKind> + Send + Sync>,
|
|
209
213
|
namespace: String,
|
|
214
|
+
permit_dealer: MeteredPermitDealer<LocalActivitySlotKind>,
|
|
210
215
|
heartbeat_timeout_tx: UnboundedSender<HeartbeatTimeoutMsg>,
|
|
211
216
|
metrics_context: MetricsContext,
|
|
212
217
|
) -> Self {
|
|
213
218
|
let (act_req_tx, act_req_rx) = unbounded_channel();
|
|
214
219
|
let (cancels_req_tx, cancels_req_rx) = unbounded_channel();
|
|
215
220
|
let shutdown_complete_tok = CancellationToken::new();
|
|
216
|
-
let semaphore = MeteredPermitDealer::new(slot_supplier, metrics_context, None);
|
|
217
221
|
Self {
|
|
218
222
|
namespace,
|
|
219
223
|
rcvs: tokio::sync::Mutex::new(RcvChans::new(
|
|
220
224
|
act_req_rx,
|
|
221
|
-
|
|
225
|
+
permit_dealer,
|
|
222
226
|
cancels_req_rx,
|
|
223
227
|
shutdown_complete_tok.clone(),
|
|
224
228
|
)),
|
|
@@ -233,16 +237,28 @@ impl LocalActivityManager {
|
|
|
233
237
|
next_tt_num: 0,
|
|
234
238
|
}),
|
|
235
239
|
workflows_have_shut_down: Default::default(),
|
|
240
|
+
metrics: metrics_context,
|
|
236
241
|
}
|
|
237
242
|
}
|
|
238
243
|
|
|
239
244
|
#[cfg(test)]
|
|
240
245
|
fn test(max_concurrent: usize) -> Self {
|
|
241
246
|
use crate::worker::tuner::FixedSizeSlotSupplier;
|
|
247
|
+
use std::sync::Arc;
|
|
242
248
|
|
|
243
249
|
let ss = Arc::new(FixedSizeSlotSupplier::new(max_concurrent));
|
|
244
250
|
let (hb_tx, _hb_rx) = unbounded_channel();
|
|
245
|
-
Self::new(
|
|
251
|
+
Self::new(
|
|
252
|
+
"fake_ns".to_string(),
|
|
253
|
+
MeteredPermitDealer::new(
|
|
254
|
+
ss,
|
|
255
|
+
MetricsContext::no_op(),
|
|
256
|
+
None,
|
|
257
|
+
Arc::new(Default::default()),
|
|
258
|
+
),
|
|
259
|
+
hb_tx,
|
|
260
|
+
MetricsContext::no_op(),
|
|
261
|
+
)
|
|
246
262
|
}
|
|
247
263
|
|
|
248
264
|
#[cfg(test)]
|
|
@@ -473,12 +489,18 @@ impl LocalActivityManager {
|
|
|
473
489
|
dispatch_time: Instant::now(),
|
|
474
490
|
attempt,
|
|
475
491
|
_permit: permit.into_used(LocalActivitySlotInfo {
|
|
476
|
-
activity_type: new_la.workflow_type.
|
|
492
|
+
activity_type: new_la.workflow_type.clone(),
|
|
477
493
|
}),
|
|
478
494
|
},
|
|
479
495
|
);
|
|
480
496
|
|
|
481
497
|
let (schedule_to_close, start_to_close) = sa.close_timeouts.into_sched_and_start();
|
|
498
|
+
self.metrics
|
|
499
|
+
.with_new_attrs([
|
|
500
|
+
activity_type(sa.activity_type.clone()),
|
|
501
|
+
workflow_type(new_la.workflow_type.clone()),
|
|
502
|
+
])
|
|
503
|
+
.la_executed();
|
|
482
504
|
Some(NextPendingLAAction::Dispatch(ActivityTask {
|
|
483
505
|
task_token: tt.0,
|
|
484
506
|
variant: Some(activity_task::Variant::Start(Start {
|
|
@@ -500,9 +522,7 @@ impl LocalActivityManager {
|
|
|
500
522
|
.ok(),
|
|
501
523
|
start_to_close_timeout: start_to_close
|
|
502
524
|
.or(schedule_to_close)
|
|
503
|
-
.
|
|
504
|
-
.try_into()
|
|
505
|
-
.ok(),
|
|
525
|
+
.and_then(|t| t.try_into().ok()),
|
|
506
526
|
heartbeat_timeout: None,
|
|
507
527
|
retry_policy: Some(sa.retry_policy),
|
|
508
528
|
is_local: true,
|
|
@@ -536,6 +556,11 @@ impl LocalActivityManager {
|
|
|
536
556
|
}
|
|
537
557
|
}
|
|
538
558
|
|
|
559
|
+
let la_metrics = self.metrics.with_new_attrs([
|
|
560
|
+
activity_type(info.la_info.schedule_cmd.activity_type.clone()),
|
|
561
|
+
workflow_type(info.la_info.workflow_type.clone()),
|
|
562
|
+
]);
|
|
563
|
+
|
|
539
564
|
enum Outcome {
|
|
540
565
|
FailurePath { backoff: Option<Duration> },
|
|
541
566
|
JustReport,
|
|
@@ -553,31 +578,48 @@ impl LocalActivityManager {
|
|
|
553
578
|
}
|
|
554
579
|
|
|
555
580
|
let mut is_timeout = false;
|
|
581
|
+
let runtime = info.dispatch_time.elapsed();
|
|
582
|
+
la_metrics.la_exec_latency(runtime);
|
|
556
583
|
let outcome = match &status {
|
|
557
|
-
LocalActivityExecutionResult::Failed(fail) =>
|
|
558
|
-
|
|
559
|
-
},
|
|
560
|
-
LocalActivityExecutionResult::TimedOut(fail)
|
|
561
|
-
if matches!(status.get_timeout_type(), Some(TimeoutType::StartToClose)) =>
|
|
562
|
-
{
|
|
563
|
-
// Start to close timeouts are retryable, other timeout types aren't.
|
|
564
|
-
is_timeout = true;
|
|
584
|
+
LocalActivityExecutionResult::Failed(fail) => {
|
|
585
|
+
la_metrics.la_execution_failed();
|
|
565
586
|
Outcome::FailurePath {
|
|
566
587
|
backoff: calc_backoff!(fail),
|
|
567
588
|
}
|
|
568
589
|
}
|
|
569
|
-
LocalActivityExecutionResult::TimedOut(
|
|
590
|
+
LocalActivityExecutionResult::TimedOut(fail) => {
|
|
591
|
+
la_metrics.la_execution_failed();
|
|
570
592
|
is_timeout = true;
|
|
593
|
+
// Start to close timeouts are retryable, other timeout types aren't.
|
|
594
|
+
if matches!(status.get_timeout_type(), Some(TimeoutType::StartToClose)) {
|
|
595
|
+
Outcome::FailurePath {
|
|
596
|
+
backoff: calc_backoff!(fail),
|
|
597
|
+
}
|
|
598
|
+
} else {
|
|
599
|
+
Outcome::JustReport
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
LocalActivityExecutionResult::Completed(_) => {
|
|
603
|
+
if let Some(rt) = info
|
|
604
|
+
.la_info
|
|
605
|
+
.schedule_cmd
|
|
606
|
+
.original_schedule_time
|
|
607
|
+
.and_then(|t| t.elapsed().ok())
|
|
608
|
+
{
|
|
609
|
+
la_metrics.la_exec_succeeded_latency(rt);
|
|
610
|
+
}
|
|
611
|
+
Outcome::JustReport
|
|
612
|
+
}
|
|
613
|
+
LocalActivityExecutionResult::Cancelled { .. } => {
|
|
614
|
+
la_metrics.la_execution_cancelled();
|
|
571
615
|
Outcome::JustReport
|
|
572
616
|
}
|
|
573
|
-
LocalActivityExecutionResult::Completed(_)
|
|
574
|
-
| LocalActivityExecutionResult::Cancelled { .. } => Outcome::JustReport,
|
|
575
617
|
};
|
|
576
618
|
|
|
577
619
|
let mut resolution = LocalActivityResolution {
|
|
578
620
|
seq: info.la_info.schedule_cmd.seq,
|
|
579
621
|
result: status,
|
|
580
|
-
runtime
|
|
622
|
+
runtime,
|
|
581
623
|
attempt: info.attempt,
|
|
582
624
|
backoff: None,
|
|
583
625
|
original_schedule_time: info.la_info.schedule_cmd.original_schedule_time,
|
|
@@ -692,6 +734,8 @@ impl LocalActivityManager {
|
|
|
692
734
|
while !self.set_shutdown_complete_if_ready(&mut self.dat.lock()) {
|
|
693
735
|
self.complete_notify.notified().await;
|
|
694
736
|
}
|
|
737
|
+
// This makes sure we drop any permits that might be held inside the stream
|
|
738
|
+
self.rcvs.lock().await.inner = stream::empty().boxed();
|
|
695
739
|
}
|
|
696
740
|
|
|
697
741
|
/// Try to close the activity stream as soon as worker shutdown is initiated. This is required
|