@temporalio/core-bridge 1.13.0 → 1.13.2
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 +239 -382
- package/Cargo.toml +11 -11
- package/lib/native.d.ts +10 -3
- 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/.cargo/config.toml +71 -11
- package/sdk-core/.clippy.toml +1 -0
- package/sdk-core/.github/workflows/heavy.yml +2 -0
- package/sdk-core/.github/workflows/per-pr.yml +50 -18
- package/sdk-core/ARCHITECTURE.md +44 -48
- package/sdk-core/Cargo.toml +26 -7
- package/sdk-core/README.md +4 -0
- package/sdk-core/arch_docs/diagrams/TimerMachine_Coverage.puml +14 -0
- package/sdk-core/arch_docs/diagrams/initial_event_history.png +0 -0
- package/sdk-core/arch_docs/sdks_intro.md +299 -0
- package/sdk-core/client/Cargo.toml +8 -7
- package/sdk-core/client/src/callback_based.rs +1 -2
- package/sdk-core/client/src/lib.rs +485 -299
- package/sdk-core/client/src/metrics.rs +32 -8
- package/sdk-core/client/src/proxy.rs +124 -5
- package/sdk-core/client/src/raw.rs +598 -307
- package/sdk-core/client/src/replaceable.rs +253 -0
- package/sdk-core/client/src/retry.rs +9 -6
- package/sdk-core/client/src/worker_registry/mod.rs +19 -3
- package/sdk-core/client/src/workflow_handle/mod.rs +20 -17
- package/sdk-core/core/Cargo.toml +100 -31
- package/sdk-core/core/src/core_tests/activity_tasks.rs +55 -225
- package/sdk-core/core/src/core_tests/mod.rs +2 -8
- package/sdk-core/core/src/core_tests/queries.rs +3 -5
- package/sdk-core/core/src/core_tests/replay_flag.rs +3 -62
- package/sdk-core/core/src/core_tests/updates.rs +4 -5
- package/sdk-core/core/src/core_tests/workers.rs +4 -3
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +10 -7
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +28 -291
- package/sdk-core/core/src/ephemeral_server/mod.rs +15 -3
- package/sdk-core/core/src/internal_flags.rs +11 -1
- package/sdk-core/core/src/lib.rs +50 -36
- package/sdk-core/core/src/pollers/mod.rs +5 -5
- package/sdk-core/core/src/pollers/poll_buffer.rs +2 -2
- package/sdk-core/core/src/protosext/mod.rs +13 -5
- package/sdk-core/core/src/protosext/protocol_messages.rs +4 -11
- package/sdk-core/core/src/retry_logic.rs +256 -108
- package/sdk-core/core/src/telemetry/metrics.rs +1 -0
- package/sdk-core/core/src/telemetry/mod.rs +8 -2
- package/sdk-core/core/src/telemetry/prometheus_meter.rs +2 -2
- package/sdk-core/core/src/test_help/integ_helpers.rs +971 -0
- package/sdk-core/core/src/test_help/mod.rs +10 -1100
- package/sdk-core/core/src/test_help/unit_helpers.rs +218 -0
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +42 -6
- package/sdk-core/core/src/worker/activities/local_activities.rs +19 -19
- package/sdk-core/core/src/worker/activities.rs +10 -3
- package/sdk-core/core/src/worker/client/mocks.rs +3 -3
- package/sdk-core/core/src/worker/client.rs +130 -93
- package/sdk-core/core/src/worker/heartbeat.rs +12 -13
- package/sdk-core/core/src/worker/mod.rs +31 -21
- package/sdk-core/core/src/worker/nexus.rs +14 -3
- package/sdk-core/core/src/worker/slot_provider.rs +9 -0
- package/sdk-core/core/src/worker/tuner.rs +159 -0
- package/sdk-core/core/src/worker/workflow/history_update.rs +3 -265
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -54
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +0 -82
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +0 -67
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -192
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +0 -43
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +6 -554
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +0 -71
- package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +102 -3
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +10 -539
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +0 -139
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -119
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +6 -63
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +9 -4
- package/sdk-core/core/src/worker/workflow/mod.rs +5 -1
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +8 -3
- package/sdk-core/core-api/Cargo.toml +4 -4
- package/sdk-core/core-api/src/envconfig.rs +153 -54
- package/sdk-core/core-api/src/lib.rs +68 -0
- package/sdk-core/core-api/src/telemetry/metrics.rs +2 -1
- package/sdk-core/core-api/src/telemetry.rs +13 -0
- package/sdk-core/core-c-bridge/Cargo.toml +13 -8
- package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +184 -22
- package/sdk-core/core-c-bridge/src/client.rs +462 -184
- package/sdk-core/core-c-bridge/src/envconfig.rs +314 -0
- package/sdk-core/core-c-bridge/src/lib.rs +1 -0
- package/sdk-core/core-c-bridge/src/random.rs +4 -4
- package/sdk-core/core-c-bridge/src/runtime.rs +22 -23
- package/sdk-core/core-c-bridge/src/testing.rs +1 -4
- package/sdk-core/core-c-bridge/src/tests/context.rs +31 -31
- package/sdk-core/core-c-bridge/src/tests/mod.rs +32 -28
- package/sdk-core/core-c-bridge/src/tests/utils.rs +7 -7
- package/sdk-core/core-c-bridge/src/worker.rs +319 -66
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +6 -1
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +5 -5
- package/sdk-core/sdk/Cargo.toml +8 -2
- package/sdk-core/sdk/src/activity_context.rs +1 -1
- package/sdk-core/sdk/src/app_data.rs +1 -1
- package/sdk-core/sdk/src/interceptors.rs +1 -4
- package/sdk-core/sdk/src/lib.rs +1 -5
- package/sdk-core/sdk/src/workflow_context/options.rs +10 -1
- package/sdk-core/sdk/src/workflow_future.rs +1 -1
- package/sdk-core/sdk-core-protos/Cargo.toml +6 -6
- package/sdk-core/sdk-core-protos/build.rs +10 -23
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/create-release.yml +9 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +254 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +234 -5
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +1 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +6 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +30 -6
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
- package/sdk-core/{test-utils → sdk-core-protos}/src/canned_histories.rs +5 -5
- package/sdk-core/sdk-core-protos/src/history_builder.rs +2 -2
- package/sdk-core/sdk-core-protos/src/lib.rs +25 -9
- package/sdk-core/sdk-core-protos/src/test_utils.rs +89 -0
- package/sdk-core/sdk-core-protos/src/utilities.rs +14 -5
- package/sdk-core/tests/c_bridge_smoke_test.c +10 -0
- package/sdk-core/tests/cloud_tests.rs +10 -8
- package/sdk-core/tests/common/http_proxy.rs +134 -0
- package/sdk-core/{test-utils/src/lib.rs → tests/common/mod.rs} +214 -281
- package/sdk-core/{test-utils/src → tests/common}/workflows.rs +4 -3
- package/sdk-core/tests/fuzzy_workflow.rs +1 -1
- package/sdk-core/tests/global_metric_tests.rs +8 -7
- package/sdk-core/tests/heavy_tests.rs +7 -3
- package/sdk-core/tests/integ_tests/client_tests.rs +111 -24
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +14 -9
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +4 -4
- package/sdk-core/tests/integ_tests/metrics_tests.rs +114 -14
- package/sdk-core/tests/integ_tests/pagination_tests.rs +273 -0
- package/sdk-core/tests/integ_tests/polling_tests.rs +311 -93
- package/sdk-core/tests/integ_tests/queries_tests.rs +4 -4
- package/sdk-core/tests/integ_tests/update_tests.rs +13 -7
- package/sdk-core/tests/integ_tests/visibility_tests.rs +26 -9
- package/sdk-core/tests/integ_tests/worker_tests.rs +668 -13
- package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +40 -24
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +244 -11
- package/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +78 -2
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +61 -2
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +465 -7
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +41 -2
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +315 -3
- package/sdk-core/tests/integ_tests/workflow_tests/eager.rs +1 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +1990 -14
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +65 -2
- package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +123 -23
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +525 -3
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +65 -16
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +32 -23
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +126 -5
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +1 -2
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +124 -8
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +62 -2
- package/sdk-core/tests/integ_tests/workflow_tests.rs +67 -8
- package/sdk-core/tests/main.rs +26 -17
- package/sdk-core/tests/manual_tests.rs +5 -1
- package/sdk-core/tests/runner.rs +22 -40
- package/sdk-core/tests/shared_tests/mod.rs +1 -1
- package/sdk-core/tests/shared_tests/priority.rs +1 -1
- package/sdk-core/{core/benches/workflow_replay.rs → tests/workflow_replay_bench.rs} +10 -5
- package/src/client.rs +97 -20
- package/src/helpers/callbacks.rs +4 -4
- package/src/helpers/errors.rs +7 -1
- package/src/helpers/handles.rs +1 -0
- package/src/helpers/try_from_js.rs +4 -3
- package/src/lib.rs +3 -2
- package/src/metrics.rs +3 -0
- package/src/runtime.rs +5 -2
- package/src/worker.rs +9 -12
- package/ts/native.ts +13 -3
- package/sdk-core/arch_docs/diagrams/workflow_internals.svg +0 -1
- package/sdk-core/core/src/core_tests/child_workflows.rs +0 -281
- package/sdk-core/core/src/core_tests/determinism.rs +0 -318
- package/sdk-core/core/src/core_tests/local_activities.rs +0 -1442
- package/sdk-core/test-utils/Cargo.toml +0 -38
- package/sdk-core/test-utils/src/histfetch.rs +0 -28
- package/sdk-core/test-utils/src/interceptors.rs +0 -46
|
@@ -2,9 +2,11 @@ use crate::{
|
|
|
2
2
|
ByteArray, ByteArrayRef, ByteArrayRefArray, UserDataHandle, client::Client, runtime::Runtime,
|
|
3
3
|
};
|
|
4
4
|
use anyhow::{Context, bail};
|
|
5
|
+
use crossbeam_utils::atomic::AtomicCell;
|
|
5
6
|
use prost::Message;
|
|
6
7
|
use std::{
|
|
7
8
|
collections::{HashMap, HashSet},
|
|
9
|
+
num::NonZero,
|
|
8
10
|
sync::Arc,
|
|
9
11
|
time::Duration,
|
|
10
12
|
};
|
|
@@ -22,14 +24,14 @@ use temporal_sdk_core_api::{
|
|
|
22
24
|
};
|
|
23
25
|
use temporal_sdk_core_protos::{
|
|
24
26
|
coresdk::{
|
|
25
|
-
ActivityHeartbeat, ActivityTaskCompletion,
|
|
27
|
+
ActivityHeartbeat, ActivityTaskCompletion, nexus::NexusTaskCompletion,
|
|
26
28
|
workflow_completion::WorkflowActivationCompletion,
|
|
27
29
|
},
|
|
28
30
|
temporal::api::history::v1::History,
|
|
29
31
|
};
|
|
30
32
|
use tokio::sync::{
|
|
33
|
+
Notify,
|
|
31
34
|
mpsc::{Sender, channel},
|
|
32
|
-
oneshot,
|
|
33
35
|
};
|
|
34
36
|
use tokio_stream::wrappers::ReceiverStream;
|
|
35
37
|
|
|
@@ -51,6 +53,7 @@ pub struct WorkerOptions {
|
|
|
51
53
|
pub workflow_task_poller_behavior: PollerBehavior,
|
|
52
54
|
pub nonsticky_to_sticky_poll_ratio: f32,
|
|
53
55
|
pub activity_task_poller_behavior: PollerBehavior,
|
|
56
|
+
pub nexus_task_poller_behavior: PollerBehavior,
|
|
54
57
|
pub nondeterminism_as_workflow_fail: bool,
|
|
55
58
|
pub nondeterminism_as_workflow_fail_for_types: ByteArrayRefArray,
|
|
56
59
|
}
|
|
@@ -130,6 +133,7 @@ pub struct TunerHolder {
|
|
|
130
133
|
pub workflow_slot_supplier: SlotSupplier,
|
|
131
134
|
pub activity_slot_supplier: SlotSupplier,
|
|
132
135
|
pub local_activity_slot_supplier: SlotSupplier,
|
|
136
|
+
pub nexus_task_slot_supplier: SlotSupplier,
|
|
133
137
|
}
|
|
134
138
|
|
|
135
139
|
#[repr(C)]
|
|
@@ -163,14 +167,24 @@ struct CustomSlotSupplier<SK> {
|
|
|
163
167
|
unsafe impl<SK> Send for CustomSlotSupplier<SK> {}
|
|
164
168
|
unsafe impl<SK> Sync for CustomSlotSupplier<SK> {}
|
|
165
169
|
|
|
166
|
-
pub type
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
pub type
|
|
172
|
-
|
|
173
|
-
|
|
170
|
+
pub type CustomSlotSupplierReserveCallback = unsafe extern "C" fn(
|
|
171
|
+
ctx: *const SlotReserveCtx,
|
|
172
|
+
completion_ctx: *const SlotReserveCompletionCtx,
|
|
173
|
+
user_data: *mut libc::c_void,
|
|
174
|
+
);
|
|
175
|
+
pub type CustomSlotSupplierCancelReserveCallback = unsafe extern "C" fn(
|
|
176
|
+
completion_ctx: *const SlotReserveCompletionCtx,
|
|
177
|
+
user_data: *mut libc::c_void,
|
|
178
|
+
);
|
|
179
|
+
pub type CustomSlotSupplierTryReserveCallback =
|
|
180
|
+
unsafe extern "C" fn(ctx: *const SlotReserveCtx, user_data: *mut libc::c_void) -> usize;
|
|
181
|
+
pub type CustomSlotSupplierMarkUsedCallback =
|
|
182
|
+
unsafe extern "C" fn(ctx: *const SlotMarkUsedCtx, user_data: *mut libc::c_void);
|
|
183
|
+
pub type CustomSlotSupplierReleaseCallback =
|
|
184
|
+
unsafe extern "C" fn(ctx: *const SlotReleaseCtx, user_data: *mut libc::c_void);
|
|
185
|
+
pub type CustomSlotSupplierAvailableSlotsCallback =
|
|
186
|
+
Option<unsafe extern "C" fn(available_slots: *mut usize, user_data: *mut libc::c_void) -> bool>;
|
|
187
|
+
pub type CustomSlotSupplierFreeCallback =
|
|
174
188
|
unsafe extern "C" fn(userimpl: *const CustomSlotSupplierCallbacks);
|
|
175
189
|
|
|
176
190
|
#[repr(C)]
|
|
@@ -179,12 +193,46 @@ pub struct CustomSlotSupplierCallbacksImpl(pub *const CustomSlotSupplierCallback
|
|
|
179
193
|
|
|
180
194
|
#[repr(C)]
|
|
181
195
|
pub struct CustomSlotSupplierCallbacks {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
196
|
+
/// Called to initiate asynchronous slot reservation. `ctx` contains information about
|
|
197
|
+
/// reservation request. The pointer is only valid for the duration of the function call; the
|
|
198
|
+
/// implementation should copy the data out of it for later use, and return as soon as possible.
|
|
199
|
+
///
|
|
200
|
+
/// When slot is reserved, the implementation should call [`temporal_core_complete_async_reserve`]
|
|
201
|
+
/// with the same `completion_ctx` as passed to this function. Reservation cannot be cancelled
|
|
202
|
+
/// by Lang, but it can be cancelled by Core through [`cancel_reserve`](Self::cancel_reserve)
|
|
203
|
+
/// callback. If reservation was cancelled, [`temporal_core_complete_async_cancel_reserve`]
|
|
204
|
+
/// should be called instead.
|
|
205
|
+
///
|
|
206
|
+
/// Slot reservation cannot error. The implementation should recover from errors and keep trying
|
|
207
|
+
/// to reserve a slot until it eventually succeeds, or until reservation is cancelled by Core.
|
|
208
|
+
pub reserve: CustomSlotSupplierReserveCallback,
|
|
209
|
+
/// Called to cancel slot reservation. `completion_ctx` specifies which reservation is being
|
|
210
|
+
/// cancelled; the matching [`reserve`](Self::reserve) call was made with the same `completion_ctx`.
|
|
211
|
+
/// After cancellation, the implementation should call [`temporal_core_complete_async_cancel_reserve`]
|
|
212
|
+
/// with the same `completion_ctx`. Calling [`temporal_core_complete_async_reserve`] is not
|
|
213
|
+
/// needed after cancellation.
|
|
214
|
+
pub cancel_reserve: CustomSlotSupplierCancelReserveCallback,
|
|
215
|
+
/// Called to try an immediate slot reservation. The callback should return 0 if immediate
|
|
216
|
+
/// reservation is not currently possible, or permit ID if reservation was successful. Permit ID
|
|
217
|
+
/// is arbitrary, but must be unique among live reservations as it's later used for [`mark_used`](Self::mark_used)
|
|
218
|
+
/// and [`release`](Self::release) callbacks.
|
|
219
|
+
pub try_reserve: CustomSlotSupplierTryReserveCallback,
|
|
220
|
+
/// Called after successful reservation to mark slot as used. See [`SlotSupplier`](temporal_sdk_core_api::worker::SlotSupplier)
|
|
221
|
+
/// trait for details.
|
|
222
|
+
pub mark_used: CustomSlotSupplierMarkUsedCallback,
|
|
223
|
+
/// Called to free a previously reserved slot.
|
|
224
|
+
pub release: CustomSlotSupplierReleaseCallback,
|
|
225
|
+
/// Called to retrieve the number of available slots if known. If the implementation knows how
|
|
226
|
+
/// many slots are available at the moment, it should set the value behind the `available_slots`
|
|
227
|
+
/// pointer and return true. If that number is unknown, it should return false.
|
|
228
|
+
///
|
|
229
|
+
/// This function pointer can be set to null. It will be treated as if the number of available
|
|
230
|
+
/// slots is never known.
|
|
231
|
+
pub available_slots: CustomSlotSupplierAvailableSlotsCallback,
|
|
232
|
+
/// Called when the slot supplier is being dropped. All resources should be freed.
|
|
233
|
+
pub free: CustomSlotSupplierFreeCallback,
|
|
234
|
+
/// Passed as an extra argument to the callbacks.
|
|
235
|
+
pub user_data: *mut libc::c_void,
|
|
188
236
|
}
|
|
189
237
|
|
|
190
238
|
impl CustomSlotSupplierCallbacksImpl {
|
|
@@ -221,8 +269,6 @@ pub struct SlotReserveCtx {
|
|
|
221
269
|
pub worker_identity: ByteArrayRef,
|
|
222
270
|
pub worker_build_id: ByteArrayRef,
|
|
223
271
|
pub is_sticky: bool,
|
|
224
|
-
// The C# side will store a pointer here to the cancellation token source
|
|
225
|
-
pub token_src: *mut libc::c_void,
|
|
226
272
|
}
|
|
227
273
|
unsafe impl Send for SlotReserveCtx {}
|
|
228
274
|
|
|
@@ -247,31 +293,67 @@ pub enum SlotInfo {
|
|
|
247
293
|
#[repr(C)]
|
|
248
294
|
pub struct SlotMarkUsedCtx {
|
|
249
295
|
pub slot_info: SlotInfo,
|
|
250
|
-
///
|
|
296
|
+
/// Lang-issued permit ID.
|
|
251
297
|
pub slot_permit: usize,
|
|
252
298
|
}
|
|
253
299
|
|
|
254
300
|
#[repr(C)]
|
|
255
301
|
pub struct SlotReleaseCtx {
|
|
256
302
|
pub slot_info: *const SlotInfo,
|
|
257
|
-
///
|
|
303
|
+
/// Lang-issued permit ID.
|
|
258
304
|
pub slot_permit: usize,
|
|
259
305
|
}
|
|
260
306
|
|
|
261
|
-
struct
|
|
262
|
-
|
|
263
|
-
|
|
307
|
+
pub struct SlotReserveCompletionCtx {
|
|
308
|
+
state: AtomicCell<SlotReserveOperationState>,
|
|
309
|
+
notify: Notify,
|
|
264
310
|
}
|
|
265
|
-
|
|
311
|
+
|
|
312
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
313
|
+
enum SlotReserveOperationState {
|
|
314
|
+
Pending,
|
|
315
|
+
Cancelled,
|
|
316
|
+
Completed(NonZero<usize>),
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
struct CancelReserveGuard<'a, SK: SlotKind + Send + Sync> {
|
|
320
|
+
slot_supplier: &'a CustomSlotSupplier<SK>,
|
|
321
|
+
completion_ctx: Arc<SlotReserveCompletionCtx>,
|
|
322
|
+
completed: bool,
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
impl<'a, SK: SlotKind + Send + Sync> Drop for CancelReserveGuard<'a, SK> {
|
|
266
326
|
fn drop(&mut self) {
|
|
267
|
-
if
|
|
327
|
+
// do not cancel if already completed
|
|
328
|
+
if !self.completed {
|
|
329
|
+
let state = self
|
|
330
|
+
.completion_ctx
|
|
331
|
+
.state
|
|
332
|
+
.swap(SlotReserveOperationState::Cancelled);
|
|
268
333
|
unsafe {
|
|
269
|
-
|
|
334
|
+
let inner = &*self.slot_supplier.inner.0;
|
|
335
|
+
match state {
|
|
336
|
+
SlotReserveOperationState::Cancelled => {
|
|
337
|
+
// This situation should never happen, but on the other hand, it doesn't
|
|
338
|
+
// result in any unsafety, deadlock or leak. It's safe to ignore it, but in
|
|
339
|
+
// debug builds we'd like to know it happened.
|
|
340
|
+
debug_assert!(false, "slot reservation cancelled twice")
|
|
341
|
+
}
|
|
342
|
+
SlotReserveOperationState::Pending => {
|
|
343
|
+
(inner.cancel_reserve)(Arc::as_ptr(&self.completion_ctx), inner.user_data)
|
|
344
|
+
}
|
|
345
|
+
SlotReserveOperationState::Completed(slot_permit) => (inner.release)(
|
|
346
|
+
&SlotReleaseCtx {
|
|
347
|
+
slot_info: std::ptr::null(),
|
|
348
|
+
slot_permit: slot_permit.into(),
|
|
349
|
+
},
|
|
350
|
+
inner.user_data,
|
|
351
|
+
),
|
|
352
|
+
}
|
|
270
353
|
}
|
|
271
354
|
}
|
|
272
355
|
}
|
|
273
356
|
}
|
|
274
|
-
unsafe impl Send for CancelReserveGuard {}
|
|
275
357
|
|
|
276
358
|
#[async_trait::async_trait]
|
|
277
359
|
impl<SK: SlotKind + Send + Sync> temporal_sdk_core_api::worker::SlotSupplier
|
|
@@ -280,36 +362,53 @@ impl<SK: SlotKind + Send + Sync> temporal_sdk_core_api::worker::SlotSupplier
|
|
|
280
362
|
type SlotKind = SK;
|
|
281
363
|
|
|
282
364
|
async fn reserve_slot(&self, ctx: &dyn SlotReservationContext) -> SlotSupplierPermit {
|
|
283
|
-
let (tx, rx) = oneshot::channel();
|
|
284
365
|
let ctx = Self::convert_reserve_ctx(ctx);
|
|
285
|
-
let
|
|
366
|
+
let completion_ctx = Arc::new(SlotReserveCompletionCtx {
|
|
367
|
+
state: AtomicCell::new(SlotReserveOperationState::Pending),
|
|
368
|
+
notify: Notify::new(),
|
|
369
|
+
});
|
|
286
370
|
unsafe {
|
|
287
|
-
let
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
371
|
+
let inner = &*self.inner.0;
|
|
372
|
+
(inner.reserve)(&ctx, Arc::into_raw(completion_ctx.clone()), inner.user_data);
|
|
373
|
+
}
|
|
374
|
+
let mut guard = CancelReserveGuard {
|
|
375
|
+
slot_supplier: self,
|
|
376
|
+
completion_ctx,
|
|
377
|
+
completed: false,
|
|
378
|
+
};
|
|
379
|
+
// if the future is dropped before this await resolves, the guard is dropped which triggers cancellation
|
|
380
|
+
guard.completion_ctx.notify.notified().await;
|
|
381
|
+
guard.completed = true;
|
|
382
|
+
match guard.completion_ctx.state.load() {
|
|
383
|
+
SlotReserveOperationState::Completed(permit_id) => {
|
|
384
|
+
SlotSupplierPermit::with_user_data::<usize>(permit_id.get())
|
|
385
|
+
}
|
|
386
|
+
other => panic!("Unexpected slot reservation state: expected Completed, got {other:?}"),
|
|
293
387
|
}
|
|
294
388
|
}
|
|
295
389
|
|
|
296
390
|
fn try_reserve_slot(&self, ctx: &dyn SlotReservationContext) -> Option<SlotSupplierPermit> {
|
|
297
391
|
let ctx = Self::convert_reserve_ctx(ctx);
|
|
298
|
-
let permit_id = unsafe { ((*self.inner.0).try_reserve)(&ctx) };
|
|
392
|
+
let permit_id = unsafe { ((*self.inner.0).try_reserve)(&ctx, (*self.inner.0).user_data) };
|
|
299
393
|
if permit_id == 0 {
|
|
300
394
|
None
|
|
301
395
|
} else {
|
|
302
|
-
Some(SlotSupplierPermit::with_user_data(permit_id))
|
|
396
|
+
Some(SlotSupplierPermit::with_user_data::<usize>(permit_id))
|
|
303
397
|
}
|
|
304
398
|
}
|
|
305
399
|
|
|
306
400
|
fn mark_slot_used(&self, ctx: &dyn SlotMarkUsedContext<SlotKind = Self::SlotKind>) {
|
|
307
401
|
let ctx = SlotMarkUsedCtx {
|
|
308
402
|
slot_info: Self::convert_slot_info(ctx.info().downcast()),
|
|
309
|
-
slot_permit: ctx
|
|
403
|
+
slot_permit: ctx
|
|
404
|
+
.permit()
|
|
405
|
+
.user_data::<usize>()
|
|
406
|
+
.copied()
|
|
407
|
+
.expect("permit user data should be usize"),
|
|
310
408
|
};
|
|
311
409
|
unsafe {
|
|
312
|
-
|
|
410
|
+
let inner = &*self.inner.0;
|
|
411
|
+
(inner.mark_used)(&ctx, inner.user_data);
|
|
313
412
|
}
|
|
314
413
|
}
|
|
315
414
|
|
|
@@ -321,15 +420,26 @@ impl<SK: SlotKind + Send + Sync> temporal_sdk_core_api::worker::SlotSupplier
|
|
|
321
420
|
}
|
|
322
421
|
let ctx = SlotReleaseCtx {
|
|
323
422
|
slot_info: info_ptr,
|
|
324
|
-
slot_permit: ctx
|
|
423
|
+
slot_permit: ctx
|
|
424
|
+
.permit()
|
|
425
|
+
.user_data::<usize>()
|
|
426
|
+
.copied()
|
|
427
|
+
.expect("permit user data should be usize"),
|
|
325
428
|
};
|
|
326
429
|
unsafe {
|
|
327
|
-
|
|
430
|
+
let inner = &*self.inner.0;
|
|
431
|
+
(inner.release)(&ctx, inner.user_data);
|
|
328
432
|
}
|
|
329
433
|
}
|
|
330
434
|
|
|
331
435
|
fn available_slots(&self) -> Option<usize> {
|
|
332
|
-
|
|
436
|
+
unsafe {
|
|
437
|
+
let inner = &*self.inner.0;
|
|
438
|
+
inner.available_slots.and_then(|f| {
|
|
439
|
+
let mut available_slots = 0;
|
|
440
|
+
f(&mut available_slots, inner.user_data).then_some(available_slots)
|
|
441
|
+
})
|
|
442
|
+
}
|
|
333
443
|
}
|
|
334
444
|
}
|
|
335
445
|
|
|
@@ -358,7 +468,6 @@ impl<SK: SlotKind + Send + Sync> CustomSlotSupplier<SK> {
|
|
|
358
468
|
ByteArrayRef::empty()
|
|
359
469
|
},
|
|
360
470
|
is_sticky: ctx.is_sticky(),
|
|
361
|
-
token_src: std::ptr::null_mut(),
|
|
362
471
|
}
|
|
363
472
|
}
|
|
364
473
|
|
|
@@ -378,7 +487,7 @@ impl<SK: SlotKind + Send + Sync> CustomSlotSupplier<SK> {
|
|
|
378
487
|
}
|
|
379
488
|
temporal_sdk_core_api::worker::SlotInfo::Nexus(n) => SlotInfo::NexusSlotInfo {
|
|
380
489
|
operation: n.operation.as_str().into(),
|
|
381
|
-
service: n.
|
|
490
|
+
service: n.service.as_str().into(),
|
|
382
491
|
},
|
|
383
492
|
}
|
|
384
493
|
}
|
|
@@ -558,7 +667,7 @@ pub extern "C" fn temporal_core_worker_poll_workflow_activation(
|
|
|
558
667
|
worker
|
|
559
668
|
.runtime
|
|
560
669
|
.clone()
|
|
561
|
-
.alloc_utf8(&format!("
|
|
670
|
+
.alloc_utf8(&format!("Workflow polling failure: {err}"))
|
|
562
671
|
.into_raw()
|
|
563
672
|
.cast_const(),
|
|
564
673
|
),
|
|
@@ -592,7 +701,41 @@ pub extern "C" fn temporal_core_worker_poll_activity_task(
|
|
|
592
701
|
worker
|
|
593
702
|
.runtime
|
|
594
703
|
.clone()
|
|
595
|
-
.alloc_utf8(&format!("
|
|
704
|
+
.alloc_utf8(&format!("Activity polling failure: {err}"))
|
|
705
|
+
.into_raw()
|
|
706
|
+
.cast_const(),
|
|
707
|
+
),
|
|
708
|
+
};
|
|
709
|
+
unsafe {
|
|
710
|
+
callback(user_data.into(), success, fail);
|
|
711
|
+
}
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
#[unsafe(no_mangle)]
|
|
716
|
+
pub extern "C" fn temporal_core_worker_poll_nexus_task(
|
|
717
|
+
worker: *mut Worker,
|
|
718
|
+
user_data: *mut libc::c_void,
|
|
719
|
+
callback: WorkerPollCallback,
|
|
720
|
+
) {
|
|
721
|
+
let worker = unsafe { &*worker };
|
|
722
|
+
let user_data = UserDataHandle(user_data);
|
|
723
|
+
let core_worker = worker.worker.as_ref().unwrap().clone();
|
|
724
|
+
worker.runtime.core.tokio_handle().spawn(async move {
|
|
725
|
+
let (success, fail) = match core_worker.poll_nexus_task().await {
|
|
726
|
+
Ok(task) => (
|
|
727
|
+
ByteArray::from_vec(task.encode_to_vec())
|
|
728
|
+
.into_raw()
|
|
729
|
+
.cast_const(),
|
|
730
|
+
std::ptr::null(),
|
|
731
|
+
),
|
|
732
|
+
Err(PollError::ShutDown) => (std::ptr::null(), std::ptr::null()),
|
|
733
|
+
Err(err) => (
|
|
734
|
+
std::ptr::null(),
|
|
735
|
+
worker
|
|
736
|
+
.runtime
|
|
737
|
+
.clone()
|
|
738
|
+
.alloc_utf8(&format!("Nexus polling failure: {err}"))
|
|
596
739
|
.into_raw()
|
|
597
740
|
.cast_const(),
|
|
598
741
|
),
|
|
@@ -620,7 +763,7 @@ pub extern "C" fn temporal_core_worker_complete_workflow_activation(
|
|
|
620
763
|
worker
|
|
621
764
|
.runtime
|
|
622
765
|
.clone()
|
|
623
|
-
.alloc_utf8(&format!("
|
|
766
|
+
.alloc_utf8(&format!("Workflow task decode failure: {err}"))
|
|
624
767
|
.into_raw(),
|
|
625
768
|
);
|
|
626
769
|
}
|
|
@@ -635,7 +778,7 @@ pub extern "C" fn temporal_core_worker_complete_workflow_activation(
|
|
|
635
778
|
Err(err) => worker
|
|
636
779
|
.runtime
|
|
637
780
|
.clone()
|
|
638
|
-
.alloc_utf8(&format!("
|
|
781
|
+
.alloc_utf8(&format!("Workflow completion failure: {err}"))
|
|
639
782
|
.into_raw()
|
|
640
783
|
.cast_const(),
|
|
641
784
|
};
|
|
@@ -662,7 +805,7 @@ pub extern "C" fn temporal_core_worker_complete_activity_task(
|
|
|
662
805
|
worker
|
|
663
806
|
.runtime
|
|
664
807
|
.clone()
|
|
665
|
-
.alloc_utf8(&format!("
|
|
808
|
+
.alloc_utf8(&format!("Activity task decode failure: {err}"))
|
|
666
809
|
.into_raw(),
|
|
667
810
|
);
|
|
668
811
|
}
|
|
@@ -677,7 +820,49 @@ pub extern "C" fn temporal_core_worker_complete_activity_task(
|
|
|
677
820
|
Err(err) => worker
|
|
678
821
|
.runtime
|
|
679
822
|
.clone()
|
|
680
|
-
.alloc_utf8(&format!("
|
|
823
|
+
.alloc_utf8(&format!("Activity completion failure: {err}"))
|
|
824
|
+
.into_raw()
|
|
825
|
+
.cast_const(),
|
|
826
|
+
};
|
|
827
|
+
unsafe {
|
|
828
|
+
callback(user_data.into(), fail);
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
#[unsafe(no_mangle)]
|
|
834
|
+
pub extern "C" fn temporal_core_worker_complete_nexus_task(
|
|
835
|
+
worker: *mut Worker,
|
|
836
|
+
completion: ByteArrayRef,
|
|
837
|
+
user_data: *mut libc::c_void,
|
|
838
|
+
callback: WorkerCallback,
|
|
839
|
+
) {
|
|
840
|
+
let worker = unsafe { &*worker };
|
|
841
|
+
let completion = match NexusTaskCompletion::decode(completion.to_slice()) {
|
|
842
|
+
Ok(completion) => completion,
|
|
843
|
+
Err(err) => {
|
|
844
|
+
unsafe {
|
|
845
|
+
callback(
|
|
846
|
+
user_data,
|
|
847
|
+
worker
|
|
848
|
+
.runtime
|
|
849
|
+
.clone()
|
|
850
|
+
.alloc_utf8(&format!("Nexus task decode failure: {err}"))
|
|
851
|
+
.into_raw(),
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
let user_data = UserDataHandle(user_data);
|
|
858
|
+
let core_worker = worker.worker.as_ref().unwrap().clone();
|
|
859
|
+
worker.runtime.core.tokio_handle().spawn(async move {
|
|
860
|
+
let fail = match core_worker.complete_nexus_task(completion).await {
|
|
861
|
+
Ok(_) => std::ptr::null(),
|
|
862
|
+
Err(err) => worker
|
|
863
|
+
.runtime
|
|
864
|
+
.clone()
|
|
865
|
+
.alloc_utf8(&format!("Nexus completion failure: {err}"))
|
|
681
866
|
.into_raw()
|
|
682
867
|
.cast_const(),
|
|
683
868
|
};
|
|
@@ -707,7 +892,7 @@ pub extern "C" fn temporal_core_worker_record_activity_heartbeat(
|
|
|
707
892
|
Err(err) => worker
|
|
708
893
|
.runtime
|
|
709
894
|
.clone()
|
|
710
|
-
.alloc_utf8(&format!("
|
|
895
|
+
.alloc_utf8(&format!("Activity heartbeat decode failure: {err}"))
|
|
711
896
|
.into_raw(),
|
|
712
897
|
}
|
|
713
898
|
}
|
|
@@ -861,29 +1046,88 @@ pub extern "C" fn temporal_core_worker_replay_push(
|
|
|
861
1046
|
}
|
|
862
1047
|
}
|
|
863
1048
|
|
|
1049
|
+
/// Completes asynchronous slot reservation started by a call to [`CustomSlotSupplierCallbacks::reserve`].
|
|
1050
|
+
///
|
|
1051
|
+
/// `completion_ctx` must be the same as the one passed to the matching [`reserve`](CustomSlotSupplierCallbacks::reserve)
|
|
1052
|
+
/// call. `permit_id` is arbitrary, but must be unique among live reservations as it's later used
|
|
1053
|
+
/// for [`mark_used`](CustomSlotSupplierCallbacks::mark_used) and [`release`](CustomSlotSupplierCallbacks::release)
|
|
1054
|
+
/// callbacks.
|
|
1055
|
+
///
|
|
1056
|
+
/// This function returns true if the reservation was completed successfully, or false if the
|
|
1057
|
+
/// reservation was cancelled before completion. If this function returns false, the implementation
|
|
1058
|
+
/// should call [`temporal_core_complete_async_cancel_reserve`] with the same `completion_ctx`.
|
|
1059
|
+
///
|
|
1060
|
+
/// **Caution:** if this function returns true, `completion_ctx` gets freed. Afterwards, calling
|
|
1061
|
+
/// either [`temporal_core_complete_async_reserve`] or [`temporal_core_complete_async_cancel_reserve`]
|
|
1062
|
+
/// with the same `completion_ctx` will cause **memory corruption!**
|
|
864
1063
|
#[unsafe(no_mangle)]
|
|
865
1064
|
pub extern "C" fn temporal_core_complete_async_reserve(
|
|
866
|
-
|
|
1065
|
+
completion_ctx: *const SlotReserveCompletionCtx,
|
|
867
1066
|
permit_id: usize,
|
|
868
|
-
) {
|
|
869
|
-
if
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
1067
|
+
) -> bool {
|
|
1068
|
+
if completion_ctx.is_null() {
|
|
1069
|
+
panic!("completion_ctx is null");
|
|
1070
|
+
}
|
|
1071
|
+
let permit_id =
|
|
1072
|
+
NonZero::new(permit_id).expect("permit_id cannot be 0 on successful reservation");
|
|
1073
|
+
let prev_state = unsafe {
|
|
1074
|
+
// Not turning completion_ctx into Arc yet as we only want to deallocate it on success
|
|
1075
|
+
(*completion_ctx).state.compare_exchange(
|
|
1076
|
+
SlotReserveOperationState::Pending,
|
|
1077
|
+
SlotReserveOperationState::Completed(permit_id),
|
|
1078
|
+
)
|
|
1079
|
+
};
|
|
1080
|
+
match prev_state {
|
|
1081
|
+
Ok(_) => {
|
|
1082
|
+
let completion_ctx = unsafe { Arc::from_raw(completion_ctx) };
|
|
1083
|
+
completion_ctx.notify.notify_one();
|
|
1084
|
+
true
|
|
874
1085
|
}
|
|
875
|
-
|
|
876
|
-
|
|
1086
|
+
Err(SlotReserveOperationState::Cancelled) => false,
|
|
1087
|
+
Err(SlotReserveOperationState::Completed(prev_permit_id)) => {
|
|
1088
|
+
panic!(
|
|
1089
|
+
"temporal_core_complete_async_reserve called twice for the same reservation - first permit ID {prev_permit_id}, second permit ID {permit_id}"
|
|
1090
|
+
)
|
|
1091
|
+
}
|
|
1092
|
+
Err(SlotReserveOperationState::Pending) => unreachable!(),
|
|
877
1093
|
}
|
|
878
1094
|
}
|
|
879
1095
|
|
|
1096
|
+
/// Completes cancellation of asynchronous slot reservation.
|
|
1097
|
+
///
|
|
1098
|
+
/// Cancellation can only be initiated by Core. It's done by calling [`CustomSlotSupplierCallbacks::cancel_reserve`]
|
|
1099
|
+
/// after an earlier call to [`CustomSlotSupplierCallbacks::reserve`].
|
|
1100
|
+
///
|
|
1101
|
+
/// `completion_ctx` must be the same as the one passed to the matching [`cancel_reserve`](CustomSlotSupplierCallbacks::cancel_reserve)
|
|
1102
|
+
/// call.
|
|
1103
|
+
///
|
|
1104
|
+
/// This function returns true on successful cancellation, or false if cancellation was not
|
|
1105
|
+
/// requested for the given `completion_ctx`. A false value indicates there's likely a logic bug in
|
|
1106
|
+
/// the implementation where it doesn't correctly wait for [`cancel_reserve`](CustomSlotSupplierCallbacks::cancel_reserve)
|
|
1107
|
+
/// callback to be called.
|
|
1108
|
+
///
|
|
1109
|
+
/// **Caution:** if this function returns true, `completion_ctx` gets freed. Afterwards, calling
|
|
1110
|
+
/// either [`temporal_core_complete_async_reserve`] or [`temporal_core_complete_async_cancel_reserve`]
|
|
1111
|
+
/// with the same `completion_ctx` will cause **memory corruption!**
|
|
880
1112
|
#[unsafe(no_mangle)]
|
|
881
|
-
pub extern "C" fn
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
) {
|
|
885
|
-
|
|
886
|
-
|
|
1113
|
+
pub extern "C" fn temporal_core_complete_async_cancel_reserve(
|
|
1114
|
+
completion_ctx: *const SlotReserveCompletionCtx,
|
|
1115
|
+
) -> bool {
|
|
1116
|
+
if completion_ctx.is_null() {
|
|
1117
|
+
panic!("completion_ctx is null");
|
|
1118
|
+
}
|
|
1119
|
+
let state = unsafe { (*completion_ctx).state.load() };
|
|
1120
|
+
match state {
|
|
1121
|
+
SlotReserveOperationState::Cancelled => {
|
|
1122
|
+
drop(unsafe { Arc::from_raw(completion_ctx) });
|
|
1123
|
+
true
|
|
1124
|
+
}
|
|
1125
|
+
SlotReserveOperationState::Pending => false,
|
|
1126
|
+
SlotReserveOperationState::Completed(permit_id) => {
|
|
1127
|
+
panic!(
|
|
1128
|
+
"temporal_core_complete_async_cancel_reserve called on completed reservation - permit ID {permit_id}"
|
|
1129
|
+
)
|
|
1130
|
+
}
|
|
887
1131
|
}
|
|
888
1132
|
}
|
|
889
1133
|
|
|
@@ -958,6 +1202,7 @@ impl TryFrom<&WorkerOptions> for temporal_sdk_core::WorkerConfig {
|
|
|
958
1202
|
.workflow_task_poller_behavior(temporal_sdk_core_api::worker::PollerBehavior::try_from(&opt.workflow_task_poller_behavior)?)
|
|
959
1203
|
.nonsticky_to_sticky_poll_ratio(opt.nonsticky_to_sticky_poll_ratio)
|
|
960
1204
|
.activity_task_poller_behavior(temporal_sdk_core_api::worker::PollerBehavior::try_from(&opt.activity_task_poller_behavior)?)
|
|
1205
|
+
.nexus_task_poller_behavior(temporal_sdk_core_api::worker::PollerBehavior::try_from(&opt.nexus_task_poller_behavior)?)
|
|
961
1206
|
.workflow_failure_errors(if opt.nondeterminism_as_workflow_fail {
|
|
962
1207
|
HashSet::from([WorkflowErrorType::Nondeterminism])
|
|
963
1208
|
} else {
|
|
@@ -1003,10 +1248,17 @@ impl TryFrom<&TunerHolder> for temporal_sdk_core::TunerHolder {
|
|
|
1003
1248
|
} else {
|
|
1004
1249
|
None
|
|
1005
1250
|
};
|
|
1251
|
+
let maybe_nexus_resource_opts =
|
|
1252
|
+
if let SlotSupplier::ResourceBased(ref ss) = holder.nexus_task_slot_supplier {
|
|
1253
|
+
Some(&ss.tuner_options)
|
|
1254
|
+
} else {
|
|
1255
|
+
None
|
|
1256
|
+
};
|
|
1006
1257
|
let all_resource_opts = [
|
|
1007
1258
|
maybe_wf_resource_opts,
|
|
1008
1259
|
maybe_act_resource_opts,
|
|
1009
1260
|
maybe_local_act_resource_opts,
|
|
1261
|
+
maybe_nexus_resource_opts,
|
|
1010
1262
|
];
|
|
1011
1263
|
let mut set_resource_opts = all_resource_opts.iter().flatten();
|
|
1012
1264
|
let first = set_resource_opts.next();
|
|
@@ -1033,6 +1285,7 @@ impl TryFrom<&TunerHolder> for temporal_sdk_core::TunerHolder {
|
|
|
1033
1285
|
.workflow_slot_options(holder.workflow_slot_supplier.try_into()?)
|
|
1034
1286
|
.activity_slot_options(holder.activity_slot_supplier.try_into()?)
|
|
1035
1287
|
.local_activity_slot_options(holder.local_activity_slot_supplier.try_into()?)
|
|
1288
|
+
.nexus_slot_options(holder.nexus_task_slot_supplier.try_into()?)
|
|
1036
1289
|
.build()
|
|
1037
1290
|
.context("Invalid tuner holder options")?
|
|
1038
1291
|
.build_tuner_holder()
|
|
@@ -434,6 +434,7 @@ impl StateMachineDefinition {
|
|
|
434
434
|
}
|
|
435
435
|
};
|
|
436
436
|
let mut multi_dest_enums = vec![];
|
|
437
|
+
let mut multi_dest_enum_names = HashSet::new();
|
|
437
438
|
let state_branches: Vec<_> = statemap.into_iter().map(|(from, transitions)| {
|
|
438
439
|
let occupied_current_state = quote! { Some(#state_enum_name::#from(state_data)) };
|
|
439
440
|
// Merge transition dest states with the same handler
|
|
@@ -468,7 +469,11 @@ impl StateMachineDefinition {
|
|
|
468
469
|
}
|
|
469
470
|
}
|
|
470
471
|
};
|
|
471
|
-
|
|
472
|
+
// Deduplicate; two different events may each result in a transition
|
|
473
|
+
// set with the same set of dest states
|
|
474
|
+
if multi_dest_enum_names.insert(enum_ident.clone()) {
|
|
475
|
+
multi_dest_enums.push(multi_dest_enum);
|
|
476
|
+
}
|
|
472
477
|
quote! {
|
|
473
478
|
#transition_result_name<#enum_ident>
|
|
474
479
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
error: Duplicate transitions are not allowed!
|
|
2
2
|
--> $DIR/dupe_transitions_fail.rs:5:1
|
|
3
3
|
|
|
|
4
|
-
5
|
|
5
|
-
6
|
|
6
|
-
7
|
|
7
|
-
8
|
|
8
|
-
9
|
|
4
|
+
5 | / fsm! {
|
|
5
|
+
6 | | name SimpleMachine; command SimpleMachineCommand; error Infallible;
|
|
6
|
+
7 | |
|
|
7
|
+
8 | | One --(A)--> Two;
|
|
8
|
+
9 | | One --(A)--> Two;
|
|
9
9
|
10 | | }
|
|
10
10
|
| |_^
|
|
11
11
|
|
|
package/sdk-core/sdk/Cargo.toml
CHANGED
|
@@ -16,9 +16,15 @@ anyhow = "1.0"
|
|
|
16
16
|
derive_more = { workspace = true }
|
|
17
17
|
futures-util = { version = "0.3", default-features = false }
|
|
18
18
|
parking_lot = { version = "0.12", features = ["send_guard"] }
|
|
19
|
-
prost-types = {
|
|
19
|
+
prost-types = { workspace = true }
|
|
20
20
|
serde = "1.0"
|
|
21
|
-
tokio = { version = "1.
|
|
21
|
+
tokio = { version = "1.47", features = [
|
|
22
|
+
"rt",
|
|
23
|
+
"rt-multi-thread",
|
|
24
|
+
"parking_lot",
|
|
25
|
+
"time",
|
|
26
|
+
"fs",
|
|
27
|
+
] }
|
|
22
28
|
tokio-util = { version = "0.7" }
|
|
23
29
|
tokio-stream = "0.1"
|
|
24
30
|
tracing = "0.1"
|
|
@@ -56,7 +56,7 @@ pub struct ActivityInfo {
|
|
|
56
56
|
impl ActContext {
|
|
57
57
|
/// Construct new Activity Context, returning the context and the first argument to the activity
|
|
58
58
|
/// (which may be a default [Payload]).
|
|
59
|
-
pub
|
|
59
|
+
pub fn new(
|
|
60
60
|
worker: Arc<dyn Worker>,
|
|
61
61
|
app_data: Arc<AppData>,
|
|
62
62
|
cancellation_token: CancellationToken,
|