@temporalio/core-bridge 0.16.4 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +339 -226
- package/Cargo.toml +7 -3
- package/common.js +50 -0
- package/index.d.ts +7 -0
- package/index.js +12 -0
- package/package.json +7 -4
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/{index.node → releases/index.node} +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/scripts/build.js +10 -50
- package/sdk-core/.buildkite/docker/Dockerfile +1 -1
- package/sdk-core/.buildkite/docker/docker-compose.yaml +2 -2
- package/sdk-core/.buildkite/pipeline.yml +2 -0
- package/sdk-core/Cargo.toml +1 -88
- package/sdk-core/README.md +30 -6
- package/sdk-core/bridge-ffi/Cargo.toml +24 -0
- package/sdk-core/bridge-ffi/LICENSE.txt +23 -0
- package/sdk-core/bridge-ffi/build.rs +25 -0
- package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +216 -0
- package/sdk-core/bridge-ffi/src/lib.rs +829 -0
- package/sdk-core/bridge-ffi/src/wrappers.rs +193 -0
- package/sdk-core/client/Cargo.toml +32 -0
- package/sdk-core/{src/pollers/gateway.rs → client/src/lib.rs} +101 -195
- package/sdk-core/client/src/metrics.rs +89 -0
- package/sdk-core/client/src/mocks.rs +167 -0
- package/sdk-core/{src/pollers → client/src}/retry.rs +172 -14
- package/sdk-core/core/Cargo.toml +96 -0
- package/sdk-core/{src → core/src}/core_tests/activity_tasks.rs +193 -37
- package/sdk-core/{src → core/src}/core_tests/child_workflows.rs +14 -14
- package/sdk-core/{src → core/src}/core_tests/determinism.rs +8 -8
- package/sdk-core/core/src/core_tests/local_activities.rs +328 -0
- package/sdk-core/{src → core/src}/core_tests/mod.rs +6 -9
- package/sdk-core/{src → core/src}/core_tests/queries.rs +54 -54
- package/sdk-core/{src → core/src}/core_tests/replay_flag.rs +8 -12
- package/sdk-core/{src → core/src}/core_tests/workers.rs +120 -33
- package/sdk-core/{src → core/src}/core_tests/workflow_cancels.rs +16 -26
- package/sdk-core/{src → core/src}/core_tests/workflow_tasks.rs +280 -292
- package/sdk-core/core/src/lib.rs +374 -0
- package/sdk-core/{src → core/src}/log_export.rs +3 -27
- package/sdk-core/core/src/pending_activations.rs +162 -0
- package/sdk-core/{src → core/src}/pollers/mod.rs +4 -22
- package/sdk-core/{src → core/src}/pollers/poll_buffer.rs +1 -1
- package/sdk-core/core/src/protosext/mod.rs +396 -0
- package/sdk-core/core/src/replay/mod.rs +210 -0
- package/sdk-core/core/src/retry_logic.rs +144 -0
- package/sdk-core/{src → core/src}/telemetry/metrics.rs +3 -58
- package/sdk-core/{src → core/src}/telemetry/mod.rs +8 -8
- package/sdk-core/{src → core/src}/telemetry/prometheus_server.rs +0 -0
- package/sdk-core/{src → core/src}/test_help/mod.rs +35 -83
- package/sdk-core/{src → core/src}/worker/activities/activity_heartbeat_manager.rs +95 -42
- package/sdk-core/core/src/worker/activities/local_activities.rs +973 -0
- package/sdk-core/{src → core/src}/worker/activities.rs +52 -33
- package/sdk-core/{src → core/src}/worker/dispatcher.rs +8 -6
- package/sdk-core/{src → core/src}/worker/mod.rs +347 -221
- package/sdk-core/core/src/worker/wft_delivery.rs +81 -0
- package/sdk-core/{src → core/src}/workflow/bridge.rs +5 -2
- package/sdk-core/{src → core/src}/workflow/driven_workflow.rs +17 -7
- package/sdk-core/{src → core/src}/workflow/history_update.rs +33 -7
- package/sdk-core/{src → core/src/workflow}/machines/activity_state_machine.rs +26 -26
- package/sdk-core/{src → core/src/workflow}/machines/cancel_external_state_machine.rs +8 -11
- package/sdk-core/{src → core/src/workflow}/machines/cancel_workflow_state_machine.rs +19 -21
- package/sdk-core/{src → core/src/workflow}/machines/child_workflow_state_machine.rs +20 -31
- package/sdk-core/{src → core/src/workflow}/machines/complete_workflow_state_machine.rs +3 -5
- package/sdk-core/{src → core/src/workflow}/machines/continue_as_new_workflow_state_machine.rs +18 -18
- package/sdk-core/{src → core/src/workflow}/machines/fail_workflow_state_machine.rs +5 -6
- package/sdk-core/core/src/workflow/machines/local_activity_state_machine.rs +1451 -0
- package/sdk-core/{src → core/src/workflow}/machines/mod.rs +54 -107
- package/sdk-core/{src → core/src/workflow}/machines/mutable_side_effect_state_machine.rs +0 -0
- package/sdk-core/{src → core/src/workflow}/machines/patch_state_machine.rs +29 -30
- package/sdk-core/{src → core/src/workflow}/machines/side_effect_state_machine.rs +0 -0
- package/sdk-core/{src → core/src/workflow}/machines/signal_external_state_machine.rs +17 -19
- package/sdk-core/{src → core/src/workflow}/machines/timer_state_machine.rs +20 -21
- package/sdk-core/{src → core/src/workflow}/machines/transition_coverage.rs +5 -2
- package/sdk-core/{src → core/src/workflow}/machines/upsert_search_attributes_state_machine.rs +0 -0
- package/sdk-core/core/src/workflow/machines/workflow_machines/local_acts.rs +96 -0
- package/sdk-core/{src → core/src/workflow}/machines/workflow_machines.rs +357 -171
- package/sdk-core/{src → core/src/workflow}/machines/workflow_task_state_machine.rs +1 -1
- package/sdk-core/{src → core/src}/workflow/mod.rs +200 -39
- package/sdk-core/{src → core/src}/workflow/workflow_tasks/cache_manager.rs +0 -0
- package/sdk-core/{src → core/src}/workflow/workflow_tasks/concurrency_manager.rs +38 -5
- package/sdk-core/{src → core/src}/workflow/workflow_tasks/mod.rs +317 -103
- package/sdk-core/{test_utils → core-api}/Cargo.toml +10 -7
- package/sdk-core/{src → core-api/src}/errors.rs +42 -92
- package/sdk-core/core-api/src/lib.rs +158 -0
- package/sdk-core/{src/worker/config.rs → core-api/src/worker.rs} +18 -23
- package/sdk-core/etc/deps.svg +156 -0
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +5 -5
- package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +3 -5
- package/sdk-core/fsm/rustfsm_trait/src/lib.rs +7 -1
- package/sdk-core/histories/fail_wf_task.bin +0 -0
- package/sdk-core/histories/timer_workflow_history.bin +0 -0
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +44 -13
- package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +19 -1
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +1 -1
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +9 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +1 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +13 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +14 -7
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +176 -18
- package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +11 -0
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +3 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +156 -7
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +135 -104
- package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
- package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +78 -0
- package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +205 -0
- package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +61 -0
- package/sdk-core/protos/local/{child_workflow.proto → temporal/sdk/core/child_workflow/child_workflow.proto} +1 -1
- package/sdk-core/protos/local/{common.proto → temporal/sdk/core/common/common.proto} +5 -3
- package/sdk-core/protos/local/{core_interface.proto → temporal/sdk/core/core_interface.proto} +10 -10
- package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
- package/sdk-core/protos/local/{workflow_activation.proto → temporal/sdk/core/workflow_activation/workflow_activation.proto} +35 -11
- package/sdk-core/protos/local/{workflow_commands.proto → temporal/sdk/core/workflow_commands/workflow_commands.proto} +55 -4
- package/sdk-core/protos/local/{workflow_completion.proto → temporal/sdk/core/workflow_completion/workflow_completion.proto} +3 -3
- package/sdk-core/sdk/Cargo.toml +32 -0
- package/sdk-core/{src/prototype_rust_sdk → sdk/src}/conversions.rs +0 -0
- package/sdk-core/sdk/src/lib.rs +699 -0
- package/sdk-core/sdk/src/payload_converter.rs +11 -0
- package/sdk-core/sdk/src/workflow_context/options.rs +180 -0
- package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_context.rs +201 -124
- package/sdk-core/{src/prototype_rust_sdk → sdk/src}/workflow_future.rs +63 -30
- package/sdk-core/sdk-core-protos/Cargo.toml +10 -0
- package/sdk-core/sdk-core-protos/build.rs +28 -6
- package/sdk-core/sdk-core-protos/src/constants.rs +7 -0
- package/sdk-core/{src/test_help → sdk-core-protos/src}/history_builder.rs +134 -49
- package/sdk-core/sdk-core-protos/src/history_info.rs +216 -0
- package/sdk-core/sdk-core-protos/src/lib.rs +601 -168
- package/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
- package/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
- package/sdk-core/test-utils/Cargo.toml +32 -0
- package/sdk-core/{src/test_help → test-utils/src}/canned_histories.rs +59 -78
- package/sdk-core/test-utils/src/histfetch.rs +28 -0
- package/sdk-core/{test_utils → test-utils}/src/lib.rs +131 -68
- package/sdk-core/tests/integ_tests/client_tests.rs +1 -1
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +11 -7
- package/sdk-core/tests/integ_tests/polling_tests.rs +12 -11
- package/sdk-core/tests/integ_tests/queries_tests.rs +82 -78
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +91 -71
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +3 -4
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +2 -4
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +4 -6
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +4 -6
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -4
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +496 -0
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +5 -8
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +125 -0
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +7 -13
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +33 -5
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +12 -16
- package/sdk-core/tests/integ_tests/workflow_tests.rs +85 -82
- package/sdk-core/tests/load_tests.rs +6 -6
- package/sdk-core/tests/main.rs +2 -2
- package/src/conversions.rs +24 -21
- package/src/errors.rs +8 -0
- package/src/lib.rs +323 -211
- package/sdk-core/protos/local/activity_result.proto +0 -46
- package/sdk-core/protos/local/activity_task.proto +0 -66
- package/sdk-core/src/core_tests/retry.rs +0 -147
- package/sdk-core/src/lib.rs +0 -403
- package/sdk-core/src/machines/local_activity_state_machine.rs +0 -117
- package/sdk-core/src/pending_activations.rs +0 -249
- package/sdk-core/src/protosext/mod.rs +0 -160
- package/sdk-core/src/prototype_rust_sdk.rs +0 -412
- package/sdk-core/src/task_token.rs +0 -20
- package/sdk-core/src/test_help/history_info.rs +0 -157
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
use rustfsm::{fsm, TransitionResult};
|
|
2
|
-
|
|
3
|
-
fsm! {
|
|
4
|
-
pub(super) name LocalActivityMachine;
|
|
5
|
-
command LocalActivityCommand;
|
|
6
|
-
error LocalActivityMachineError;
|
|
7
|
-
|
|
8
|
-
Created --(CheckExecutionState, on_check_execution_state) --> Replaying;
|
|
9
|
-
Created --(CheckExecutionState, on_check_execution_state) --> Executing;
|
|
10
|
-
|
|
11
|
-
Executing --(Schedule, on_schedule) --> RequestPrepared;
|
|
12
|
-
|
|
13
|
-
MarkerCommandCreated --(CommandRecordMarker, on_command_record_marker) --> ResultNotified;
|
|
14
|
-
|
|
15
|
-
Replaying --(Schedule) --> WaitingMarkerEvent;
|
|
16
|
-
|
|
17
|
-
RequestPrepared --(MarkAsSent) --> RequestSent;
|
|
18
|
-
|
|
19
|
-
RequestSent --(NonReplayWorkflowTaskStarted) --> RequestSent;
|
|
20
|
-
RequestSent --(HandleResult, on_handle_result) --> MarkerCommandCreated;
|
|
21
|
-
|
|
22
|
-
ResultNotified --(MarkerRecorded, on_marker_recorded) --> MarkerCommandRecorded;
|
|
23
|
-
|
|
24
|
-
WaitingMarkerEvent --(MarkerRecorded, on_marker_recorded) --> MarkerCommandRecorded;
|
|
25
|
-
WaitingMarkerEvent --(NonReplayWorkflowTaskStarted, on_non_replay_workflow_task_started) --> RequestPrepared;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
#[derive(thiserror::Error, Debug)]
|
|
29
|
-
pub(super) enum LocalActivityMachineError {}
|
|
30
|
-
|
|
31
|
-
pub(super) enum LocalActivityCommand {}
|
|
32
|
-
|
|
33
|
-
#[derive(Default, Clone)]
|
|
34
|
-
pub(super) struct Created {}
|
|
35
|
-
|
|
36
|
-
impl Created {
|
|
37
|
-
pub(super) fn on_check_execution_state(
|
|
38
|
-
self,
|
|
39
|
-
) -> LocalActivityMachineTransition<ReplayingOrExecuting> {
|
|
40
|
-
unimplemented!()
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
#[derive(Default, Clone)]
|
|
45
|
-
pub(super) struct Executing {}
|
|
46
|
-
|
|
47
|
-
impl Executing {
|
|
48
|
-
pub(super) fn on_schedule(self) -> LocalActivityMachineTransition<RequestPrepared> {
|
|
49
|
-
unimplemented!()
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
#[derive(Default, Clone)]
|
|
54
|
-
pub(super) struct MarkerCommandCreated {}
|
|
55
|
-
|
|
56
|
-
impl MarkerCommandCreated {
|
|
57
|
-
pub(super) fn on_command_record_marker(self) -> LocalActivityMachineTransition<ResultNotified> {
|
|
58
|
-
unimplemented!()
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
#[derive(Default, Clone)]
|
|
63
|
-
pub(super) struct MarkerCommandRecorded {}
|
|
64
|
-
|
|
65
|
-
#[derive(Default, Clone)]
|
|
66
|
-
pub(super) struct Replaying {}
|
|
67
|
-
|
|
68
|
-
#[derive(Default, Clone)]
|
|
69
|
-
pub(super) struct RequestPrepared {}
|
|
70
|
-
|
|
71
|
-
#[derive(Default, Clone)]
|
|
72
|
-
pub(super) struct RequestSent {}
|
|
73
|
-
|
|
74
|
-
impl RequestSent {
|
|
75
|
-
pub(super) fn on_handle_result(self) -> LocalActivityMachineTransition<MarkerCommandCreated> {
|
|
76
|
-
unimplemented!()
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
impl From<RequestPrepared> for RequestSent {
|
|
81
|
-
fn from(_: RequestPrepared) -> Self {
|
|
82
|
-
Self::default()
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
#[derive(Default, Clone)]
|
|
87
|
-
pub(super) struct ResultNotified {}
|
|
88
|
-
|
|
89
|
-
impl ResultNotified {
|
|
90
|
-
pub(super) fn on_marker_recorded(
|
|
91
|
-
self,
|
|
92
|
-
) -> LocalActivityMachineTransition<MarkerCommandRecorded> {
|
|
93
|
-
unimplemented!()
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
#[derive(Default, Clone)]
|
|
98
|
-
pub(super) struct WaitingMarkerEvent {}
|
|
99
|
-
|
|
100
|
-
impl WaitingMarkerEvent {
|
|
101
|
-
pub(super) fn on_marker_recorded(
|
|
102
|
-
self,
|
|
103
|
-
) -> LocalActivityMachineTransition<MarkerCommandRecorded> {
|
|
104
|
-
unimplemented!()
|
|
105
|
-
}
|
|
106
|
-
pub(super) fn on_non_replay_workflow_task_started(
|
|
107
|
-
self,
|
|
108
|
-
) -> LocalActivityMachineTransition<RequestPrepared> {
|
|
109
|
-
unimplemented!()
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
impl From<Replaying> for WaitingMarkerEvent {
|
|
114
|
-
fn from(_: Replaying) -> Self {
|
|
115
|
-
Self::default()
|
|
116
|
-
}
|
|
117
|
-
}
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
use parking_lot::RwLock;
|
|
2
|
-
use slotmap::SlotMap;
|
|
3
|
-
use std::{
|
|
4
|
-
cmp::Ordering,
|
|
5
|
-
collections::{HashMap, VecDeque},
|
|
6
|
-
};
|
|
7
|
-
use temporal_sdk_core_protos::coresdk::workflow_activation::{
|
|
8
|
-
wf_activation_job, WfActivation, WfActivationJob,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
/// Tracks pending activations using an internal queue, while also allowing lookup and removal of
|
|
12
|
-
/// any pending activations by run ID.
|
|
13
|
-
#[derive(Default)]
|
|
14
|
-
pub struct PendingActivations {
|
|
15
|
-
inner: RwLock<PaInner>,
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
slotmap::new_key_type! { struct ActivationKey; }
|
|
19
|
-
|
|
20
|
-
#[derive(Default)]
|
|
21
|
-
struct PaInner {
|
|
22
|
-
activations: SlotMap<ActivationKey, WfActivation>,
|
|
23
|
-
by_run_id: HashMap<String, ActivationKey>,
|
|
24
|
-
// Holds the actual queue of activations
|
|
25
|
-
queue: VecDeque<ActivationKey>,
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
impl PendingActivations {
|
|
29
|
-
/// Push a pending activation
|
|
30
|
-
///
|
|
31
|
-
/// Importantly, if there already exist activations for same workflow run in the queue, and the
|
|
32
|
-
/// new activation (or pending one) is just an eviction job, it can be merged into the existing
|
|
33
|
-
/// activation.
|
|
34
|
-
///
|
|
35
|
-
/// Any other attempt to enqueue a pending activation while there is already one for a given
|
|
36
|
-
/// run is a violation of our logic and will cause a panic. This is because there should never
|
|
37
|
-
/// be new activations with real work in them queued up when one is already queued, because they
|
|
38
|
-
/// should not be produced until the last one is completed (only one outstanding activation at
|
|
39
|
-
/// a time rule). New work from the server similarily should not be pushed here, as it is
|
|
40
|
-
/// buffered until any oustanding workflow task is completed.
|
|
41
|
-
pub fn push(&self, v: WfActivation) {
|
|
42
|
-
let mut inner = self.inner.write();
|
|
43
|
-
|
|
44
|
-
// Check if an activation with the same ID already exists, and merge joblist if so
|
|
45
|
-
if let Some(key) = inner.by_run_id.get(&v.run_id).copied() {
|
|
46
|
-
let act = inner
|
|
47
|
-
.activations
|
|
48
|
-
.get_mut(key)
|
|
49
|
-
.expect("PA run id mapping is always in sync with slot map");
|
|
50
|
-
if v.is_only_eviction() || act.is_only_eviction() {
|
|
51
|
-
merge_joblists(&mut act.jobs, v.jobs.into_iter());
|
|
52
|
-
} else {
|
|
53
|
-
panic!(
|
|
54
|
-
"Cannot enqueue non-eviction pending activation for run with an \
|
|
55
|
-
existing non-eviction PA: {:?}",
|
|
56
|
-
v
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
} else {
|
|
60
|
-
let run_id = v.run_id.clone();
|
|
61
|
-
let key = inner.activations.insert(v);
|
|
62
|
-
inner.by_run_id.insert(run_id, key);
|
|
63
|
-
inner.queue.push_back(key);
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
pub fn pop_first_matching(&self, predicate: impl Fn(&str) -> bool) -> Option<WfActivation> {
|
|
68
|
-
let mut inner = self.inner.write();
|
|
69
|
-
let mut key_queue = inner.queue.iter().copied();
|
|
70
|
-
let maybe_key = key_queue.position(|k| {
|
|
71
|
-
inner
|
|
72
|
-
.activations
|
|
73
|
-
.get(k)
|
|
74
|
-
.map_or(false, |activation| predicate(&activation.run_id))
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
let maybe_key = maybe_key.map(|pos| inner.queue.remove(pos).unwrap());
|
|
78
|
-
maybe_key.and_then(|key| {
|
|
79
|
-
if let Some(pa) = inner.activations.remove(key) {
|
|
80
|
-
inner.by_run_id.remove(&pa.run_id);
|
|
81
|
-
Some(pa)
|
|
82
|
-
} else {
|
|
83
|
-
// Keys no longer in the slot map are ignored, since they may have been removed
|
|
84
|
-
// by run id or anything else. Try to pop the next thing from the queue. Recurse
|
|
85
|
-
// to avoid double mutable borrow.
|
|
86
|
-
drop(inner); // Will deadlock when we recurse w/o this
|
|
87
|
-
self.pop()
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
pub fn pop(&self) -> Option<WfActivation> {
|
|
93
|
-
self.pop_first_matching(|_| true)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
pub fn has_pending(&self, run_id: &str) -> bool {
|
|
97
|
-
self.inner.read().by_run_id.contains_key(run_id)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
pub fn remove_all_with_run_id(&self, run_id: &str) {
|
|
101
|
-
let mut inner = self.inner.write();
|
|
102
|
-
|
|
103
|
-
if let Some(k) = inner.by_run_id.remove(run_id) {
|
|
104
|
-
inner.activations.remove(k);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
fn merge_joblists(
|
|
110
|
-
existing_list: &mut Vec<WfActivationJob>,
|
|
111
|
-
other_jobs: impl Iterator<Item = WfActivationJob>,
|
|
112
|
-
) {
|
|
113
|
-
existing_list.extend(other_jobs);
|
|
114
|
-
// Move any evictions to the end of the list
|
|
115
|
-
existing_list
|
|
116
|
-
.as_mut_slice()
|
|
117
|
-
.sort_by(evictions_always_last_compare);
|
|
118
|
-
// Drop any duplicate evictions
|
|
119
|
-
let truncate_len = existing_list
|
|
120
|
-
.iter()
|
|
121
|
-
.rev()
|
|
122
|
-
.position(|j| {
|
|
123
|
-
!matches!(
|
|
124
|
-
j.variant,
|
|
125
|
-
Some(wf_activation_job::Variant::RemoveFromCache(_))
|
|
126
|
-
)
|
|
127
|
-
})
|
|
128
|
-
.map_or(1, |last_non_evict_job| {
|
|
129
|
-
existing_list.len() - last_non_evict_job + 1
|
|
130
|
-
});
|
|
131
|
-
existing_list.truncate(truncate_len);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
fn evictions_always_last_compare(a: &WfActivationJob, b: &WfActivationJob) -> Ordering {
|
|
135
|
-
if a == b {
|
|
136
|
-
return Ordering::Equal;
|
|
137
|
-
}
|
|
138
|
-
// Any eviction always goes last
|
|
139
|
-
if matches!(
|
|
140
|
-
a.variant,
|
|
141
|
-
Some(wf_activation_job::Variant::RemoveFromCache(_))
|
|
142
|
-
) {
|
|
143
|
-
return Ordering::Greater;
|
|
144
|
-
}
|
|
145
|
-
if matches!(
|
|
146
|
-
b.variant,
|
|
147
|
-
Some(wf_activation_job::Variant::RemoveFromCache(_))
|
|
148
|
-
) {
|
|
149
|
-
return Ordering::Less;
|
|
150
|
-
}
|
|
151
|
-
// All jobs should not change order except evictions
|
|
152
|
-
Ordering::Equal
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
#[cfg(test)]
|
|
156
|
-
mod tests {
|
|
157
|
-
use super::*;
|
|
158
|
-
use temporal_sdk_core_protos::coresdk::workflow_activation::create_evict_activation;
|
|
159
|
-
|
|
160
|
-
#[test]
|
|
161
|
-
fn merges_same_ids_with_evictions() {
|
|
162
|
-
let pas = PendingActivations::default();
|
|
163
|
-
let rid1 = "1".to_string();
|
|
164
|
-
let rid2 = "2".to_string();
|
|
165
|
-
pas.push(WfActivation {
|
|
166
|
-
run_id: rid1.clone(),
|
|
167
|
-
..Default::default()
|
|
168
|
-
});
|
|
169
|
-
pas.push(create_evict_activation(
|
|
170
|
-
rid1.clone(),
|
|
171
|
-
"whatever".to_string(),
|
|
172
|
-
));
|
|
173
|
-
pas.push(create_evict_activation(
|
|
174
|
-
rid2.clone(),
|
|
175
|
-
"whatever".to_string(),
|
|
176
|
-
));
|
|
177
|
-
pas.push(WfActivation {
|
|
178
|
-
run_id: rid2.clone(),
|
|
179
|
-
..Default::default()
|
|
180
|
-
});
|
|
181
|
-
assert!(pas.has_pending(&rid1));
|
|
182
|
-
assert!(pas.has_pending(&rid2));
|
|
183
|
-
let last = pas.pop().unwrap();
|
|
184
|
-
assert_eq!(&last.run_id, &rid1);
|
|
185
|
-
assert!(!pas.has_pending(&rid1));
|
|
186
|
-
assert!(pas.has_pending(&rid2));
|
|
187
|
-
// Should only be one id 2, they are all merged
|
|
188
|
-
let last = pas.pop().unwrap();
|
|
189
|
-
assert_eq!(&last.run_id, &rid2);
|
|
190
|
-
assert!(!pas.has_pending(&rid2));
|
|
191
|
-
assert!(pas.pop().is_none());
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
#[test]
|
|
195
|
-
#[should_panic(expected = "Cannot enqueue non-eviction")]
|
|
196
|
-
fn panics_merging_non_evict() {
|
|
197
|
-
let pas = PendingActivations::default();
|
|
198
|
-
let rid1 = "1".to_string();
|
|
199
|
-
pas.push(WfActivation {
|
|
200
|
-
run_id: rid1.clone(),
|
|
201
|
-
..Default::default()
|
|
202
|
-
});
|
|
203
|
-
pas.push(WfActivation {
|
|
204
|
-
run_id: rid1,
|
|
205
|
-
..Default::default()
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
#[test]
|
|
210
|
-
fn can_remove_all_with_id() {
|
|
211
|
-
let pas = PendingActivations::default();
|
|
212
|
-
let remove_me = "2".to_string();
|
|
213
|
-
pas.push(WfActivation {
|
|
214
|
-
run_id: "1".to_owned(),
|
|
215
|
-
..Default::default()
|
|
216
|
-
});
|
|
217
|
-
pas.push(WfActivation {
|
|
218
|
-
run_id: remove_me.clone(),
|
|
219
|
-
..Default::default()
|
|
220
|
-
});
|
|
221
|
-
pas.push(WfActivation {
|
|
222
|
-
run_id: "3".to_owned(),
|
|
223
|
-
..Default::default()
|
|
224
|
-
});
|
|
225
|
-
pas.remove_all_with_run_id(&remove_me);
|
|
226
|
-
assert!(!pas.has_pending(&remove_me));
|
|
227
|
-
assert_eq!(&pas.pop().unwrap().run_id, "1");
|
|
228
|
-
assert_eq!(&pas.pop().unwrap().run_id, "3");
|
|
229
|
-
assert!(pas.pop().is_none());
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
#[test]
|
|
233
|
-
fn can_ignore_specific_runs() {
|
|
234
|
-
let pas = PendingActivations::default();
|
|
235
|
-
pas.push(WfActivation {
|
|
236
|
-
run_id: "1_1".to_owned(),
|
|
237
|
-
..Default::default()
|
|
238
|
-
});
|
|
239
|
-
pas.push(WfActivation {
|
|
240
|
-
run_id: "1_2".to_owned(),
|
|
241
|
-
..Default::default()
|
|
242
|
-
});
|
|
243
|
-
assert_eq!(
|
|
244
|
-
&pas.pop_first_matching(|rid| rid != "1_1").unwrap().run_id,
|
|
245
|
-
"1_2"
|
|
246
|
-
);
|
|
247
|
-
assert_eq!(&pas.pop().unwrap().run_id, "1_1");
|
|
248
|
-
}
|
|
249
|
-
}
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
use crate::{
|
|
2
|
-
machines::{ProtoCommand, HAS_CHANGE_MARKER_NAME},
|
|
3
|
-
task_token::TaskToken,
|
|
4
|
-
workflow::LEGACY_QUERY_ID,
|
|
5
|
-
};
|
|
6
|
-
use std::convert::TryFrom;
|
|
7
|
-
use temporal_sdk_core_protos::{
|
|
8
|
-
coresdk::{
|
|
9
|
-
common::decode_change_marker_details,
|
|
10
|
-
workflow_activation::{wf_activation_job, QueryWorkflow, WfActivation, WfActivationJob},
|
|
11
|
-
workflow_commands::{query_result, QueryResult},
|
|
12
|
-
workflow_completion, FromPayloadsExt,
|
|
13
|
-
},
|
|
14
|
-
temporal::api::{
|
|
15
|
-
common::v1::WorkflowExecution,
|
|
16
|
-
enums::v1::EventType,
|
|
17
|
-
history::v1::{history_event, History, HistoryEvent, MarkerRecordedEventAttributes},
|
|
18
|
-
query::v1::WorkflowQuery,
|
|
19
|
-
taskqueue::v1::StickyExecutionAttributes,
|
|
20
|
-
workflowservice::v1::PollWorkflowTaskQueueResponse,
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/// A validated version of a [PollWorkflowTaskQueueResponse]
|
|
25
|
-
#[derive(Debug, Clone, PartialEq)]
|
|
26
|
-
#[allow(clippy::manual_non_exhaustive)] // Clippy doesn't understand it's only for *in* this crate
|
|
27
|
-
pub struct ValidPollWFTQResponse {
|
|
28
|
-
pub task_token: TaskToken,
|
|
29
|
-
pub task_queue: String,
|
|
30
|
-
pub workflow_execution: WorkflowExecution,
|
|
31
|
-
pub workflow_type: String,
|
|
32
|
-
pub history: History,
|
|
33
|
-
pub next_page_token: Vec<u8>,
|
|
34
|
-
pub attempt: u32,
|
|
35
|
-
pub previous_started_event_id: i64,
|
|
36
|
-
pub started_event_id: i64,
|
|
37
|
-
/// If this is present, `history` will be empty. This is not a very "tight" design, but it's
|
|
38
|
-
/// enforced at construction time. From the `query` field.
|
|
39
|
-
pub legacy_query: Option<WorkflowQuery>,
|
|
40
|
-
/// Query requests from the `queries` field
|
|
41
|
-
pub query_requests: Vec<QueryWorkflow>,
|
|
42
|
-
|
|
43
|
-
/// Zero-size field to prevent explicit construction
|
|
44
|
-
_cant_construct_me: (),
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
impl TryFrom<PollWorkflowTaskQueueResponse> for ValidPollWFTQResponse {
|
|
48
|
-
/// We return the poll response itself if it was invalid
|
|
49
|
-
type Error = PollWorkflowTaskQueueResponse;
|
|
50
|
-
|
|
51
|
-
fn try_from(value: PollWorkflowTaskQueueResponse) -> Result<Self, Self::Error> {
|
|
52
|
-
match value {
|
|
53
|
-
PollWorkflowTaskQueueResponse {
|
|
54
|
-
task_token,
|
|
55
|
-
workflow_execution_task_queue: Some(tq),
|
|
56
|
-
workflow_execution: Some(workflow_execution),
|
|
57
|
-
workflow_type: Some(workflow_type),
|
|
58
|
-
history: Some(history),
|
|
59
|
-
next_page_token,
|
|
60
|
-
attempt,
|
|
61
|
-
previous_started_event_id,
|
|
62
|
-
started_event_id,
|
|
63
|
-
query,
|
|
64
|
-
queries,
|
|
65
|
-
..
|
|
66
|
-
} => {
|
|
67
|
-
let query_requests = queries
|
|
68
|
-
.into_iter()
|
|
69
|
-
.map(|(id, q)| QueryWorkflow {
|
|
70
|
-
query_id: id,
|
|
71
|
-
query_type: q.query_type,
|
|
72
|
-
arguments: Vec::from_payloads(q.query_args),
|
|
73
|
-
})
|
|
74
|
-
.collect();
|
|
75
|
-
|
|
76
|
-
Ok(Self {
|
|
77
|
-
task_token: TaskToken(task_token),
|
|
78
|
-
task_queue: tq.name,
|
|
79
|
-
workflow_execution,
|
|
80
|
-
workflow_type: workflow_type.name,
|
|
81
|
-
history,
|
|
82
|
-
next_page_token,
|
|
83
|
-
attempt: attempt as u32,
|
|
84
|
-
previous_started_event_id,
|
|
85
|
-
started_event_id,
|
|
86
|
-
legacy_query: query,
|
|
87
|
-
query_requests,
|
|
88
|
-
_cant_construct_me: (),
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
_ => Err(value),
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/// A version of [RespondWorkflowTaskCompletedRequest] that will finish being filled out by the
|
|
97
|
-
/// server client
|
|
98
|
-
#[derive(Debug, Clone, PartialEq)]
|
|
99
|
-
pub struct WorkflowTaskCompletion {
|
|
100
|
-
/// The task token that would've been received from [crate::Core::poll_workflow_activation] API.
|
|
101
|
-
pub task_token: TaskToken,
|
|
102
|
-
/// A list of new commands to send to the server, such as starting a timer.
|
|
103
|
-
pub commands: Vec<ProtoCommand>,
|
|
104
|
-
/// If set, indicate that next task should be queued on sticky queue with given attributes.
|
|
105
|
-
pub sticky_attributes: Option<StickyExecutionAttributes>,
|
|
106
|
-
/// Responses to queries in the `queries` field of the workflow task.
|
|
107
|
-
pub query_responses: Vec<QueryResult>,
|
|
108
|
-
pub return_new_workflow_task: bool,
|
|
109
|
-
pub force_create_new_workflow_task: bool,
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
pub(crate) trait WfActivationExt {
|
|
113
|
-
/// Returns true if this activation has one and only one job to perform a legacy query
|
|
114
|
-
fn is_legacy_query(&self) -> bool;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
impl WfActivationExt for WfActivation {
|
|
118
|
-
fn is_legacy_query(&self) -> bool {
|
|
119
|
-
matches!(&self.jobs.as_slice(), &[WfActivationJob {
|
|
120
|
-
variant: Some(wf_activation_job::Variant::QueryWorkflow(qr))
|
|
121
|
-
}] if qr.query_id == LEGACY_QUERY_ID)
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/// Create a legacy query failure result
|
|
126
|
-
pub(crate) fn legacy_query_failure(fail: workflow_completion::Failure) -> QueryResult {
|
|
127
|
-
QueryResult {
|
|
128
|
-
query_id: LEGACY_QUERY_ID.to_string(),
|
|
129
|
-
variant: Some(query_result::Variant::Failed(
|
|
130
|
-
fail.failure.unwrap_or_default(),
|
|
131
|
-
)),
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
pub(crate) trait HistoryEventExt {
|
|
136
|
-
/// If this history event represents a `changed` marker, return the info about
|
|
137
|
-
/// it. Returns `None` if it is any other kind of event or marker.
|
|
138
|
-
fn get_changed_marker_details(&self) -> Option<(String, bool)>;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
impl HistoryEventExt for HistoryEvent {
|
|
142
|
-
fn get_changed_marker_details(&self) -> Option<(String, bool)> {
|
|
143
|
-
if self.event_type() == EventType::MarkerRecorded {
|
|
144
|
-
match &self.attributes {
|
|
145
|
-
Some(history_event::Attributes::MarkerRecordedEventAttributes(
|
|
146
|
-
MarkerRecordedEventAttributes {
|
|
147
|
-
marker_name,
|
|
148
|
-
details,
|
|
149
|
-
..
|
|
150
|
-
},
|
|
151
|
-
)) if marker_name == HAS_CHANGE_MARKER_NAME => {
|
|
152
|
-
decode_change_marker_details(details)
|
|
153
|
-
}
|
|
154
|
-
_ => None,
|
|
155
|
-
}
|
|
156
|
-
} else {
|
|
157
|
-
None
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|