@temporalio/core-bridge 1.9.2 → 1.10.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 +754 -473
- package/Cargo.toml +3 -3
- package/lib/index.d.ts +33 -2
- package/lib/index.js.map +1 -1
- package/package.json +4 -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/scripts/build.js +4 -3
- package/sdk-core/.cargo/config.toml +2 -4
- package/sdk-core/.github/workflows/heavy.yml +1 -1
- package/sdk-core/.github/workflows/per-pr.yml +6 -4
- package/sdk-core/Cargo.toml +10 -3
- package/sdk-core/README.md +4 -6
- package/sdk-core/client/Cargo.toml +13 -5
- package/sdk-core/client/src/lib.rs +123 -34
- package/sdk-core/client/src/metrics.rs +70 -18
- package/sdk-core/client/src/proxy.rs +85 -0
- package/sdk-core/client/src/raw.rs +67 -5
- package/sdk-core/client/src/worker_registry/mod.rs +5 -3
- package/sdk-core/client/src/workflow_handle/mod.rs +3 -1
- package/sdk-core/core/Cargo.toml +31 -37
- package/sdk-core/core/src/abstractions/take_cell.rs +3 -3
- package/sdk-core/core/src/abstractions.rs +176 -108
- package/sdk-core/core/src/core_tests/activity_tasks.rs +4 -13
- package/sdk-core/core/src/core_tests/determinism.rs +2 -1
- package/sdk-core/core/src/core_tests/local_activities.rs +3 -3
- package/sdk-core/core/src/core_tests/mod.rs +3 -3
- package/sdk-core/core/src/core_tests/queries.rs +42 -5
- package/sdk-core/core/src/core_tests/workers.rs +2 -3
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +115 -15
- package/sdk-core/core/src/ephemeral_server/mod.rs +109 -136
- package/sdk-core/core/src/internal_flags.rs +8 -8
- package/sdk-core/core/src/lib.rs +16 -11
- package/sdk-core/core/src/pollers/mod.rs +11 -5
- package/sdk-core/core/src/pollers/poll_buffer.rs +48 -29
- package/sdk-core/core/src/protosext/mod.rs +32 -32
- package/sdk-core/core/src/protosext/protocol_messages.rs +14 -24
- package/sdk-core/core/src/retry_logic.rs +2 -2
- package/sdk-core/core/src/telemetry/log_export.rs +10 -9
- package/sdk-core/core/src/telemetry/metrics.rs +233 -330
- package/sdk-core/core/src/telemetry/mod.rs +11 -38
- package/sdk-core/core/src/telemetry/otel.rs +355 -0
- package/sdk-core/core/src/telemetry/prometheus_server.rs +36 -23
- package/sdk-core/core/src/test_help/mod.rs +80 -59
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +6 -6
- package/sdk-core/core/src/worker/activities/local_activities.rs +46 -43
- package/sdk-core/core/src/worker/activities.rs +45 -46
- package/sdk-core/core/src/worker/client/mocks.rs +8 -7
- package/sdk-core/core/src/worker/client.rs +40 -39
- package/sdk-core/core/src/worker/mod.rs +72 -42
- package/sdk-core/core/src/worker/slot_provider.rs +28 -28
- package/sdk-core/core/src/worker/slot_supplier.rs +1 -0
- package/sdk-core/core/src/worker/tuner/fixed_size.rs +52 -0
- package/sdk-core/core/src/worker/tuner/resource_based.rs +561 -0
- package/sdk-core/core/src/worker/tuner.rs +122 -0
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +6 -6
- package/sdk-core/core/src/worker/workflow/history_update.rs +27 -53
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +4 -17
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -10
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +4 -11
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +17 -35
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +0 -8
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +1 -5
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +0 -5
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +0 -5
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +0 -14
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -5
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +0 -5
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -10
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +3 -10
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +12 -8
- package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +0 -10
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +6 -13
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +27 -37
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +3 -14
- package/sdk-core/core/src/worker/workflow/managed_run.rs +84 -54
- package/sdk-core/core/src/worker/workflow/mod.rs +63 -160
- package/sdk-core/core/src/worker/workflow/run_cache.rs +22 -13
- package/sdk-core/core/src/worker/workflow/wft_extraction.rs +16 -3
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +15 -12
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +39 -78
- package/sdk-core/core-api/Cargo.toml +6 -5
- package/sdk-core/core-api/src/errors.rs +8 -0
- package/sdk-core/core-api/src/telemetry/metrics.rs +75 -4
- package/sdk-core/core-api/src/telemetry.rs +7 -1
- package/sdk-core/core-api/src/worker.rs +212 -56
- package/sdk-core/fsm/Cargo.toml +3 -0
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
- package/sdk-core/sdk/Cargo.toml +5 -7
- package/sdk-core/sdk/src/app_data.rs +3 -3
- package/sdk-core/sdk/src/lib.rs +5 -3
- package/sdk-core/sdk/src/workflow_context/options.rs +1 -1
- package/sdk-core/sdk/src/workflow_context.rs +10 -9
- package/sdk-core/sdk/src/workflow_future.rs +1 -1
- package/sdk-core/sdk-core-protos/Cargo.toml +8 -6
- package/sdk-core/sdk-core-protos/build.rs +1 -10
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/PULL_REQUEST_TEMPLATE.md +3 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/ci.yml +26 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/Makefile +42 -20
- package/sdk-core/sdk-core-protos/protos/api_upstream/README.md +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/api-linter.yaml +36 -26
- package/sdk-core/sdk-core-protos/protos/api_upstream/buf.lock +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/google/protobuf/struct.proto +95 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +9632 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +7337 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/payload_description.txt +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +45 -11
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +22 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/command_type.proto +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/common.proto +44 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/event_type.proto +18 -3
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +20 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +30 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/update.proto +7 -8
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/workflow.proto +23 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/errordetails/v1/message.proto +20 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +25 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +141 -15
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +12 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +193 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +73 -6
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +46 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/schedule/v1/message.proto +4 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +2 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +116 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +134 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +274 -29
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +57 -1
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +10 -12
- package/sdk-core/sdk-core-protos/src/history_builder.rs +1 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +54 -51
- package/sdk-core/sdk-core-protos/src/task_token.rs +11 -2
- package/sdk-core/test-utils/Cargo.toml +7 -4
- package/sdk-core/test-utils/src/histfetch.rs +1 -1
- package/sdk-core/test-utils/src/lib.rs +44 -62
- package/sdk-core/tests/fuzzy_workflow.rs +5 -2
- package/sdk-core/tests/heavy_tests.rs +114 -17
- package/sdk-core/tests/integ_tests/activity_functions.rs +1 -1
- package/sdk-core/tests/integ_tests/client_tests.rs +2 -2
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +38 -26
- package/sdk-core/tests/integ_tests/metrics_tests.rs +126 -17
- package/sdk-core/tests/integ_tests/polling_tests.rs +118 -2
- package/sdk-core/tests/integ_tests/update_tests.rs +3 -5
- package/sdk-core/tests/integ_tests/visibility_tests.rs +3 -3
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +3 -3
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +5 -4
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -2
- package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +6 -10
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +9 -7
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +14 -9
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +6 -13
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +9 -6
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +5 -5
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests.rs +115 -11
- package/sdk-core/tests/main.rs +2 -2
- package/src/conversions.rs +57 -0
- package/src/lib.rs +1 -0
- package/src/runtime.rs +51 -35
- package/ts/index.ts +67 -3
- package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +0 -117
- package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +0 -24
- package/sdk-core/sdk/src/payload_converter.rs +0 -11
- package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/Dockerfile +0 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/docker-compose.yml +0 -15
- package/sdk-core/sdk-core-protos/protos/api_upstream/.buildkite/pipeline.yml +0 -10
- package/sdk-core/test-utils/src/wf_input_saver.rs +0 -50
- package/sdk-core/tests/wf_input_replay.rs +0 -32
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
mod activities;
|
|
2
2
|
pub(crate) mod client;
|
|
3
3
|
mod slot_provider;
|
|
4
|
+
pub(crate) mod tuner;
|
|
4
5
|
mod workflow;
|
|
5
6
|
|
|
6
7
|
pub use temporal_sdk_core_api::worker::{WorkerConfig, WorkerConfigBuilder};
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
pub use tuner::{
|
|
9
|
+
FixedSizeSlotSupplier, RealSysInfo, ResourceBasedSlots, ResourceBasedTuner,
|
|
10
|
+
ResourceSlotOptions, TunerBuilder, TunerHolder,
|
|
11
|
+
};
|
|
9
12
|
|
|
10
13
|
pub(crate) use activities::{
|
|
11
14
|
ExecutingLAId, LocalActRequest, LocalActivityExecutionResult, LocalActivityResolution,
|
|
@@ -13,10 +16,10 @@ pub(crate) use activities::{
|
|
|
13
16
|
};
|
|
14
17
|
pub(crate) use workflow::{wft_poller::new_wft_poller, LEGACY_QUERY_ID};
|
|
15
18
|
|
|
16
|
-
use temporal_client::WorkerKey;
|
|
19
|
+
use temporal_client::{ConfiguredClient, TemporalServiceClientWithMetrics, WorkerKey};
|
|
17
20
|
|
|
18
21
|
use crate::{
|
|
19
|
-
abstractions::{dbg_panic,
|
|
22
|
+
abstractions::{dbg_panic, MeteredPermitDealer},
|
|
20
23
|
errors::CompleteWfError,
|
|
21
24
|
pollers::{
|
|
22
25
|
new_activity_task_buffer, new_workflow_task_buffer, BoxedActPoller, WorkflowTaskPoller,
|
|
@@ -38,6 +41,7 @@ use crate::{
|
|
|
38
41
|
};
|
|
39
42
|
use activities::WorkerActivityTasks;
|
|
40
43
|
use futures_util::{stream, StreamExt};
|
|
44
|
+
use parking_lot::Mutex;
|
|
41
45
|
use slot_provider::SlotProvider;
|
|
42
46
|
use std::{
|
|
43
47
|
convert::TryInto,
|
|
@@ -81,7 +85,7 @@ pub struct Worker {
|
|
|
81
85
|
config: WorkerConfig,
|
|
82
86
|
wf_client: Arc<dyn WorkerClient>,
|
|
83
87
|
/// Registration key to enable eager workflow start for this worker
|
|
84
|
-
worker_key: Option<WorkerKey
|
|
88
|
+
worker_key: Mutex<Option<WorkerKey>>,
|
|
85
89
|
/// Manages all workflows and WFT processing
|
|
86
90
|
workflows: Workflows,
|
|
87
91
|
/// Manages activity tasks for this worker/task queue
|
|
@@ -169,7 +173,7 @@ impl WorkerTrait for Worker {
|
|
|
169
173
|
}
|
|
170
174
|
self.shutdown_token.cancel();
|
|
171
175
|
// First, disable Eager Workflow Start
|
|
172
|
-
if let Some(key) = self.worker_key {
|
|
176
|
+
if let Some(key) = *self.worker_key.lock() {
|
|
173
177
|
self.wf_client.workers().unregister(key);
|
|
174
178
|
}
|
|
175
179
|
// Second, we want to stop polling of both activity and workflow tasks
|
|
@@ -217,12 +221,23 @@ impl Worker {
|
|
|
217
221
|
)
|
|
218
222
|
}
|
|
219
223
|
|
|
224
|
+
/// Replace client and return a new client. For eager workflow purposes, this new client will
|
|
225
|
+
/// now apply to future eager start requests and the older client will not.
|
|
226
|
+
pub fn replace_client(&self, new_client: ConfiguredClient<TemporalServiceClientWithMetrics>) {
|
|
227
|
+
// Unregister worker from current client, register in new client at the end
|
|
228
|
+
let mut worker_key = self.worker_key.lock();
|
|
229
|
+
let slot_provider = (*worker_key).and_then(|k| self.wf_client.workers().unregister(k));
|
|
230
|
+
self.wf_client
|
|
231
|
+
.replace_client(super::init_worker_client(&self.config, new_client));
|
|
232
|
+
*worker_key = slot_provider
|
|
233
|
+
.and_then(|slot_provider| self.wf_client.workers().register(slot_provider));
|
|
234
|
+
}
|
|
235
|
+
|
|
220
236
|
#[cfg(test)]
|
|
221
237
|
pub(crate) fn new_test(config: WorkerConfig, client: impl WorkerClient + 'static) -> Self {
|
|
222
238
|
Self::new(config, None, Arc::new(client), None)
|
|
223
239
|
}
|
|
224
240
|
|
|
225
|
-
#[allow(clippy::too_many_arguments)] // Not much worth combining here
|
|
226
241
|
pub(crate) fn new_with_pollers(
|
|
227
242
|
config: WorkerConfig,
|
|
228
243
|
sticky_queue_name: Option<String>,
|
|
@@ -230,22 +245,40 @@ impl Worker {
|
|
|
230
245
|
task_pollers: TaskPollers,
|
|
231
246
|
telem_instance: Option<&TelemetryInstance>,
|
|
232
247
|
) -> Self {
|
|
233
|
-
let metrics = if let Some(ti) = telem_instance {
|
|
234
|
-
|
|
248
|
+
let (metrics, meter) = if let Some(ti) = telem_instance {
|
|
249
|
+
(
|
|
250
|
+
MetricsContext::top_level(config.namespace.clone(), config.task_queue.clone(), ti),
|
|
251
|
+
ti.get_metric_meter(),
|
|
252
|
+
)
|
|
235
253
|
} else {
|
|
236
|
-
MetricsContext::no_op()
|
|
254
|
+
(MetricsContext::no_op(), None)
|
|
237
255
|
};
|
|
256
|
+
let tuner = config
|
|
257
|
+
.tuner
|
|
258
|
+
.as_ref()
|
|
259
|
+
.cloned()
|
|
260
|
+
.unwrap_or_else(|| TunerBuilder::from_config(&config).build());
|
|
261
|
+
|
|
238
262
|
metrics.worker_registered();
|
|
263
|
+
if let Some(meter) = meter {
|
|
264
|
+
tuner.attach_metrics(meter.clone());
|
|
265
|
+
}
|
|
239
266
|
let shutdown_token = CancellationToken::new();
|
|
240
|
-
let
|
|
241
|
-
|
|
267
|
+
let wft_slots = Arc::new(MeteredPermitDealer::new(
|
|
268
|
+
tuner.workflow_task_slot_supplier(),
|
|
242
269
|
metrics.with_new_attrs([workflow_worker_type()]),
|
|
243
|
-
|
|
270
|
+
if config.max_cached_workflows > 0 {
|
|
271
|
+
// Since we always need to be able to poll the normal task queue as well as the
|
|
272
|
+
// sticky queue, we need a value of at least 2 here.
|
|
273
|
+
Some(std::cmp::max(2, config.max_cached_workflows))
|
|
274
|
+
} else {
|
|
275
|
+
None
|
|
276
|
+
},
|
|
244
277
|
));
|
|
245
|
-
let
|
|
246
|
-
|
|
278
|
+
let act_slots = Arc::new(MeteredPermitDealer::new(
|
|
279
|
+
tuner.activity_task_slot_supplier(),
|
|
247
280
|
metrics.with_new_attrs([activity_worker_type()]),
|
|
248
|
-
|
|
281
|
+
None,
|
|
249
282
|
));
|
|
250
283
|
let (external_wft_tx, external_wft_rx) = unbounded_channel();
|
|
251
284
|
let (wft_stream, act_poller) = match task_pollers {
|
|
@@ -265,7 +298,7 @@ impl Worker {
|
|
|
265
298
|
normal_name: "".to_string(),
|
|
266
299
|
},
|
|
267
300
|
max_nonsticky_polls,
|
|
268
|
-
|
|
301
|
+
wft_slots.clone(),
|
|
269
302
|
shutdown_token.child_token(),
|
|
270
303
|
Some(move |np| {
|
|
271
304
|
wft_metrics.record_num_pollers(np);
|
|
@@ -281,7 +314,7 @@ impl Worker {
|
|
|
281
314
|
normal_name: config.task_queue.clone(),
|
|
282
315
|
},
|
|
283
316
|
max_sticky_polls,
|
|
284
|
-
|
|
317
|
+
wft_slots.clone(),
|
|
285
318
|
shutdown_token.child_token(),
|
|
286
319
|
Some(move |np| {
|
|
287
320
|
sticky_metrics.record_num_pollers(np);
|
|
@@ -296,7 +329,7 @@ impl Worker {
|
|
|
296
329
|
client.clone(),
|
|
297
330
|
config.task_queue.clone(),
|
|
298
331
|
config.max_concurrent_at_polls,
|
|
299
|
-
|
|
332
|
+
act_slots.clone(),
|
|
300
333
|
config.max_task_queue_activities_per_second,
|
|
301
334
|
shutdown_token.child_token(),
|
|
302
335
|
Some(move |np| act_metrics.record_num_pollers(np)),
|
|
@@ -327,9 +360,8 @@ impl Worker {
|
|
|
327
360
|
wft_stream,
|
|
328
361
|
act_poller,
|
|
329
362
|
} => {
|
|
330
|
-
let ap =
|
|
331
|
-
|
|
332
|
-
let wft_semaphore = wft_semaphore.clone();
|
|
363
|
+
let ap = act_poller.map(|ap| MockPermittedPollBuffer::new(act_slots.clone(), ap));
|
|
364
|
+
let wft_semaphore = wft_slots.clone();
|
|
333
365
|
let wfs = wft_stream.then(move |s| {
|
|
334
366
|
let wft_semaphore = wft_semaphore.clone();
|
|
335
367
|
async move {
|
|
@@ -347,14 +379,14 @@ impl Worker {
|
|
|
347
379
|
|
|
348
380
|
let (hb_tx, hb_rx) = unbounded_channel();
|
|
349
381
|
let local_act_mgr = Arc::new(LocalActivityManager::new(
|
|
350
|
-
|
|
382
|
+
tuner.local_activity_slot_supplier(),
|
|
351
383
|
config.namespace.clone(),
|
|
352
384
|
hb_tx,
|
|
353
385
|
metrics.with_new_attrs([local_activity_worker_type()]),
|
|
354
386
|
));
|
|
355
387
|
let at_task_mgr = act_poller.map(|ap| {
|
|
356
388
|
WorkerActivityTasks::new(
|
|
357
|
-
|
|
389
|
+
act_slots,
|
|
358
390
|
ap,
|
|
359
391
|
client.clone(),
|
|
360
392
|
metrics.clone(),
|
|
@@ -368,14 +400,14 @@ impl Worker {
|
|
|
368
400
|
if !poll_on_non_local_activities {
|
|
369
401
|
info!("Activity polling is disabled for this worker");
|
|
370
402
|
};
|
|
371
|
-
let la_sink = LAReqSink::new(local_act_mgr.clone()
|
|
403
|
+
let la_sink = LAReqSink::new(local_act_mgr.clone());
|
|
372
404
|
let provider = SlotProvider::new(
|
|
373
405
|
config.namespace.clone(),
|
|
374
406
|
config.task_queue.clone(),
|
|
375
|
-
|
|
407
|
+
wft_slots.clone(),
|
|
376
408
|
external_wft_tx,
|
|
377
409
|
);
|
|
378
|
-
let worker_key = client.workers().register(Box::new(provider));
|
|
410
|
+
let worker_key = Mutex::new(client.workers().register(Box::new(provider)));
|
|
379
411
|
Self {
|
|
380
412
|
worker_key,
|
|
381
413
|
wf_client: client.clone(),
|
|
@@ -384,7 +416,7 @@ impl Worker {
|
|
|
384
416
|
config.clone(),
|
|
385
417
|
metrics,
|
|
386
418
|
shutdown_token.child_token(),
|
|
387
|
-
client.capabilities().
|
|
419
|
+
client.capabilities().clone().unwrap_or_default(),
|
|
388
420
|
),
|
|
389
421
|
sticky_queue_name.map(|sq| StickyExecutionAttributes {
|
|
390
422
|
worker_task_queue: Some(TaskQueue {
|
|
@@ -400,7 +432,7 @@ impl Worker {
|
|
|
400
432
|
),
|
|
401
433
|
}),
|
|
402
434
|
client,
|
|
403
|
-
|
|
435
|
+
wft_slots,
|
|
404
436
|
wft_stream,
|
|
405
437
|
la_sink,
|
|
406
438
|
local_act_mgr.clone(),
|
|
@@ -473,11 +505,11 @@ impl Worker {
|
|
|
473
505
|
}
|
|
474
506
|
|
|
475
507
|
#[allow(unused)]
|
|
476
|
-
pub(crate) fn available_wft_permits(&self) -> usize {
|
|
508
|
+
pub(crate) fn available_wft_permits(&self) -> Option<usize> {
|
|
477
509
|
self.workflows.available_wft_permits()
|
|
478
510
|
}
|
|
479
511
|
#[cfg(test)]
|
|
480
|
-
pub(crate) fn unused_wft_permits(&self) -> usize {
|
|
512
|
+
pub(crate) fn unused_wft_permits(&self) -> Option<usize> {
|
|
481
513
|
self.workflows.unused_wft_permits()
|
|
482
514
|
}
|
|
483
515
|
|
|
@@ -659,10 +691,9 @@ impl Worker {
|
|
|
659
691
|
}
|
|
660
692
|
}
|
|
661
693
|
|
|
662
|
-
pub struct PostActivateHookData<'a> {
|
|
663
|
-
pub run_id: &'a str,
|
|
664
|
-
pub
|
|
665
|
-
pub replaying: bool,
|
|
694
|
+
pub(crate) struct PostActivateHookData<'a> {
|
|
695
|
+
pub(crate) run_id: &'a str,
|
|
696
|
+
pub(crate) replaying: bool,
|
|
666
697
|
}
|
|
667
698
|
|
|
668
699
|
fn build_wf_basics(
|
|
@@ -718,7 +749,7 @@ mod tests {
|
|
|
718
749
|
.as_ref()
|
|
719
750
|
.unwrap()
|
|
720
751
|
.remaining_activity_capacity(),
|
|
721
|
-
5
|
|
752
|
+
Some(5)
|
|
722
753
|
);
|
|
723
754
|
}
|
|
724
755
|
|
|
@@ -735,16 +766,15 @@ mod tests {
|
|
|
735
766
|
.unwrap();
|
|
736
767
|
let worker = Worker::new_test(cfg, mock_client);
|
|
737
768
|
assert!(worker.activity_poll().await.is_err());
|
|
738
|
-
assert_eq!(
|
|
769
|
+
assert_eq!(
|
|
770
|
+
worker.at_task_mgr.unwrap().remaining_activity_capacity(),
|
|
771
|
+
Some(5)
|
|
772
|
+
);
|
|
739
773
|
}
|
|
740
774
|
|
|
741
775
|
#[test]
|
|
742
776
|
fn max_polls_calculated_properly() {
|
|
743
|
-
let
|
|
744
|
-
let cfg = wcb
|
|
745
|
-
.namespace("default")
|
|
746
|
-
.task_queue("whatever")
|
|
747
|
-
.worker_build_id("test_bin_id")
|
|
777
|
+
let cfg = test_worker_cfg()
|
|
748
778
|
.max_concurrent_wft_polls(5_usize)
|
|
749
779
|
.build()
|
|
750
780
|
.unwrap();
|
|
@@ -3,27 +3,38 @@
|
|
|
3
3
|
//! This enables latency optimizations such as Eager Workflow Start.
|
|
4
4
|
|
|
5
5
|
use crate::{
|
|
6
|
-
abstractions::{
|
|
6
|
+
abstractions::{MeteredPermitDealer, OwnedMeteredSemPermit},
|
|
7
7
|
protosext::ValidPollWFTQResponse,
|
|
8
8
|
worker::workflow::wft_poller::validate_wft,
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
use std::sync::Arc;
|
|
12
12
|
use temporal_client::{Slot as SlotTrait, SlotProvider as SlotProviderTrait};
|
|
13
|
+
use temporal_sdk_core_api::worker::WorkflowSlotKind;
|
|
13
14
|
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::PollWorkflowTaskQueueResponse;
|
|
14
15
|
use tokio::sync::mpsc::UnboundedSender;
|
|
15
16
|
use tonic::Status;
|
|
16
17
|
|
|
17
|
-
type WFTStreamSender =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
type WFTStreamSender = UnboundedSender<
|
|
19
|
+
Result<
|
|
20
|
+
(
|
|
21
|
+
ValidPollWFTQResponse,
|
|
22
|
+
OwnedMeteredSemPermit<WorkflowSlotKind>,
|
|
23
|
+
),
|
|
24
|
+
Status,
|
|
25
|
+
>,
|
|
26
|
+
>;
|
|
27
|
+
|
|
28
|
+
struct Slot {
|
|
29
|
+
permit: OwnedMeteredSemPermit<WorkflowSlotKind>,
|
|
22
30
|
external_wft_tx: WFTStreamSender,
|
|
23
31
|
}
|
|
24
32
|
|
|
25
33
|
impl Slot {
|
|
26
|
-
fn new(
|
|
34
|
+
fn new(
|
|
35
|
+
permit: OwnedMeteredSemPermit<WorkflowSlotKind>,
|
|
36
|
+
external_wft_tx: WFTStreamSender,
|
|
37
|
+
) -> Self {
|
|
27
38
|
Self {
|
|
28
39
|
permit,
|
|
29
40
|
external_wft_tx,
|
|
@@ -44,18 +55,18 @@ impl SlotTrait for Slot {
|
|
|
44
55
|
|
|
45
56
|
#[derive(derive_more::DebugCustom)]
|
|
46
57
|
#[debug(fmt = "SlotProvider {{ namespace:{namespace}, task_queue: {task_queue} }}")]
|
|
47
|
-
pub struct SlotProvider {
|
|
58
|
+
pub(super) struct SlotProvider {
|
|
48
59
|
namespace: String,
|
|
49
60
|
task_queue: String,
|
|
50
|
-
wft_semaphore: Arc<
|
|
61
|
+
wft_semaphore: Arc<MeteredPermitDealer<WorkflowSlotKind>>,
|
|
51
62
|
external_wft_tx: WFTStreamSender,
|
|
52
63
|
}
|
|
53
64
|
|
|
54
65
|
impl SlotProvider {
|
|
55
|
-
pub(
|
|
66
|
+
pub(super) fn new(
|
|
56
67
|
namespace: String,
|
|
57
68
|
task_queue: String,
|
|
58
|
-
wft_semaphore: Arc<
|
|
69
|
+
wft_semaphore: Arc<MeteredPermitDealer<WorkflowSlotKind>>,
|
|
59
70
|
external_wft_tx: WFTStreamSender,
|
|
60
71
|
) -> Self {
|
|
61
72
|
Self {
|
|
@@ -86,6 +97,7 @@ impl SlotProviderTrait for SlotProvider {
|
|
|
86
97
|
mod tests {
|
|
87
98
|
use super::*;
|
|
88
99
|
|
|
100
|
+
use crate::abstractions::tests::fixed_size_permit_dealer;
|
|
89
101
|
use temporal_sdk_core_protos::temporal::api::{
|
|
90
102
|
common::v1::{WorkflowExecution, WorkflowType},
|
|
91
103
|
history::v1::History,
|
|
@@ -106,11 +118,7 @@ mod tests {
|
|
|
106
118
|
|
|
107
119
|
#[tokio::test]
|
|
108
120
|
async fn slot_propagates_through_channel() {
|
|
109
|
-
let wft_semaphore = Arc::new(
|
|
110
|
-
2,
|
|
111
|
-
crate::MetricsContext::no_op(),
|
|
112
|
-
|_, _| {},
|
|
113
|
-
));
|
|
121
|
+
let wft_semaphore = Arc::new(fixed_size_permit_dealer(2));
|
|
114
122
|
let (external_wft_tx, mut external_wft_rx) = unbounded_channel();
|
|
115
123
|
|
|
116
124
|
let provider = SlotProvider::new(
|
|
@@ -133,11 +141,7 @@ mod tests {
|
|
|
133
141
|
let (external_wft_tx, mut external_wft_rx) = unbounded_channel();
|
|
134
142
|
{
|
|
135
143
|
let external_wft_tx = external_wft_tx;
|
|
136
|
-
let wft_semaphore = Arc::new(
|
|
137
|
-
2,
|
|
138
|
-
crate::MetricsContext::no_op(),
|
|
139
|
-
|_, _| {},
|
|
140
|
-
));
|
|
144
|
+
let wft_semaphore = Arc::new(fixed_size_permit_dealer(2));
|
|
141
145
|
let provider = SlotProvider::new(
|
|
142
146
|
"my_namespace".to_string(),
|
|
143
147
|
"my_queue".to_string(),
|
|
@@ -151,11 +155,7 @@ mod tests {
|
|
|
151
155
|
|
|
152
156
|
#[tokio::test]
|
|
153
157
|
async fn unused_slots_reclaimed() {
|
|
154
|
-
let wft_semaphore = Arc::new(
|
|
155
|
-
2,
|
|
156
|
-
crate::MetricsContext::no_op(),
|
|
157
|
-
|_, _| {},
|
|
158
|
-
));
|
|
158
|
+
let wft_semaphore = Arc::new(fixed_size_permit_dealer(2));
|
|
159
159
|
{
|
|
160
160
|
let wft_semaphore = wft_semaphore.clone();
|
|
161
161
|
let (external_wft_tx, _) = unbounded_channel();
|
|
@@ -167,9 +167,9 @@ mod tests {
|
|
|
167
167
|
);
|
|
168
168
|
let slot = provider.try_reserve_wft_slot();
|
|
169
169
|
assert!(slot.is_some());
|
|
170
|
-
assert_eq!(wft_semaphore.available_permits(), 1);
|
|
170
|
+
assert_eq!(wft_semaphore.available_permits(), Some(1));
|
|
171
171
|
// drop slot without using it
|
|
172
172
|
}
|
|
173
|
-
assert_eq!(wft_semaphore.available_permits(), 2);
|
|
173
|
+
assert_eq!(wft_semaphore.available_permits(), Some(2));
|
|
174
174
|
}
|
|
175
175
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
use std::{marker::PhantomData, sync::Arc};
|
|
2
|
+
use temporal_sdk_core_api::worker::{
|
|
3
|
+
SlotKind, SlotReservationContext, SlotSupplier, SlotSupplierPermit,
|
|
4
|
+
};
|
|
5
|
+
use tokio::sync::Semaphore;
|
|
6
|
+
|
|
7
|
+
/// Implements [SlotSupplier] with a fixed number of slots
|
|
8
|
+
pub struct FixedSizeSlotSupplier<SK> {
|
|
9
|
+
sem: Arc<Semaphore>,
|
|
10
|
+
_pd: PhantomData<SK>,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
impl<SK> FixedSizeSlotSupplier<SK> {
|
|
14
|
+
/// Create a slot supplier which will only hand out at most the provided number of slots
|
|
15
|
+
pub fn new(size: usize) -> Self {
|
|
16
|
+
Self {
|
|
17
|
+
sem: Arc::new(Semaphore::new(size)),
|
|
18
|
+
_pd: Default::default(),
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[async_trait::async_trait]
|
|
24
|
+
impl<SK> SlotSupplier for FixedSizeSlotSupplier<SK>
|
|
25
|
+
where
|
|
26
|
+
SK: SlotKind + Send + Sync,
|
|
27
|
+
{
|
|
28
|
+
type SlotKind = SK;
|
|
29
|
+
|
|
30
|
+
async fn reserve_slot(&self, _: &dyn SlotReservationContext) -> SlotSupplierPermit {
|
|
31
|
+
let perm = self
|
|
32
|
+
.sem
|
|
33
|
+
.clone()
|
|
34
|
+
.acquire_owned()
|
|
35
|
+
.await
|
|
36
|
+
.expect("inner semaphore is never closed");
|
|
37
|
+
SlotSupplierPermit::with_user_data(perm)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fn try_reserve_slot(&self, _: &dyn SlotReservationContext) -> Option<SlotSupplierPermit> {
|
|
41
|
+
let perm = self.sem.clone().try_acquire_owned();
|
|
42
|
+
perm.ok().map(SlotSupplierPermit::with_user_data)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
fn mark_slot_used(&self, _info: SK::Info<'_>) {}
|
|
46
|
+
|
|
47
|
+
fn release_slot(&self) {}
|
|
48
|
+
|
|
49
|
+
fn available_slots(&self) -> Option<usize> {
|
|
50
|
+
Some(self.sem.available_permits())
|
|
51
|
+
}
|
|
52
|
+
}
|