@temporalio/core-bridge 1.5.2 → 1.7.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 +304 -112
- package/lib/index.d.ts +8 -6
- package/lib/index.js.map +1 -1
- package/package.json +9 -4
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.buildkite/docker/Dockerfile +2 -2
- package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
- package/sdk-core/.buildkite/pipeline.yml +2 -4
- package/sdk-core/.cargo/config.toml +5 -2
- package/sdk-core/.github/workflows/heavy.yml +29 -0
- package/sdk-core/Cargo.toml +1 -1
- package/sdk-core/README.md +20 -10
- package/sdk-core/client/src/lib.rs +215 -39
- package/sdk-core/client/src/metrics.rs +17 -8
- package/sdk-core/client/src/raw.rs +4 -4
- package/sdk-core/client/src/retry.rs +32 -20
- package/sdk-core/core/Cargo.toml +25 -12
- package/sdk-core/core/src/abstractions/take_cell.rs +28 -0
- package/sdk-core/core/src/abstractions.rs +204 -14
- package/sdk-core/core/src/core_tests/activity_tasks.rs +143 -50
- package/sdk-core/core/src/core_tests/child_workflows.rs +6 -5
- package/sdk-core/core/src/core_tests/determinism.rs +165 -2
- package/sdk-core/core/src/core_tests/local_activities.rs +431 -43
- package/sdk-core/core/src/core_tests/queries.rs +34 -16
- package/sdk-core/core/src/core_tests/workers.rs +8 -5
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +588 -55
- package/sdk-core/core/src/ephemeral_server/mod.rs +113 -12
- package/sdk-core/core/src/internal_flags.rs +155 -0
- package/sdk-core/core/src/lib.rs +16 -9
- package/sdk-core/core/src/protosext/mod.rs +1 -1
- package/sdk-core/core/src/replay/mod.rs +16 -27
- package/sdk-core/core/src/telemetry/log_export.rs +1 -1
- package/sdk-core/core/src/telemetry/metrics.rs +69 -35
- package/sdk-core/core/src/telemetry/mod.rs +60 -21
- package/sdk-core/core/src/telemetry/prometheus_server.rs +19 -13
- package/sdk-core/core/src/test_help/mod.rs +73 -14
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +119 -160
- package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
- package/sdk-core/core/src/worker/activities/local_activities.rs +379 -129
- package/sdk-core/core/src/worker/activities.rs +350 -175
- package/sdk-core/core/src/worker/client/mocks.rs +22 -2
- package/sdk-core/core/src/worker/client.rs +18 -2
- package/sdk-core/core/src/worker/mod.rs +183 -64
- package/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
- package/sdk-core/core/src/worker/workflow/history_update.rs +916 -277
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +216 -183
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +9 -12
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +7 -9
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +160 -87
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +13 -14
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -9
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +14 -17
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +242 -110
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +27 -19
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +9 -11
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +321 -206
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +13 -18
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +20 -29
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +257 -51
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +310 -150
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +17 -20
- package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +31 -15
- package/sdk-core/core/src/worker/workflow/managed_run.rs +1052 -380
- package/sdk-core/core/src/worker/workflow/mod.rs +598 -390
- package/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
- package/sdk-core/core/src/worker/workflow/wft_extraction.rs +137 -0
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
- package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
- package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +469 -718
- package/sdk-core/core-api/Cargo.toml +2 -1
- package/sdk-core/core-api/src/errors.rs +1 -34
- package/sdk-core/core-api/src/lib.rs +19 -9
- package/sdk-core/core-api/src/telemetry.rs +4 -6
- package/sdk-core/core-api/src/worker.rs +19 -1
- package/sdk-core/etc/deps.svg +115 -140
- package/sdk-core/etc/regen-depgraph.sh +5 -0
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +86 -61
- package/sdk-core/fsm/rustfsm_trait/src/lib.rs +29 -71
- package/sdk-core/histories/ends_empty_wft_complete.bin +0 -0
- package/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
- package/sdk-core/histories/old_change_marker_format.bin +0 -0
- package/sdk-core/protos/api_upstream/.github/CODEOWNERS +2 -1
- package/sdk-core/protos/api_upstream/Makefile +6 -6
- package/sdk-core/protos/api_upstream/build/go.mod +7 -0
- package/sdk-core/protos/api_upstream/build/go.sum +5 -0
- package/sdk-core/protos/api_upstream/build/tools.go +29 -0
- package/sdk-core/protos/api_upstream/go.mod +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +9 -2
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +7 -26
- package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +3 -7
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +8 -8
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +25 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +49 -26
- package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +5 -2
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
- package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
- package/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -28
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -4
- package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +7 -8
- package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +10 -7
- package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +19 -30
- package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
- package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
- package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +8 -0
- package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +67 -60
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +85 -84
- package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +9 -3
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
- package/sdk-core/sdk/Cargo.toml +5 -4
- package/sdk-core/sdk/src/lib.rs +108 -26
- package/sdk-core/sdk/src/workflow_context/options.rs +7 -1
- package/sdk-core/sdk/src/workflow_context.rs +24 -17
- package/sdk-core/sdk/src/workflow_future.rs +16 -15
- package/sdk-core/sdk-core-protos/Cargo.toml +5 -2
- package/sdk-core/sdk-core-protos/build.rs +36 -2
- package/sdk-core/sdk-core-protos/src/history_builder.rs +138 -106
- package/sdk-core/sdk-core-protos/src/history_info.rs +10 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +272 -87
- package/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
- package/sdk-core/test-utils/Cargo.toml +3 -1
- package/sdk-core/test-utils/src/canned_histories.rs +106 -296
- package/sdk-core/test-utils/src/histfetch.rs +1 -1
- package/sdk-core/test-utils/src/lib.rs +82 -23
- package/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
- package/sdk-core/test-utils/src/workflows.rs +29 -0
- package/sdk-core/tests/fuzzy_workflow.rs +130 -0
- package/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
- package/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
- package/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
- package/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
- package/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +161 -72
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +80 -3
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +94 -200
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +2 -4
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +34 -28
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +76 -7
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +7 -8
- package/sdk-core/tests/integ_tests/workflow_tests.rs +13 -14
- package/sdk-core/tests/main.rs +3 -13
- package/sdk-core/tests/runner.rs +75 -36
- package/sdk-core/tests/wf_input_replay.rs +32 -0
- package/src/conversions.rs +14 -8
- package/src/runtime.rs +9 -8
- package/ts/index.ts +8 -6
- package/sdk-core/bridge-ffi/Cargo.toml +0 -24
- package/sdk-core/bridge-ffi/LICENSE.txt +0 -23
- package/sdk-core/bridge-ffi/build.rs +0 -25
- package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -224
- package/sdk-core/bridge-ffi/src/lib.rs +0 -746
- package/sdk-core/bridge-ffi/src/wrappers.rs +0 -221
- package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
- package/sdk-core/sdk/src/conversions.rs +0 -8
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
use crate::{
|
|
2
2
|
telemetry::metrics::workflow_type,
|
|
3
3
|
worker::workflow::{
|
|
4
|
-
managed_run::
|
|
5
|
-
|
|
4
|
+
managed_run::{ManagedRun, RunUpdateAct},
|
|
5
|
+
HistoryUpdate, LocalActivityRequestSink, PermittedWFT, RunBasics,
|
|
6
6
|
},
|
|
7
7
|
MetricsContext,
|
|
8
8
|
};
|
|
9
9
|
use lru::LruCache;
|
|
10
|
-
use std::{num::NonZeroUsize,
|
|
11
|
-
use
|
|
10
|
+
use std::{mem, num::NonZeroUsize, rc::Rc};
|
|
11
|
+
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::get_system_info_response;
|
|
12
12
|
|
|
13
13
|
pub(super) struct RunCache {
|
|
14
14
|
max: usize,
|
|
15
15
|
namespace: String,
|
|
16
|
-
|
|
16
|
+
server_capabilities: get_system_info_response::Capabilities,
|
|
17
17
|
/// Run id -> Data
|
|
18
|
-
runs: LruCache<String,
|
|
19
|
-
local_activity_request_sink: LocalActivityRequestSink
|
|
18
|
+
runs: LruCache<String, ManagedRun>,
|
|
19
|
+
local_activity_request_sink: Rc<dyn LocalActivityRequestSink>,
|
|
20
20
|
|
|
21
21
|
metrics: MetricsContext,
|
|
22
22
|
}
|
|
@@ -25,8 +25,8 @@ impl RunCache {
|
|
|
25
25
|
pub fn new(
|
|
26
26
|
max_cache_size: usize,
|
|
27
27
|
namespace: String,
|
|
28
|
-
|
|
29
|
-
local_activity_request_sink: LocalActivityRequestSink,
|
|
28
|
+
server_capabilities: get_system_info_response::Capabilities,
|
|
29
|
+
local_activity_request_sink: impl LocalActivityRequestSink,
|
|
30
30
|
metrics: MetricsContext,
|
|
31
31
|
) -> Self {
|
|
32
32
|
// The cache needs room for at least one run, otherwise we couldn't do anything. In
|
|
@@ -39,80 +39,63 @@ impl RunCache {
|
|
|
39
39
|
Self {
|
|
40
40
|
max: max_cache_size,
|
|
41
41
|
namespace,
|
|
42
|
-
|
|
42
|
+
server_capabilities,
|
|
43
43
|
runs: LruCache::new(
|
|
44
44
|
NonZeroUsize::new(lru_size).expect("LRU size is guaranteed positive"),
|
|
45
45
|
),
|
|
46
|
-
local_activity_request_sink,
|
|
46
|
+
local_activity_request_sink: Rc::new(local_activity_request_sink),
|
|
47
47
|
metrics,
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
pub fn instantiate_or_update(
|
|
52
|
-
&mut self,
|
|
53
|
-
run_id: &str,
|
|
54
|
-
workflow_id: &str,
|
|
55
|
-
wf_type: &str,
|
|
56
|
-
history_update: HistoryUpdate,
|
|
57
|
-
start_time: Instant,
|
|
58
|
-
) -> &mut ManagedRunHandle {
|
|
51
|
+
pub fn instantiate_or_update(&mut self, mut pwft: PermittedWFT) -> RunUpdateAct {
|
|
59
52
|
let cur_num_cached_runs = self.runs.len();
|
|
53
|
+
let run_id = &pwft.work.execution.run_id;
|
|
60
54
|
|
|
61
|
-
if self.runs.
|
|
62
|
-
|
|
63
|
-
// use get_mut above instead of in here (even though we always return from this branch).
|
|
64
|
-
// So, forced to do this.
|
|
65
|
-
let run_handle = self.runs.get_mut(run_id).unwrap();
|
|
66
|
-
|
|
67
|
-
run_handle.metrics.sticky_cache_hit();
|
|
68
|
-
run_handle.incoming_wft(NewIncomingWFT {
|
|
69
|
-
history_update: Some(history_update),
|
|
70
|
-
start_time,
|
|
71
|
-
});
|
|
55
|
+
if let Some(run_handle) = self.runs.get_mut(run_id) {
|
|
56
|
+
let rur = run_handle.incoming_wft(pwft);
|
|
72
57
|
self.metrics.cache_size(cur_num_cached_runs as u64);
|
|
73
|
-
return
|
|
58
|
+
return rur;
|
|
74
59
|
}
|
|
75
60
|
|
|
76
61
|
// Create a new workflow machines instance for this workflow, initialize it, and
|
|
77
62
|
// track it.
|
|
78
63
|
let metrics = self
|
|
79
64
|
.metrics
|
|
80
|
-
.with_new_attrs([workflow_type(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
65
|
+
.with_new_attrs([workflow_type(pwft.work.workflow_type.clone())]);
|
|
66
|
+
// Replace the update in the wft with a dummy one, since we must instantiate the machines
|
|
67
|
+
// with the update.
|
|
68
|
+
let history_update = mem::replace(&mut pwft.work.update, HistoryUpdate::dummy());
|
|
69
|
+
let mut mrh = ManagedRun::new(
|
|
70
|
+
RunBasics {
|
|
71
|
+
namespace: self.namespace.clone(),
|
|
72
|
+
workflow_id: pwft.work.execution.workflow_id.clone(),
|
|
73
|
+
workflow_type: pwft.work.workflow_type.clone(),
|
|
74
|
+
run_id: pwft.work.execution.run_id.clone(),
|
|
75
|
+
history: history_update,
|
|
76
|
+
metrics,
|
|
77
|
+
capabilities: &self.server_capabilities,
|
|
78
|
+
},
|
|
92
79
|
self.local_activity_request_sink.clone(),
|
|
93
|
-
metrics,
|
|
94
80
|
);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
});
|
|
99
|
-
if self.runs.push(run_id.to_string(), mrh).is_some() {
|
|
81
|
+
let run_id = run_id.to_string();
|
|
82
|
+
let rur = mrh.incoming_wft(pwft);
|
|
83
|
+
if self.runs.push(run_id, mrh).is_some() {
|
|
100
84
|
panic!("Overflowed run cache! Cache owner is expected to avoid this!");
|
|
101
85
|
}
|
|
102
86
|
self.metrics.cache_size(cur_num_cached_runs as u64 + 1);
|
|
103
|
-
|
|
104
|
-
self.runs.get_mut(run_id).unwrap()
|
|
87
|
+
rur
|
|
105
88
|
}
|
|
106
|
-
pub fn remove(&mut self, k: &str) -> Option<
|
|
89
|
+
pub fn remove(&mut self, k: &str) -> Option<ManagedRun> {
|
|
107
90
|
let r = self.runs.pop(k);
|
|
108
91
|
self.metrics.cache_size(self.len() as u64);
|
|
109
92
|
r
|
|
110
93
|
}
|
|
111
94
|
|
|
112
|
-
pub fn get_mut(&mut self, k: &str) -> Option<&mut
|
|
95
|
+
pub fn get_mut(&mut self, k: &str) -> Option<&mut ManagedRun> {
|
|
113
96
|
self.runs.get_mut(k)
|
|
114
97
|
}
|
|
115
|
-
pub fn get(&mut self, k: &str) -> Option<&
|
|
98
|
+
pub fn get(&mut self, k: &str) -> Option<&ManagedRun> {
|
|
116
99
|
self.runs.get(k)
|
|
117
100
|
}
|
|
118
101
|
|
|
@@ -121,16 +104,16 @@ impl RunCache {
|
|
|
121
104
|
self.runs.peek_lru().map(|(run_id, _)| run_id.as_str())
|
|
122
105
|
}
|
|
123
106
|
/// Returns an iterator yielding cached runs in LRU order
|
|
124
|
-
pub fn runs_lru_order(&self) -> impl Iterator<Item = (&str, &
|
|
107
|
+
pub fn runs_lru_order(&self) -> impl Iterator<Item = (&str, &ManagedRun)> {
|
|
125
108
|
self.runs.iter().rev().map(|(k, v)| (k.as_str(), v))
|
|
126
109
|
}
|
|
127
|
-
pub fn peek(&self, k: &str) -> Option<&
|
|
110
|
+
pub fn peek(&self, k: &str) -> Option<&ManagedRun> {
|
|
128
111
|
self.runs.peek(k)
|
|
129
112
|
}
|
|
130
113
|
pub fn has_run(&self, k: &str) -> bool {
|
|
131
114
|
self.runs.contains(k)
|
|
132
115
|
}
|
|
133
|
-
pub fn handles(&self) -> impl Iterator<Item = &
|
|
116
|
+
pub fn handles(&self) -> impl Iterator<Item = &ManagedRun> {
|
|
134
117
|
self.runs.iter().map(|(_, v)| v)
|
|
135
118
|
}
|
|
136
119
|
pub fn is_full(&self) -> bool {
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
use crate::{
|
|
2
|
+
abstractions::OwnedMeteredSemPermit,
|
|
3
|
+
protosext::ValidPollWFTQResponse,
|
|
4
|
+
worker::{
|
|
5
|
+
client::WorkerClient,
|
|
6
|
+
workflow::{
|
|
7
|
+
history_update::HistoryPaginator, CacheMissFetchReq, HistoryUpdate, NextPageReq,
|
|
8
|
+
PermittedWFT,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
use futures::Stream;
|
|
13
|
+
use futures_util::{stream, stream::PollNext, FutureExt, StreamExt};
|
|
14
|
+
use std::{future, sync::Arc};
|
|
15
|
+
use temporal_sdk_core_protos::TaskToken;
|
|
16
|
+
use tracing::Span;
|
|
17
|
+
|
|
18
|
+
/// Transforms incoming validated WFTs and history fetching requests into [PermittedWFT]s ready
|
|
19
|
+
/// for application to workflow state
|
|
20
|
+
pub(super) struct WFTExtractor {}
|
|
21
|
+
|
|
22
|
+
pub(super) enum WFTExtractorOutput {
|
|
23
|
+
NewWFT(PermittedWFT),
|
|
24
|
+
FetchResult(PermittedWFT, Arc<HistfetchRC>),
|
|
25
|
+
NextPage {
|
|
26
|
+
paginator: HistoryPaginator,
|
|
27
|
+
update: HistoryUpdate,
|
|
28
|
+
span: Span,
|
|
29
|
+
rc: Arc<HistfetchRC>,
|
|
30
|
+
},
|
|
31
|
+
FailedFetch {
|
|
32
|
+
run_id: String,
|
|
33
|
+
err: tonic::Status,
|
|
34
|
+
auto_reply_fail_tt: Option<TaskToken>,
|
|
35
|
+
},
|
|
36
|
+
PollerDead,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type WFTStreamIn = (
|
|
40
|
+
Result<ValidPollWFTQResponse, tonic::Status>,
|
|
41
|
+
OwnedMeteredSemPermit,
|
|
42
|
+
);
|
|
43
|
+
#[derive(derive_more::From, Debug)]
|
|
44
|
+
pub(super) enum HistoryFetchReq {
|
|
45
|
+
Full(CacheMissFetchReq, Arc<HistfetchRC>),
|
|
46
|
+
NextPage(NextPageReq, Arc<HistfetchRC>),
|
|
47
|
+
}
|
|
48
|
+
/// Used inside of `Arc`s to ensure we don't shutdown while there are outstanding fetches.
|
|
49
|
+
#[derive(Debug)]
|
|
50
|
+
pub(super) struct HistfetchRC {}
|
|
51
|
+
|
|
52
|
+
impl WFTExtractor {
|
|
53
|
+
pub(super) fn build(
|
|
54
|
+
client: Arc<dyn WorkerClient>,
|
|
55
|
+
max_fetch_concurrency: usize,
|
|
56
|
+
wft_stream: impl Stream<Item = WFTStreamIn> + Send + 'static,
|
|
57
|
+
fetch_stream: impl Stream<Item = HistoryFetchReq> + Send + 'static,
|
|
58
|
+
) -> impl Stream<Item = Result<WFTExtractorOutput, tonic::Status>> + Send + 'static {
|
|
59
|
+
let fetch_client = client.clone();
|
|
60
|
+
let wft_stream = wft_stream
|
|
61
|
+
.map(move |(wft, permit)| {
|
|
62
|
+
let client = client.clone();
|
|
63
|
+
async move {
|
|
64
|
+
match wft {
|
|
65
|
+
Ok(wft) => {
|
|
66
|
+
let run_id = wft.workflow_execution.run_id.clone();
|
|
67
|
+
let tt = wft.task_token.clone();
|
|
68
|
+
Ok(match HistoryPaginator::from_poll(wft, client).await {
|
|
69
|
+
Ok((pag, prep)) => WFTExtractorOutput::NewWFT(PermittedWFT {
|
|
70
|
+
work: prep,
|
|
71
|
+
permit: permit.into_used(),
|
|
72
|
+
paginator: pag,
|
|
73
|
+
}),
|
|
74
|
+
Err(err) => WFTExtractorOutput::FailedFetch {
|
|
75
|
+
run_id,
|
|
76
|
+
err,
|
|
77
|
+
auto_reply_fail_tt: Some(tt),
|
|
78
|
+
},
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
Err(e) => Err(e),
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// This is... unattractive, but lets us avoid boxing all the futs in the stream
|
|
85
|
+
.left_future()
|
|
86
|
+
.left_future()
|
|
87
|
+
})
|
|
88
|
+
.chain(stream::iter([future::ready(Ok(
|
|
89
|
+
WFTExtractorOutput::PollerDead,
|
|
90
|
+
))
|
|
91
|
+
.right_future()
|
|
92
|
+
.left_future()]));
|
|
93
|
+
|
|
94
|
+
stream::select_with_strategy(
|
|
95
|
+
wft_stream,
|
|
96
|
+
fetch_stream.map(move |fetchreq: HistoryFetchReq| {
|
|
97
|
+
let client = fetch_client.clone();
|
|
98
|
+
async move {
|
|
99
|
+
Ok(match fetchreq {
|
|
100
|
+
// It's OK to simply drop the refcounters in the event of fetch
|
|
101
|
+
// failure. We'll just proceed with shutdown.
|
|
102
|
+
HistoryFetchReq::Full(req, rc) => {
|
|
103
|
+
let run_id = req.original_wft.work.execution.run_id.clone();
|
|
104
|
+
match HistoryPaginator::from_fetchreq(req, client).await {
|
|
105
|
+
Ok(r) => WFTExtractorOutput::FetchResult(r, rc),
|
|
106
|
+
Err(err) => WFTExtractorOutput::FailedFetch {
|
|
107
|
+
run_id,
|
|
108
|
+
err,
|
|
109
|
+
auto_reply_fail_tt: None,
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
HistoryFetchReq::NextPage(mut req, rc) => {
|
|
114
|
+
match req.paginator.extract_next_update().await {
|
|
115
|
+
Ok(update) => WFTExtractorOutput::NextPage {
|
|
116
|
+
paginator: req.paginator,
|
|
117
|
+
update,
|
|
118
|
+
span: req.span,
|
|
119
|
+
rc,
|
|
120
|
+
},
|
|
121
|
+
Err(err) => WFTExtractorOutput::FailedFetch {
|
|
122
|
+
run_id: req.paginator.run_id,
|
|
123
|
+
err,
|
|
124
|
+
auto_reply_fail_tt: None,
|
|
125
|
+
},
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
.right_future()
|
|
131
|
+
}),
|
|
132
|
+
// Priority always goes to the fetching stream
|
|
133
|
+
|_: &mut ()| PollNext::Right,
|
|
134
|
+
)
|
|
135
|
+
.buffer_unordered(max_fetch_concurrency)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -47,10 +47,7 @@ pub(crate) fn validate_wft(
|
|
|
47
47
|
wft.try_into().map_err(|resp| {
|
|
48
48
|
tonic::Status::new(
|
|
49
49
|
tonic::Code::DataLoss,
|
|
50
|
-
format!(
|
|
51
|
-
"Server returned a poll WFT response we couldn't interpret: {:?}",
|
|
52
|
-
resp
|
|
53
|
-
),
|
|
50
|
+
format!("Server returned a poll WFT response we couldn't interpret: {resp:?}"),
|
|
54
51
|
)
|
|
55
52
|
})
|
|
56
53
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
use crate::{
|
|
2
|
+
telemetry::metrics::MetricsContext,
|
|
3
|
+
worker::{
|
|
4
|
+
client::mocks::DEFAULT_TEST_CAPABILITIES,
|
|
5
|
+
workflow::{
|
|
6
|
+
workflow_stream::{WFStream, WFStreamInput},
|
|
7
|
+
LAReqSink, LocalActivityRequestSink,
|
|
8
|
+
},
|
|
9
|
+
LocalActRequest, LocalActivityResolution,
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
use crossbeam::queue::SegQueue;
|
|
13
|
+
use futures::Stream;
|
|
14
|
+
use futures_util::StreamExt;
|
|
15
|
+
use serde::{Deserialize, Serialize};
|
|
16
|
+
use std::{future, sync::Arc};
|
|
17
|
+
use temporal_sdk_core_api::worker::WorkerConfig;
|
|
18
|
+
use tokio::sync::mpsc::UnboundedSender;
|
|
19
|
+
use tokio_util::sync::CancellationToken;
|
|
20
|
+
|
|
21
|
+
/// Replay everything that happened to internal workflow state. Useful for 100% deterministic
|
|
22
|
+
/// reproduction of bugs.
|
|
23
|
+
///
|
|
24
|
+
/// Use `CoreWfStarter::enable_wf_state_input_recording` from the integration test utilities to
|
|
25
|
+
/// activate saving the data to disk, and use the `wf_input_replay` example binary to replay.
|
|
26
|
+
pub async fn replay_wf_state_inputs(mut config: WorkerConfig, inputs: impl Stream<Item = Vec<u8>>) {
|
|
27
|
+
use crate::worker::build_wf_basics;
|
|
28
|
+
|
|
29
|
+
let la_resp_q = Arc::new(SegQueue::new());
|
|
30
|
+
let la_resp_q_clone = la_resp_q.clone();
|
|
31
|
+
let inputs = inputs
|
|
32
|
+
.map(|bytes| {
|
|
33
|
+
rmp_serde::from_slice::<StoredWFStateInputDeSer>(&bytes)
|
|
34
|
+
.expect("Can decode wf stream input")
|
|
35
|
+
})
|
|
36
|
+
.filter_map(|si| {
|
|
37
|
+
future::ready(match si {
|
|
38
|
+
StoredWFStateInputDeSer::Stream(wfsi) => Some(wfsi),
|
|
39
|
+
StoredWFStateInputDeSer::ImmediateLASinkResolutions(lares) => {
|
|
40
|
+
la_resp_q_clone.push(lares);
|
|
41
|
+
None
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
let basics = build_wf_basics(
|
|
46
|
+
&mut config,
|
|
47
|
+
MetricsContext::no_op(),
|
|
48
|
+
CancellationToken::new(),
|
|
49
|
+
DEFAULT_TEST_CAPABILITIES.clone(),
|
|
50
|
+
);
|
|
51
|
+
let sink = ReadingFromFileLaReqSink {
|
|
52
|
+
resolutions: la_resp_q,
|
|
53
|
+
};
|
|
54
|
+
info!("Beginning workflow stream internal state replay");
|
|
55
|
+
let stream = WFStream::build_internal(inputs, basics, sink);
|
|
56
|
+
stream
|
|
57
|
+
.for_each(|o| async move { trace!("Stream output: {:?}", o) })
|
|
58
|
+
.await;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
impl WFStream {
|
|
62
|
+
pub(super) fn prep_input(&mut self, action: &WFStreamInput) -> Option<PreppedInputWrite> {
|
|
63
|
+
// Remove the channel, we'll put it back, avoiding a clone
|
|
64
|
+
self.wf_state_inputs.take().map(|chan| PreppedInputWrite {
|
|
65
|
+
data: rmp_serde::to_vec(&StoredWFStateInputSer::Stream(action))
|
|
66
|
+
.expect("WF Inputs are serializable"),
|
|
67
|
+
chan,
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
pub(super) fn flush_write(&mut self, w: PreppedInputWrite) {
|
|
71
|
+
let _ = w.chan.send(w.data);
|
|
72
|
+
self.wf_state_inputs = Some(w.chan);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
pub(super) struct PreppedInputWrite {
|
|
76
|
+
data: Vec<u8>,
|
|
77
|
+
chan: UnboundedSender<Vec<u8>>,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
#[derive(Serialize)]
|
|
81
|
+
enum StoredWFStateInputSer<'a> {
|
|
82
|
+
Stream(&'a WFStreamInput),
|
|
83
|
+
ImmediateLASinkResolutions(&'a Vec<LocalActivityResolution>),
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#[derive(Deserialize)]
|
|
87
|
+
enum StoredWFStateInputDeSer {
|
|
88
|
+
Stream(WFStreamInput),
|
|
89
|
+
ImmediateLASinkResolutions(Vec<LocalActivityResolution>),
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
struct ReadingFromFileLaReqSink {
|
|
93
|
+
resolutions: Arc<SegQueue<Vec<LocalActivityResolution>>>,
|
|
94
|
+
}
|
|
95
|
+
impl LocalActivityRequestSink for ReadingFromFileLaReqSink {
|
|
96
|
+
fn sink_reqs(&self, reqs: Vec<LocalActRequest>) -> Vec<LocalActivityResolution> {
|
|
97
|
+
if !reqs.is_empty() {
|
|
98
|
+
self.resolutions
|
|
99
|
+
.pop()
|
|
100
|
+
.expect("LA sink was called, but there's no stored immediate response")
|
|
101
|
+
} else {
|
|
102
|
+
vec![]
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
impl LAReqSink {
|
|
108
|
+
pub(crate) fn write_req(&self, res: &Vec<LocalActivityResolution>) {
|
|
109
|
+
if let Some(r) = self.recorder.as_ref() {
|
|
110
|
+
r.send(
|
|
111
|
+
rmp_serde::to_vec(&StoredWFStateInputSer::ImmediateLASinkResolutions(res))
|
|
112
|
+
.expect("LA immediate resolutions are serializable"),
|
|
113
|
+
)
|
|
114
|
+
.expect("WF input serialization channel is available for immediate LA result storage");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
use tonic::{Code, Status};
|
|
2
|
+
|
|
3
|
+
#[derive(serde::Serialize, serde::Deserialize)]
|
|
4
|
+
#[serde(remote = "Status")]
|
|
5
|
+
pub(super) struct SerdeStatus {
|
|
6
|
+
#[serde(getter = "get_code")]
|
|
7
|
+
code: i32,
|
|
8
|
+
#[serde(getter = "get_owned_msg")]
|
|
9
|
+
message: String,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
fn get_owned_msg(v: &Status) -> String {
|
|
13
|
+
v.message().to_string()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
fn get_code(v: &Status) -> i32 {
|
|
17
|
+
v.code() as i32
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
impl From<SerdeStatus> for Status {
|
|
21
|
+
fn from(v: SerdeStatus) -> Self {
|
|
22
|
+
Status::new(Code::from(v.code), v.message)
|
|
23
|
+
}
|
|
24
|
+
}
|