@temporalio/core-bridge 1.10.3 → 1.11.1
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 +563 -676
- package/Cargo.toml +3 -3
- package/lib/index.d.ts +16 -5
- package/lib/index.js.map +1 -1
- package/lib/worker-tuner.d.ts +57 -0
- package/lib/worker-tuner.js +3 -0
- package/lib/worker-tuner.js.map +1 -0
- 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/heavy.yml +6 -11
- package/sdk-core/.github/workflows/per-pr.yml +23 -41
- package/sdk-core/Cargo.toml +5 -5
- package/sdk-core/README.md +2 -0
- package/sdk-core/client/Cargo.toml +4 -2
- package/sdk-core/client/src/lib.rs +60 -17
- package/sdk-core/client/src/metrics.rs +1 -1
- package/sdk-core/client/src/proxy.rs +17 -12
- package/sdk-core/client/src/raw.rs +218 -69
- package/sdk-core/client/src/retry.rs +19 -9
- package/sdk-core/core/Cargo.toml +12 -12
- package/sdk-core/core/src/abstractions.rs +3 -3
- package/sdk-core/core/src/core_tests/activity_tasks.rs +2 -1
- package/sdk-core/core/src/core_tests/determinism.rs +1 -1
- package/sdk-core/core/src/core_tests/local_activities.rs +73 -10
- package/sdk-core/core/src/core_tests/queries.rs +2 -1
- package/sdk-core/core/src/core_tests/updates.rs +162 -4
- package/sdk-core/core/src/core_tests/workers.rs +38 -2
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +158 -27
- package/sdk-core/core/src/internal_flags.rs +17 -7
- package/sdk-core/core/src/lib.rs +9 -3
- package/sdk-core/core/src/pollers/poll_buffer.rs +1 -10
- package/sdk-core/core/src/protosext/mod.rs +0 -1
- package/sdk-core/core/src/protosext/protocol_messages.rs +105 -16
- package/sdk-core/core/src/retry_logic.rs +22 -2
- package/sdk-core/core/src/telemetry/otel.rs +44 -12
- package/sdk-core/core/src/test_help/mod.rs +65 -12
- package/sdk-core/core/src/worker/activities/local_activities.rs +1 -4
- package/sdk-core/core/src/worker/activities.rs +3 -4
- package/sdk-core/core/src/worker/client/mocks.rs +7 -6
- package/sdk-core/core/src/worker/client.rs +11 -2
- package/sdk-core/core/src/worker/mod.rs +49 -24
- package/sdk-core/core/src/worker/tuner/resource_based.rs +48 -48
- package/sdk-core/core/src/worker/tuner.rs +124 -4
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +1 -1
- package/sdk-core/core/src/worker/workflow/history_update.rs +11 -2
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +18 -3
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +4 -4
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +3 -1
- package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +38 -28
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +4 -2
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +95 -71
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +1 -1
- package/sdk-core/core/src/worker/workflow/managed_run.rs +214 -14
- package/sdk-core/core/src/worker/workflow/mod.rs +49 -36
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +1 -2
- package/sdk-core/core-api/src/errors.rs +13 -7
- package/sdk-core/core-api/src/lib.rs +9 -1
- package/sdk-core/sdk/Cargo.toml +1 -1
- package/sdk-core/sdk/src/activity_context.rs +3 -4
- package/sdk-core/sdk/src/lib.rs +96 -49
- package/sdk-core/sdk/src/workflow_context/options.rs +8 -4
- package/sdk-core/sdk/src/workflow_context.rs +53 -49
- package/sdk-core/sdk/src/workflow_future.rs +10 -4
- package/sdk-core/sdk-core-protos/Cargo.toml +4 -3
- package/sdk-core/sdk-core-protos/build.rs +2 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/.github/workflows/build.yaml +18 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/LICENSE +21 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/Makefile +59 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/README.md +25 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.gen.yaml +14 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.lock +8 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.yaml +9 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +520 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +263 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +173 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +164 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +36 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +22 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +50 -8
- package/sdk-core/sdk-core-protos/protos/api_upstream/.gitmodules +3 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +132 -54
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +177 -81
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +13 -0
- 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/task_queue.proto +8 -3
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +10 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +3 -3
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +6 -6
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/enhanced_stack_trace.proto +96 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/user_metadata.proto +49 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +6 -7
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +55 -24
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +7 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +21 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +64 -45
- package/sdk-core/sdk-core-protos/src/history_builder.rs +8 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +40 -10
- package/sdk-core/test-utils/src/canned_histories.rs +1 -1
- package/sdk-core/tests/fuzzy_workflow.rs +4 -2
- package/sdk-core/tests/heavy_tests.rs +3 -3
- package/sdk-core/tests/integ_tests/activity_functions.rs +2 -2
- package/sdk-core/tests/integ_tests/client_tests.rs +234 -6
- package/sdk-core/tests/integ_tests/update_tests.rs +180 -47
- package/sdk-core/tests/integ_tests/worker_tests.rs +32 -0
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +47 -3
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +10 -10
- package/sdk-core/tests/main.rs +1 -0
- package/src/conversions.rs +84 -11
- package/src/runtime.rs +5 -17
- package/src/worker.rs +27 -6
- package/ts/index.ts +24 -5
- package/ts/worker-tuner.ts +71 -0
|
@@ -25,17 +25,36 @@ use tokio::{sync::watch, task::JoinHandle};
|
|
|
25
25
|
/// threshold for each, and slots are handed out if the output of both PID controllers is above some
|
|
26
26
|
/// defined threshold. See [ResourceBasedSlotsOptions] for the default PID controller settings.
|
|
27
27
|
pub struct ResourceBasedTuner<MI> {
|
|
28
|
-
slots: Arc<
|
|
28
|
+
slots: Arc<ResourceController<MI>>,
|
|
29
29
|
wf_opts: Option<ResourceSlotOptions>,
|
|
30
30
|
act_opts: Option<ResourceSlotOptions>,
|
|
31
31
|
la_opts: Option<ResourceSlotOptions>,
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
impl ResourceBasedTuner<RealSysInfo> {
|
|
35
|
+
/// Create an instance attempting to target the provided memory and cpu thresholds as values
|
|
36
|
+
/// between 0 and 1.
|
|
37
|
+
pub fn new(target_mem_usage: f64, target_cpu_usage: f64) -> Self {
|
|
38
|
+
let opts = ResourceBasedSlotsOptionsBuilder::default()
|
|
39
|
+
.target_mem_usage(target_mem_usage)
|
|
40
|
+
.target_cpu_usage(target_cpu_usage)
|
|
41
|
+
.build()
|
|
42
|
+
.expect("default resource based slot options can't fail to build");
|
|
43
|
+
let controller = ResourceController::new_with_sysinfo(opts, RealSysInfo::new());
|
|
44
|
+
Self::new_from_controller(controller)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Create an instance using the fully configurable set of PID controller options
|
|
48
|
+
pub fn new_from_options(options: ResourceBasedSlotsOptions) -> Self {
|
|
49
|
+
let controller = ResourceController::new_with_sysinfo(options, RealSysInfo::new());
|
|
50
|
+
Self::new_from_controller(controller)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
34
54
|
impl<MI> ResourceBasedTuner<MI> {
|
|
35
|
-
|
|
36
|
-
pub fn new(resourcer: ResourceBasedSlots<MI>) -> Self {
|
|
55
|
+
fn new_from_controller(controller: ResourceController<MI>) -> Self {
|
|
37
56
|
Self {
|
|
38
|
-
slots: Arc::new(
|
|
57
|
+
slots: Arc::new(controller),
|
|
39
58
|
wf_opts: None,
|
|
40
59
|
act_opts: None,
|
|
41
60
|
la_opts: None,
|
|
@@ -84,23 +103,22 @@ pub struct ResourceSlotOptions {
|
|
|
84
103
|
ramp_throttle: Duration,
|
|
85
104
|
}
|
|
86
105
|
|
|
87
|
-
|
|
88
|
-
/// under load.
|
|
89
|
-
///
|
|
90
|
-
/// It does so by using two PID controllers, one for memory and one for CPU, which are fed the
|
|
91
|
-
/// current usage levels of their respective resource as measurements. The user specifies a target
|
|
92
|
-
/// threshold for each, and slots are handed out if the output of both PID controllers is above some
|
|
93
|
-
/// defined threshold. See [ResourceBasedSlotsOptions] for the default PID controller settings.
|
|
94
|
-
pub struct ResourceBasedSlots<MI> {
|
|
106
|
+
struct ResourceController<MI> {
|
|
95
107
|
options: ResourceBasedSlotsOptions,
|
|
96
108
|
sys_info_supplier: MI,
|
|
97
109
|
metrics: OnceLock<JoinHandle<()>>,
|
|
98
110
|
pids: Mutex<PidControllers>,
|
|
99
111
|
last_metric_vals: Arc<AtomicCell<LastMetricVals>>,
|
|
100
112
|
}
|
|
101
|
-
///
|
|
102
|
-
|
|
103
|
-
|
|
113
|
+
/// Implements [SlotSupplier] and attempts to maintain certain levels of resource usage when under
|
|
114
|
+
/// load.
|
|
115
|
+
///
|
|
116
|
+
/// It does so by using two PID controllers, one for memory and one for CPU, which are fed the
|
|
117
|
+
/// current usage levels of their respective resource as measurements. The user specifies a target
|
|
118
|
+
/// threshold for each, and slots are handed out if the output of both PID controllers is above some
|
|
119
|
+
/// defined threshold. See [ResourceBasedSlotsOptions] for the default PID controller settings.
|
|
120
|
+
pub(crate) struct ResourceBasedSlotsForType<MI, SK> {
|
|
121
|
+
inner: Arc<ResourceController<MI>>,
|
|
104
122
|
|
|
105
123
|
opts: ResourceSlotOptions,
|
|
106
124
|
|
|
@@ -108,28 +126,35 @@ pub struct ResourceBasedSlotsForType<MI, SK> {
|
|
|
108
126
|
last_slot_issued_rx: watch::Receiver<Instant>,
|
|
109
127
|
_slot_kind: PhantomData<SK>,
|
|
110
128
|
}
|
|
129
|
+
/// Allows for the full customization of the PID options for a resource based tuner
|
|
111
130
|
#[derive(Clone, Debug, derive_builder::Builder)]
|
|
112
131
|
#[non_exhaustive]
|
|
113
132
|
pub struct ResourceBasedSlotsOptions {
|
|
114
133
|
/// A value in the range [0.0, 1.0] representing the target memory usage.
|
|
115
|
-
target_mem_usage: f64,
|
|
134
|
+
pub target_mem_usage: f64,
|
|
116
135
|
/// A value in the range [0.0, 1.0] representing the target CPU usage.
|
|
117
|
-
target_cpu_usage: f64,
|
|
136
|
+
pub target_cpu_usage: f64,
|
|
118
137
|
|
|
138
|
+
/// See [pid::Pid::p]
|
|
119
139
|
#[builder(default = "5.0")]
|
|
120
140
|
pub mem_p_gain: f64,
|
|
141
|
+
/// See [pid::Pid::i]
|
|
121
142
|
#[builder(default = "0.0")]
|
|
122
143
|
pub mem_i_gain: f64,
|
|
144
|
+
/// See [pid::Pid::d]
|
|
123
145
|
#[builder(default = "1.0")]
|
|
124
146
|
pub mem_d_gain: f64,
|
|
125
147
|
/// If the mem PID controller outputs a value higher than this, we say the mem half of things
|
|
126
148
|
/// will allow a slot
|
|
127
149
|
#[builder(default = "0.25")]
|
|
128
150
|
pub mem_output_threshold: f64,
|
|
151
|
+
/// See [pid::Pid::d]
|
|
129
152
|
#[builder(default = "5.0")]
|
|
130
153
|
pub cpu_p_gain: f64,
|
|
154
|
+
/// See [pid::Pid::i]
|
|
131
155
|
#[builder(default = "0.0")]
|
|
132
156
|
pub cpu_i_gain: f64,
|
|
157
|
+
/// See [pid::Pid::d]
|
|
133
158
|
#[builder(default = "1.0")]
|
|
134
159
|
pub cpu_d_gain: f64,
|
|
135
160
|
/// If the CPU PID controller outputs a value higher than this, we say the CPU half of things
|
|
@@ -156,24 +181,6 @@ struct LastMetricVals {
|
|
|
156
181
|
cpu_used_percent: f64,
|
|
157
182
|
}
|
|
158
183
|
|
|
159
|
-
impl ResourceBasedSlots<RealSysInfo> {
|
|
160
|
-
/// Create an instance attempting to target the provided memory and cpu thresholds as values
|
|
161
|
-
/// between 0 and 1.
|
|
162
|
-
pub fn new(target_mem_usage: f64, target_cpu_usage: f64) -> Self {
|
|
163
|
-
let opts = ResourceBasedSlotsOptionsBuilder::default()
|
|
164
|
-
.target_mem_usage(target_mem_usage)
|
|
165
|
-
.target_cpu_usage(target_cpu_usage)
|
|
166
|
-
.build()
|
|
167
|
-
.expect("default resource based slot options can't fail to build");
|
|
168
|
-
Self::new_with_sysinfo(opts, RealSysInfo::new())
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/// Create an instance using the fully configurable set of PID controller options
|
|
172
|
-
pub fn new_from_options(options: ResourceBasedSlotsOptions) -> Self {
|
|
173
|
-
Self::new_with_sysinfo(options, RealSysInfo::new())
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
184
|
impl PidControllers {
|
|
178
185
|
fn new(options: &ResourceBasedSlotsOptions) -> Self {
|
|
179
186
|
let mut mem = pid::Pid::new(options.target_mem_usage, 100.0);
|
|
@@ -272,19 +279,12 @@ where
|
|
|
272
279
|
fn release_slot(&self) {}
|
|
273
280
|
}
|
|
274
281
|
|
|
275
|
-
impl<MI, SK> ResourceBasedSlotsForType<MI, SK>
|
|
276
|
-
where
|
|
277
|
-
MI: Send + Sync + SystemResourceInfo,
|
|
278
|
-
SK: Send + SlotKind + Sync,
|
|
279
|
-
{
|
|
280
|
-
}
|
|
281
|
-
|
|
282
282
|
impl<MI, SK> ResourceBasedSlotsForType<MI, SK>
|
|
283
283
|
where
|
|
284
284
|
MI: SystemResourceInfo + Send + Sync,
|
|
285
285
|
SK: SlotKind + Send + Sync,
|
|
286
286
|
{
|
|
287
|
-
fn new(inner: Arc<
|
|
287
|
+
fn new(inner: Arc<ResourceController<MI>>, opts: ResourceSlotOptions) -> Self {
|
|
288
288
|
let (tx, rx) = watch::channel(Instant::now());
|
|
289
289
|
Self {
|
|
290
290
|
opts,
|
|
@@ -334,7 +334,7 @@ impl<MI: SystemResourceInfo + Sync + Send + 'static> WorkerTuner for ResourceBas
|
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
336
|
|
|
337
|
-
impl<MI: SystemResourceInfo + Sync + Send>
|
|
337
|
+
impl<MI: SystemResourceInfo + Sync + Send> ResourceController<MI> {
|
|
338
338
|
/// Create a [ResourceBasedSlotsForType] for this instance which is willing to hand out
|
|
339
339
|
/// `minimum` slots with no checks at all and `max` slots ever. Otherwise the underlying
|
|
340
340
|
/// mem/cpu targets will attempt to be matched while under load.
|
|
@@ -344,7 +344,7 @@ impl<MI: SystemResourceInfo + Sync + Send> ResourceBasedSlots<MI> {
|
|
|
344
344
|
/// where activities might use a lot of resources, because otherwise the implementation may
|
|
345
345
|
/// hand out many slots quickly before resource usage has a chance to be reflected, possibly
|
|
346
346
|
/// resulting in OOM (for example).
|
|
347
|
-
pub fn as_kind<SK: SlotKind + Send + Sync>(
|
|
347
|
+
pub(crate) fn as_kind<SK: SlotKind + Send + Sync>(
|
|
348
348
|
self: &Arc<Self>,
|
|
349
349
|
opts: ResourceSlotOptions,
|
|
350
350
|
) -> Arc<ResourceBasedSlotsForType<MI, SK>> {
|
|
@@ -506,7 +506,7 @@ mod tests {
|
|
|
506
506
|
#[test]
|
|
507
507
|
fn mem_workflow_sync() {
|
|
508
508
|
let (fmis, used) = FakeMIS::new();
|
|
509
|
-
let rbs = Arc::new(
|
|
509
|
+
let rbs = Arc::new(ResourceController::new_with_sysinfo(test_options(), fmis))
|
|
510
510
|
.as_kind::<WorkflowSlotKind>(ResourceSlotOptions {
|
|
511
511
|
min_slots: 0,
|
|
512
512
|
max_slots: 100,
|
|
@@ -522,7 +522,7 @@ mod tests {
|
|
|
522
522
|
async fn mem_workflow_async() {
|
|
523
523
|
let (fmis, used) = FakeMIS::new();
|
|
524
524
|
used.store(90_000, Ordering::Release);
|
|
525
|
-
let rbs = Arc::new(
|
|
525
|
+
let rbs = Arc::new(ResourceController::new_with_sysinfo(test_options(), fmis))
|
|
526
526
|
.as_kind::<WorkflowSlotKind>(ResourceSlotOptions {
|
|
527
527
|
min_slots: 0,
|
|
528
528
|
max_slots: 100,
|
|
@@ -546,7 +546,7 @@ mod tests {
|
|
|
546
546
|
#[test]
|
|
547
547
|
fn minimum_respected() {
|
|
548
548
|
let (fmis, used) = FakeMIS::new();
|
|
549
|
-
let rbs = Arc::new(
|
|
549
|
+
let rbs = Arc::new(ResourceController::new_with_sysinfo(test_options(), fmis))
|
|
550
550
|
.as_kind::<WorkflowSlotKind>(ResourceSlotOptions {
|
|
551
551
|
min_slots: 2,
|
|
552
552
|
max_slots: 100,
|
|
@@ -3,7 +3,8 @@ mod resource_based;
|
|
|
3
3
|
|
|
4
4
|
pub use fixed_size::FixedSizeSlotSupplier;
|
|
5
5
|
pub use resource_based::{
|
|
6
|
-
RealSysInfo,
|
|
6
|
+
RealSysInfo, ResourceBasedSlotsOptions, ResourceBasedSlotsOptionsBuilder, ResourceBasedTuner,
|
|
7
|
+
ResourceSlotOptions,
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
use std::sync::{Arc, OnceLock};
|
|
@@ -23,6 +24,125 @@ pub struct TunerHolder {
|
|
|
23
24
|
metrics: OnceLock<TemporalMeter>,
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
/// Can be used to construct a [TunerHolder] without needing to manually construct each
|
|
28
|
+
/// [SlotSupplier]. Useful for lang bridges to allow more easily passing through user options.
|
|
29
|
+
#[derive(Clone, Debug, derive_builder::Builder)]
|
|
30
|
+
#[builder(build_fn(validate = "Self::validate"))]
|
|
31
|
+
#[non_exhaustive]
|
|
32
|
+
pub struct TunerHolderOptions {
|
|
33
|
+
/// Options for workflow slots
|
|
34
|
+
#[builder(default, setter(strip_option))]
|
|
35
|
+
pub workflow_slot_options: Option<SlotSupplierOptions>,
|
|
36
|
+
/// Options for activity slots
|
|
37
|
+
#[builder(default, setter(strip_option))]
|
|
38
|
+
pub activity_slot_options: Option<SlotSupplierOptions>,
|
|
39
|
+
/// Options for local activity slots
|
|
40
|
+
#[builder(default, setter(strip_option))]
|
|
41
|
+
pub local_activity_slot_options: Option<SlotSupplierOptions>,
|
|
42
|
+
/// Options that will apply to all resource based slot suppliers. Must be set if any slot
|
|
43
|
+
/// options are [SlotSupplierOptions::ResourceBased]
|
|
44
|
+
#[builder(default, setter(strip_option))]
|
|
45
|
+
pub resource_based_options: Option<ResourceBasedSlotsOptions>,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
impl TunerHolderOptions {
|
|
49
|
+
/// Create a [TunerHolder] from these options
|
|
50
|
+
pub fn build_tuner_holder(self) -> Result<TunerHolder, anyhow::Error> {
|
|
51
|
+
let mut builder = TunerBuilder::default();
|
|
52
|
+
// safety note: unwraps here are OK since the builder validator guarantees options for
|
|
53
|
+
// a resource based tuner are present if any supplier is resource based
|
|
54
|
+
let mut rb_tuner = self
|
|
55
|
+
.resource_based_options
|
|
56
|
+
.map(ResourceBasedTuner::new_from_options);
|
|
57
|
+
match self.workflow_slot_options {
|
|
58
|
+
Some(SlotSupplierOptions::FixedSize { slots }) => {
|
|
59
|
+
builder.workflow_slot_supplier(Arc::new(FixedSizeSlotSupplier::new(slots)));
|
|
60
|
+
}
|
|
61
|
+
Some(SlotSupplierOptions::ResourceBased(rso)) => {
|
|
62
|
+
builder.workflow_slot_supplier(
|
|
63
|
+
rb_tuner
|
|
64
|
+
.as_mut()
|
|
65
|
+
.unwrap()
|
|
66
|
+
.with_workflow_slots_options(rso)
|
|
67
|
+
.workflow_task_slot_supplier(),
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
None => {}
|
|
71
|
+
}
|
|
72
|
+
match self.activity_slot_options {
|
|
73
|
+
Some(SlotSupplierOptions::FixedSize { slots }) => {
|
|
74
|
+
builder.activity_slot_supplier(Arc::new(FixedSizeSlotSupplier::new(slots)));
|
|
75
|
+
}
|
|
76
|
+
Some(SlotSupplierOptions::ResourceBased(rso)) => {
|
|
77
|
+
builder.activity_slot_supplier(
|
|
78
|
+
rb_tuner
|
|
79
|
+
.as_mut()
|
|
80
|
+
.unwrap()
|
|
81
|
+
.with_activity_slots_options(rso)
|
|
82
|
+
.activity_task_slot_supplier(),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
None => {}
|
|
86
|
+
}
|
|
87
|
+
match self.local_activity_slot_options {
|
|
88
|
+
Some(SlotSupplierOptions::FixedSize { slots }) => {
|
|
89
|
+
builder.local_activity_slot_supplier(Arc::new(FixedSizeSlotSupplier::new(slots)));
|
|
90
|
+
}
|
|
91
|
+
Some(SlotSupplierOptions::ResourceBased(rso)) => {
|
|
92
|
+
builder.local_activity_slot_supplier(
|
|
93
|
+
rb_tuner
|
|
94
|
+
.as_mut()
|
|
95
|
+
.unwrap()
|
|
96
|
+
.with_local_activity_slots_options(rso)
|
|
97
|
+
.local_activity_slot_supplier(),
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
None => {}
|
|
101
|
+
}
|
|
102
|
+
Ok(builder.build())
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// Options for known kinds of slot suppliers
|
|
107
|
+
#[derive(Clone, Debug)]
|
|
108
|
+
pub enum SlotSupplierOptions {
|
|
109
|
+
/// Options for a [FixedSizeSlotSupplier]
|
|
110
|
+
FixedSize {
|
|
111
|
+
/// The number of slots the fixed supplier will have
|
|
112
|
+
slots: usize,
|
|
113
|
+
},
|
|
114
|
+
/// Options for a [ResourceBasedSlots]
|
|
115
|
+
ResourceBased(ResourceSlotOptions),
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
impl TunerHolderOptionsBuilder {
|
|
119
|
+
/// Create a [TunerHolder] from this builder
|
|
120
|
+
pub fn build_tuner_holder(self) -> Result<TunerHolder, anyhow::Error> {
|
|
121
|
+
let s = self.build()?;
|
|
122
|
+
s.build_tuner_holder()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
fn validate(&self) -> Result<(), String> {
|
|
126
|
+
let any_is_resource_based = matches!(
|
|
127
|
+
self.workflow_slot_options,
|
|
128
|
+
Some(Some(SlotSupplierOptions::ResourceBased(_)))
|
|
129
|
+
) || matches!(
|
|
130
|
+
self.activity_slot_options,
|
|
131
|
+
Some(Some(SlotSupplierOptions::ResourceBased(_)))
|
|
132
|
+
) || matches!(
|
|
133
|
+
self.local_activity_slot_options,
|
|
134
|
+
Some(Some(SlotSupplierOptions::ResourceBased(_)))
|
|
135
|
+
);
|
|
136
|
+
if any_is_resource_based && matches!(self.resource_based_options, None | Some(None)) {
|
|
137
|
+
return Err(
|
|
138
|
+
"`resource_based_options` must be set if any slot options are ResourceBased"
|
|
139
|
+
.to_string(),
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
Ok(())
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
26
146
|
/// Can be used to construct a `TunerHolder` from individual slot suppliers. Any supplier which is
|
|
27
147
|
/// not provided will default to a [FixedSizeSlotSupplier] with a capacity of 100.
|
|
28
148
|
#[derive(Default, Clone)]
|
|
@@ -78,8 +198,8 @@ impl TunerBuilder {
|
|
|
78
198
|
}
|
|
79
199
|
|
|
80
200
|
/// Build a [WorkerTuner] from the configured slot suppliers
|
|
81
|
-
pub fn build(&mut self) ->
|
|
82
|
-
|
|
201
|
+
pub fn build(&mut self) -> TunerHolder {
|
|
202
|
+
TunerHolder {
|
|
83
203
|
wft_supplier: self
|
|
84
204
|
.workflow_slot_supplier
|
|
85
205
|
.clone()
|
|
@@ -93,7 +213,7 @@ impl TunerBuilder {
|
|
|
93
213
|
.clone()
|
|
94
214
|
.unwrap_or_else(|| Arc::new(FixedSizeSlotSupplier::new(100))),
|
|
95
215
|
metrics: OnceLock::new(),
|
|
96
|
-
}
|
|
216
|
+
}
|
|
97
217
|
}
|
|
98
218
|
}
|
|
99
219
|
|
|
@@ -41,7 +41,7 @@ impl DrivenWorkflow {
|
|
|
41
41
|
) {
|
|
42
42
|
debug!(run_id = %attribs.original_execution_run_id, "Driven WF start");
|
|
43
43
|
let started_info = WorkflowStartedInfo {
|
|
44
|
-
workflow_task_timeout: attribs.workflow_task_timeout.
|
|
44
|
+
workflow_task_timeout: attribs.workflow_task_timeout.try_into_or_none(),
|
|
45
45
|
memo: attribs.memo.clone(),
|
|
46
46
|
search_attrs: attribs.search_attributes.clone(),
|
|
47
47
|
retry_policy: attribs.retry_policy.clone(),
|
|
@@ -5,7 +5,7 @@ use crate::{
|
|
|
5
5
|
workflow::{CacheMissFetchReq, PermittedWFT, PreparedWFT},
|
|
6
6
|
},
|
|
7
7
|
};
|
|
8
|
-
use futures::{future::BoxFuture, FutureExt, Stream};
|
|
8
|
+
use futures::{future::BoxFuture, FutureExt, Stream, TryFutureExt};
|
|
9
9
|
use itertools::Itertools;
|
|
10
10
|
use once_cell::sync::Lazy;
|
|
11
11
|
use std::{
|
|
@@ -65,6 +65,12 @@ impl Debug for HistoryUpdate {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
impl HistoryUpdate {
|
|
69
|
+
pub(crate) fn get_events(&self) -> &[HistoryEvent] {
|
|
70
|
+
&self.events
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
68
74
|
#[derive(Debug)]
|
|
69
75
|
pub(crate) enum NextWFT {
|
|
70
76
|
ReplayOver,
|
|
@@ -402,7 +408,10 @@ impl Stream for StreamingHistoryPaginator {
|
|
|
402
408
|
// SAFETY: This is safe because the inner paginator cannot be dropped before the future,
|
|
403
409
|
// and the future won't be moved from out of this struct.
|
|
404
410
|
this.open_history_request.set(Some(unsafe {
|
|
405
|
-
transmute
|
|
411
|
+
transmute::<
|
|
412
|
+
BoxFuture<'_, Result<(), tonic::Status>>,
|
|
413
|
+
BoxFuture<'static, Result<(), tonic::Status>>,
|
|
414
|
+
>(this.inner.get_next_page().map_ok(|_| ()).boxed())
|
|
406
415
|
}));
|
|
407
416
|
}
|
|
408
417
|
let history_req = this.open_history_request.as_mut().as_pin_mut().unwrap();
|
|
@@ -134,6 +134,7 @@ impl ActivityMachine {
|
|
|
134
134
|
s.shared_state().attrs.clone(),
|
|
135
135
|
use_compatible_version,
|
|
136
136
|
)),
|
|
137
|
+
user_metadata: Default::default(),
|
|
137
138
|
};
|
|
138
139
|
NewMachineWithCommand {
|
|
139
140
|
command,
|
|
@@ -406,7 +407,7 @@ impl ScheduleCommandCreated {
|
|
|
406
407
|
|
|
407
408
|
pub(super) fn on_abandoned(self, dat: &mut SharedState) -> ActivityMachineTransition<Canceled> {
|
|
408
409
|
dat.cancelled_before_sent = true;
|
|
409
|
-
|
|
410
|
+
notify_lang_activity_cancelled(None)
|
|
410
411
|
}
|
|
411
412
|
}
|
|
412
413
|
|
|
@@ -687,6 +688,7 @@ where
|
|
|
687
688
|
},
|
|
688
689
|
),
|
|
689
690
|
),
|
|
691
|
+
user_metadata: Default::default(),
|
|
690
692
|
};
|
|
691
693
|
ActivityMachineTransition::ok(
|
|
692
694
|
vec![ActivityMachineCommand::RequestCancellation(cmd)],
|
|
@@ -804,7 +806,7 @@ mod test {
|
|
|
804
806
|
internal_flags::InternalFlags,
|
|
805
807
|
replay::TestHistoryBuilder,
|
|
806
808
|
test_help::{build_fake_sdk, MockPollCfg, ResponseType},
|
|
807
|
-
worker::workflow::machines::Machines,
|
|
809
|
+
worker::workflow::{machines::Machines, OutgoingJob},
|
|
808
810
|
};
|
|
809
811
|
use std::{cell::RefCell, mem::discriminant, rc::Rc};
|
|
810
812
|
use temporal_sdk::{ActivityOptions, CancellableFuture, WfContext, WorkflowFunction};
|
|
@@ -903,7 +905,20 @@ mod test {
|
|
|
903
905
|
panic!("Wrong machine type");
|
|
904
906
|
};
|
|
905
907
|
let cmds = s.cancel().unwrap();
|
|
906
|
-
|
|
908
|
+
// We should always be notifying lang that the activity got cancelled, even if it's
|
|
909
|
+
// abandoned and we aren't telling server
|
|
910
|
+
assert_matches!(
|
|
911
|
+
cmds.as_slice(),
|
|
912
|
+
[MachineResponse::PushWFJob(OutgoingJob {
|
|
913
|
+
variant: workflow_activation_job::Variant::ResolveActivity(ResolveActivity {
|
|
914
|
+
result: Some(ActivityResolution {
|
|
915
|
+
status: Some(activity_resolution::Status::Cancelled(_))
|
|
916
|
+
}),
|
|
917
|
+
..
|
|
918
|
+
}),
|
|
919
|
+
..
|
|
920
|
+
})]
|
|
921
|
+
);
|
|
907
922
|
let curstate = s.state();
|
|
908
923
|
assert!(matches!(curstate, &ActivityMachineState::Canceled(_)));
|
|
909
924
|
}
|
|
@@ -37,6 +37,7 @@ pub(super) fn cancel_workflow(attribs: CancelWorkflowExecution) -> NewMachineWit
|
|
|
37
37
|
let command = Command {
|
|
38
38
|
command_type: CommandType::CancelWorkflowExecution as i32,
|
|
39
39
|
attributes: Some(attribs.into()),
|
|
40
|
+
user_metadata: Default::default(),
|
|
40
41
|
};
|
|
41
42
|
NewMachineWithCommand {
|
|
42
43
|
command,
|
|
@@ -97,6 +97,7 @@ impl Created {
|
|
|
97
97
|
let cmd = Command {
|
|
98
98
|
command_type: CommandType::CompleteWorkflowExecution as i32,
|
|
99
99
|
attributes: Some(self.attribs.into()),
|
|
100
|
+
user_metadata: Default::default(),
|
|
100
101
|
};
|
|
101
102
|
TransitionResult::commands(vec![CompleteWFCommand::AddCommand(cmd)])
|
|
102
103
|
}
|
package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs
CHANGED
|
@@ -40,6 +40,7 @@ pub(super) fn continue_as_new(
|
|
|
40
40
|
let command = Command {
|
|
41
41
|
command_type: CommandType::ContinueAsNewWorkflowExecution as i32,
|
|
42
42
|
attributes: Some(continue_as_new_cmd_to_api(attribs, use_compatible_version)),
|
|
43
|
+
user_metadata: Default::default(),
|
|
43
44
|
};
|
|
44
45
|
NewMachineWithCommand {
|
|
45
46
|
command,
|
|
@@ -674,7 +674,7 @@ impl WFMachinesAdapter for LocalActivityMachine {
|
|
|
674
674
|
status: Some(
|
|
675
675
|
DoBackoff {
|
|
676
676
|
attempt: attempt + 1,
|
|
677
|
-
backoff_duration: Some(b
|
|
677
|
+
backoff_duration: Some(*b),
|
|
678
678
|
original_schedule_time: original_schedule_time.map(Into::into),
|
|
679
679
|
}
|
|
680
680
|
.into(),
|
|
@@ -882,7 +882,7 @@ mod tests {
|
|
|
882
882
|
time::Duration,
|
|
883
883
|
};
|
|
884
884
|
use temporal_sdk::{
|
|
885
|
-
ActContext,
|
|
885
|
+
ActContext, ActivityError, CancellableFuture, LocalActivityOptions, WfContext,
|
|
886
886
|
WorkflowResult,
|
|
887
887
|
};
|
|
888
888
|
use temporal_sdk_core_protos::{
|
|
@@ -988,7 +988,7 @@ mod tests {
|
|
|
988
988
|
if completes_ok {
|
|
989
989
|
Ok("hi")
|
|
990
990
|
} else {
|
|
991
|
-
Err(anyhow!("Oh no I failed!"))
|
|
991
|
+
Err(anyhow!("Oh no I failed!").into())
|
|
992
992
|
}
|
|
993
993
|
},
|
|
994
994
|
);
|
|
@@ -1450,7 +1450,7 @@ mod tests {
|
|
|
1450
1450
|
ctx.cancelled().await;
|
|
1451
1451
|
}
|
|
1452
1452
|
allow_cancel_barr_clone.cancelled().await;
|
|
1453
|
-
Result::<(), _>::Err(
|
|
1453
|
+
Result::<(), _>::Err(ActivityError::cancelled())
|
|
1454
1454
|
}
|
|
1455
1455
|
});
|
|
1456
1456
|
worker.run().await.unwrap();
|
|
@@ -112,6 +112,7 @@ pub(super) fn new_external_signal(
|
|
|
112
112
|
let cmd = Command {
|
|
113
113
|
command_type: CommandType::SignalExternalWorkflowExecution as i32,
|
|
114
114
|
attributes: Some(cmd_attrs),
|
|
115
|
+
user_metadata: Default::default(),
|
|
115
116
|
};
|
|
116
117
|
Ok(NewMachineWithCommand {
|
|
117
118
|
command: cmd,
|
|
@@ -78,7 +78,8 @@ impl TimerMachine {
|
|
|
78
78
|
.expect("Scheduling timers doesn't fail");
|
|
79
79
|
let cmd = Command {
|
|
80
80
|
command_type: CommandType::StartTimer as i32,
|
|
81
|
-
attributes: Some(s.shared_state().attrs.
|
|
81
|
+
attributes: Some(s.shared_state().attrs.into()),
|
|
82
|
+
user_metadata: Default::default(),
|
|
82
83
|
};
|
|
83
84
|
(s, cmd)
|
|
84
85
|
}
|
|
@@ -210,6 +211,7 @@ impl StartCommandRecorded {
|
|
|
210
211
|
let cmd = Command {
|
|
211
212
|
command_type: CommandType::CancelTimer as i32,
|
|
212
213
|
attributes: Some(CancelTimer { seq: dat.attrs.seq }.into()),
|
|
214
|
+
user_metadata: Default::default(),
|
|
213
215
|
};
|
|
214
216
|
TransitionResult::ok(
|
|
215
217
|
vec![TimerMachineCommand::IssueCancelCmd(cmd)],
|