@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
|
@@ -23,6 +23,9 @@ use std::os::unix::fs::OpenOptionsExt;
|
|
|
23
23
|
use std::process::Stdio;
|
|
24
24
|
|
|
25
25
|
/// Configuration for Temporalite.
|
|
26
|
+
/// Will be removed eventually as its successor, Temporal CLI matures.
|
|
27
|
+
/// We don't care for the duplication between this struct and [TemporalDevServerConfig] and prefer that over another
|
|
28
|
+
/// abstraction since the existence of this struct is temporary.
|
|
26
29
|
#[derive(Debug, Clone, derive_builder::Builder)]
|
|
27
30
|
pub struct TemporaliteConfig {
|
|
28
31
|
/// Required path to executable or download info.
|
|
@@ -59,7 +62,10 @@ impl TemporaliteConfig {
|
|
|
59
62
|
/// Start a Temporalite server with configurable stdout destination.
|
|
60
63
|
pub async fn start_server_with_output(&self, output: Stdio) -> anyhow::Result<EphemeralServer> {
|
|
61
64
|
// Get exe path
|
|
62
|
-
let exe_path = self
|
|
65
|
+
let exe_path = self
|
|
66
|
+
.exe
|
|
67
|
+
.get_or_download("temporalite", "temporalite", None)
|
|
68
|
+
.await?;
|
|
63
69
|
|
|
64
70
|
// Get free port if not already given
|
|
65
71
|
let port = self.port.unwrap_or_else(|| get_free_port(&self.ip));
|
|
@@ -77,6 +83,8 @@ impl TemporaliteConfig {
|
|
|
77
83
|
self.log.0.clone(),
|
|
78
84
|
"--log-level".to_owned(),
|
|
79
85
|
self.log.1.clone(),
|
|
86
|
+
"--dynamic-config-value".to_owned(),
|
|
87
|
+
"frontend.enableServerVersionCheck=false".to_owned(),
|
|
80
88
|
];
|
|
81
89
|
if let Some(db_filename) = &self.db_filename {
|
|
82
90
|
args.push("--filename".to_owned());
|
|
@@ -101,6 +109,89 @@ impl TemporaliteConfig {
|
|
|
101
109
|
}
|
|
102
110
|
}
|
|
103
111
|
|
|
112
|
+
/// Configuration for Temporal CLI dev server.
|
|
113
|
+
#[derive(Debug, Clone, derive_builder::Builder)]
|
|
114
|
+
pub struct TemporalDevServerConfig {
|
|
115
|
+
/// Required path to executable or download info.
|
|
116
|
+
pub exe: EphemeralExe,
|
|
117
|
+
/// Namespace to use.
|
|
118
|
+
#[builder(default = "\"default\".to_owned()")]
|
|
119
|
+
pub namespace: String,
|
|
120
|
+
/// IP to bind to.
|
|
121
|
+
#[builder(default = "\"127.0.0.1\".to_owned()")]
|
|
122
|
+
pub ip: String,
|
|
123
|
+
/// Port to use or obtains a free one if none given.
|
|
124
|
+
#[builder(default)]
|
|
125
|
+
pub port: Option<u16>,
|
|
126
|
+
/// Sqlite DB filename if persisting or non-persistent if none.
|
|
127
|
+
#[builder(default)]
|
|
128
|
+
pub db_filename: Option<String>,
|
|
129
|
+
/// Whether to enable the UI.
|
|
130
|
+
#[builder(default)]
|
|
131
|
+
pub ui: bool,
|
|
132
|
+
/// Log format and level
|
|
133
|
+
#[builder(default = "(\"pretty\".to_owned(), \"warn\".to_owned())")]
|
|
134
|
+
pub log: (String, String),
|
|
135
|
+
/// Additional arguments to Temporalite.
|
|
136
|
+
#[builder(default)]
|
|
137
|
+
pub extra_args: Vec<String>,
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
impl TemporalDevServerConfig {
|
|
141
|
+
/// Start a Temporal CLI dev server.
|
|
142
|
+
pub async fn start_server(&self) -> anyhow::Result<EphemeralServer> {
|
|
143
|
+
self.start_server_with_output(Stdio::inherit()).await
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/// Start a Temporal CLI dev server with configurable stdout destination.
|
|
147
|
+
pub async fn start_server_with_output(&self, output: Stdio) -> anyhow::Result<EphemeralServer> {
|
|
148
|
+
// Get exe path
|
|
149
|
+
let exe_path = self
|
|
150
|
+
.exe
|
|
151
|
+
.get_or_download("cli", "temporal", Some("tar.gz"))
|
|
152
|
+
.await?;
|
|
153
|
+
|
|
154
|
+
// Get free port if not already given
|
|
155
|
+
let port = self.port.unwrap_or_else(|| get_free_port(&self.ip));
|
|
156
|
+
|
|
157
|
+
// Build arg set
|
|
158
|
+
let mut args = vec![
|
|
159
|
+
"server".to_owned(),
|
|
160
|
+
"start-dev".to_owned(),
|
|
161
|
+
"--port".to_owned(),
|
|
162
|
+
port.to_string(),
|
|
163
|
+
"--namespace".to_owned(),
|
|
164
|
+
self.namespace.clone(),
|
|
165
|
+
"--ip".to_owned(),
|
|
166
|
+
self.ip.clone(),
|
|
167
|
+
"--log-format".to_owned(),
|
|
168
|
+
self.log.0.clone(),
|
|
169
|
+
"--log-level".to_owned(),
|
|
170
|
+
self.log.1.clone(),
|
|
171
|
+
"--dynamic-config-value".to_owned(),
|
|
172
|
+
"frontend.enableServerVersionCheck=false".to_owned(),
|
|
173
|
+
];
|
|
174
|
+
if let Some(db_filename) = &self.db_filename {
|
|
175
|
+
args.push("--filename".to_owned());
|
|
176
|
+
args.push(db_filename.clone());
|
|
177
|
+
}
|
|
178
|
+
if !self.ui {
|
|
179
|
+
args.push("--headless".to_owned());
|
|
180
|
+
}
|
|
181
|
+
args.extend(self.extra_args.clone());
|
|
182
|
+
|
|
183
|
+
// Start
|
|
184
|
+
EphemeralServer::start(EphemeralServerConfig {
|
|
185
|
+
exe_path,
|
|
186
|
+
port,
|
|
187
|
+
args,
|
|
188
|
+
has_test_service: false,
|
|
189
|
+
output,
|
|
190
|
+
})
|
|
191
|
+
.await
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
104
195
|
/// Configuration for the test server.
|
|
105
196
|
#[derive(Debug, Clone, derive_builder::Builder)]
|
|
106
197
|
pub struct TestServerConfig {
|
|
@@ -123,7 +214,10 @@ impl TestServerConfig {
|
|
|
123
214
|
/// Start a test server with configurable stdout.
|
|
124
215
|
pub async fn start_server_with_output(&self, output: Stdio) -> anyhow::Result<EphemeralServer> {
|
|
125
216
|
// Get exe path
|
|
126
|
-
let exe_path = self
|
|
217
|
+
let exe_path = self
|
|
218
|
+
.exe
|
|
219
|
+
.get_or_download("temporal-test-server", "temporal-test-server", None)
|
|
220
|
+
.await?;
|
|
127
221
|
|
|
128
222
|
// Get free port if not already given
|
|
129
223
|
let port = self.port.unwrap_or_else(|| get_free_port("0.0.0.0"));
|
|
@@ -172,7 +266,7 @@ impl EphemeralServer {
|
|
|
172
266
|
.stdout(config.output)
|
|
173
267
|
.spawn()?;
|
|
174
268
|
let target = format!("127.0.0.1:{}", config.port);
|
|
175
|
-
let target_url = format!("http://{}"
|
|
269
|
+
let target_url = format!("http://{target}");
|
|
176
270
|
let success = Ok(EphemeralServer {
|
|
177
271
|
target,
|
|
178
272
|
has_test_service: config.has_test_service,
|
|
@@ -262,7 +356,7 @@ pub enum EphemeralExe {
|
|
|
262
356
|
#[derive(Debug, Clone)]
|
|
263
357
|
pub enum EphemeralExeVersion {
|
|
264
358
|
/// Use a default version for the given SDK name and version.
|
|
265
|
-
|
|
359
|
+
SDKDefault {
|
|
266
360
|
/// Name of the SDK to get the default for.
|
|
267
361
|
sdk_name: String,
|
|
268
362
|
/// Version of the SDK to get the default for.
|
|
@@ -280,7 +374,12 @@ struct DownloadInfo {
|
|
|
280
374
|
}
|
|
281
375
|
|
|
282
376
|
impl EphemeralExe {
|
|
283
|
-
async fn get_or_download(
|
|
377
|
+
async fn get_or_download(
|
|
378
|
+
&self,
|
|
379
|
+
artifact_name: &str,
|
|
380
|
+
downloaded_name_prefix: &str,
|
|
381
|
+
preferred_format: Option<&str>,
|
|
382
|
+
) -> anyhow::Result<PathBuf> {
|
|
284
383
|
match self {
|
|
285
384
|
EphemeralExe::ExistingPath(exe_path) => {
|
|
286
385
|
let path = PathBuf::from(exe_path);
|
|
@@ -301,12 +400,12 @@ impl EphemeralExe {
|
|
|
301
400
|
};
|
|
302
401
|
// Create dest file based on SDK name/version or fixed version
|
|
303
402
|
let dest = dest_dir.join(match version {
|
|
304
|
-
EphemeralExeVersion::
|
|
403
|
+
EphemeralExeVersion::SDKDefault {
|
|
305
404
|
sdk_name,
|
|
306
405
|
sdk_version,
|
|
307
|
-
} => format!("{}-{}-{}{}"
|
|
406
|
+
} => format!("{downloaded_name_prefix}-{sdk_name}-{sdk_version}{out_ext}"),
|
|
308
407
|
EphemeralExeVersion::Fixed(version) => {
|
|
309
|
-
format!("{}-{}{}"
|
|
408
|
+
format!("{downloaded_name_prefix}-{version}{out_ext}")
|
|
310
409
|
}
|
|
311
410
|
});
|
|
312
411
|
debug!(
|
|
@@ -326,8 +425,11 @@ impl EphemeralExe {
|
|
|
326
425
|
other => return Err(anyhow!("Unsupported arch: {}", other)),
|
|
327
426
|
};
|
|
328
427
|
let mut get_info_params = vec![("arch", arch), ("platform", platform)];
|
|
428
|
+
if let Some(format) = preferred_format {
|
|
429
|
+
get_info_params.push(("format", format));
|
|
430
|
+
}
|
|
329
431
|
let version_name = match version {
|
|
330
|
-
EphemeralExeVersion::
|
|
432
|
+
EphemeralExeVersion::SDKDefault {
|
|
331
433
|
sdk_name,
|
|
332
434
|
sdk_version,
|
|
333
435
|
} => {
|
|
@@ -340,8 +442,7 @@ impl EphemeralExe {
|
|
|
340
442
|
let client = reqwest::Client::new();
|
|
341
443
|
let info: DownloadInfo = client
|
|
342
444
|
.get(format!(
|
|
343
|
-
"https://temporal.download/{}/{}"
|
|
344
|
-
artifact_name, version_name
|
|
445
|
+
"https://temporal.download/{artifact_name}/{version_name}"
|
|
345
446
|
))
|
|
346
447
|
.query(&get_info_params)
|
|
347
448
|
.send()
|
|
@@ -371,7 +472,7 @@ impl EphemeralExe {
|
|
|
371
472
|
fn get_free_port(bind_ip: &str) -> u16 {
|
|
372
473
|
// Can just ask OS to give us a port then close socket. OS's don't give that
|
|
373
474
|
// port back to anyone else anytime soon.
|
|
374
|
-
std::net::TcpListener::bind(format!("{}:0"
|
|
475
|
+
std::net::TcpListener::bind(format!("{bind_ip}:0"))
|
|
375
476
|
.unwrap()
|
|
376
477
|
.local_addr()
|
|
377
478
|
.unwrap()
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
//! Utilities for and tracking of internal versions which alter history in incompatible ways
|
|
2
|
+
//! so that we can use older code paths for workflows executed on older core versions.
|
|
3
|
+
|
|
4
|
+
use std::collections::{BTreeSet, HashSet};
|
|
5
|
+
use temporal_sdk_core_protos::temporal::api::{
|
|
6
|
+
history::v1::WorkflowTaskCompletedEventAttributes, sdk::v1::WorkflowTaskCompletedMetadata,
|
|
7
|
+
workflowservice::v1::get_system_info_response,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/// This enumeration contains internal flags that may result in incompatible history changes with
|
|
11
|
+
/// older workflows, or other breaking changes.
|
|
12
|
+
///
|
|
13
|
+
/// When a flag has existed long enough the version it was introduced in is no longer supported, it
|
|
14
|
+
/// may be removed from the enum. *Importantly*, all variants must be given explicit values, such
|
|
15
|
+
/// that removing older variants does not create any change in existing values. Removed flag
|
|
16
|
+
/// variants must be reserved forever (a-la protobuf), and should be called out in a comment.
|
|
17
|
+
#[repr(u32)]
|
|
18
|
+
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone, Debug)]
|
|
19
|
+
pub(crate) enum CoreInternalFlags {
|
|
20
|
+
/// In this flag additional checks were added to a number of state machines to ensure that
|
|
21
|
+
/// the ID and type of activities, local activities, and child workflows match during replay.
|
|
22
|
+
IdAndTypeDeterminismChecks = 1,
|
|
23
|
+
/// Introduced automatically upserting search attributes for each patched call, and
|
|
24
|
+
/// nondeterminism checks for upserts.
|
|
25
|
+
UpsertSearchAttributeOnPatch = 2,
|
|
26
|
+
/// We received a value higher than this code can understand.
|
|
27
|
+
TooHigh = u32::MAX,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
31
|
+
pub(crate) struct InternalFlags {
|
|
32
|
+
enabled: bool,
|
|
33
|
+
core: BTreeSet<CoreInternalFlags>,
|
|
34
|
+
lang: BTreeSet<u32>,
|
|
35
|
+
core_since_last_complete: HashSet<CoreInternalFlags>,
|
|
36
|
+
lang_since_last_complete: HashSet<u32>,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
impl InternalFlags {
|
|
40
|
+
pub fn new(server_capabilities: &get_system_info_response::Capabilities) -> Self {
|
|
41
|
+
Self {
|
|
42
|
+
enabled: server_capabilities.sdk_metadata,
|
|
43
|
+
core: Default::default(),
|
|
44
|
+
lang: Default::default(),
|
|
45
|
+
core_since_last_complete: Default::default(),
|
|
46
|
+
lang_since_last_complete: Default::default(),
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#[cfg(test)]
|
|
51
|
+
pub fn all_core_enabled() -> Self {
|
|
52
|
+
Self {
|
|
53
|
+
enabled: true,
|
|
54
|
+
core: BTreeSet::from([
|
|
55
|
+
CoreInternalFlags::IdAndTypeDeterminismChecks,
|
|
56
|
+
CoreInternalFlags::UpsertSearchAttributeOnPatch,
|
|
57
|
+
]),
|
|
58
|
+
lang: Default::default(),
|
|
59
|
+
core_since_last_complete: Default::default(),
|
|
60
|
+
lang_since_last_complete: Default::default(),
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
pub fn add_from_complete(&mut self, e: &WorkflowTaskCompletedEventAttributes) {
|
|
65
|
+
if !self.enabled {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if let Some(metadata) = e.sdk_metadata.as_ref() {
|
|
70
|
+
self.core.extend(
|
|
71
|
+
metadata
|
|
72
|
+
.core_used_flags
|
|
73
|
+
.iter()
|
|
74
|
+
.map(|u| CoreInternalFlags::from_u32(*u)),
|
|
75
|
+
);
|
|
76
|
+
self.lang.extend(metadata.lang_used_flags.iter());
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
pub fn add_lang_used(&mut self, flags: impl IntoIterator<Item = u32>) {
|
|
81
|
+
if !self.enabled {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
self.lang_since_last_complete.extend(flags.into_iter());
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// Returns true if this flag may currently be used. If `should_record` is true, always returns
|
|
89
|
+
/// true and records the flag as being used, for taking later via
|
|
90
|
+
/// [Self::gather_for_wft_complete].
|
|
91
|
+
pub fn try_use(&mut self, core_patch: CoreInternalFlags, should_record: bool) -> bool {
|
|
92
|
+
if !self.enabled {
|
|
93
|
+
// If the server does not support the metadata field, we must assume we can never use
|
|
94
|
+
// any internal flags since they can't be recorded for future use
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if should_record {
|
|
99
|
+
self.core_since_last_complete.insert(core_patch);
|
|
100
|
+
true
|
|
101
|
+
} else {
|
|
102
|
+
self.core.contains(&core_patch)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// Wipes the recorded flags used during the current WFT and returns a partially filled
|
|
107
|
+
/// sdk metadata message that can be combined with any existing data before sending the WFT
|
|
108
|
+
/// complete
|
|
109
|
+
pub fn gather_for_wft_complete(&mut self) -> WorkflowTaskCompletedMetadata {
|
|
110
|
+
WorkflowTaskCompletedMetadata {
|
|
111
|
+
core_used_flags: self
|
|
112
|
+
.core_since_last_complete
|
|
113
|
+
.drain()
|
|
114
|
+
.map(|p| p as u32)
|
|
115
|
+
.collect(),
|
|
116
|
+
lang_used_flags: self.lang_since_last_complete.drain().collect(),
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
pub fn all_lang(&self) -> &BTreeSet<u32> {
|
|
121
|
+
&self.lang
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
impl CoreInternalFlags {
|
|
126
|
+
fn from_u32(v: u32) -> Self {
|
|
127
|
+
match v {
|
|
128
|
+
1 => Self::IdAndTypeDeterminismChecks,
|
|
129
|
+
2 => Self::UpsertSearchAttributeOnPatch,
|
|
130
|
+
_ => Self::TooHigh,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
#[cfg(test)]
|
|
136
|
+
mod tests {
|
|
137
|
+
use super::*;
|
|
138
|
+
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::get_system_info_response::Capabilities;
|
|
139
|
+
|
|
140
|
+
#[test]
|
|
141
|
+
fn disabled_in_capabilities_disables() {
|
|
142
|
+
let mut f = InternalFlags::new(&Capabilities::default());
|
|
143
|
+
f.add_lang_used([1]);
|
|
144
|
+
f.add_from_complete(&WorkflowTaskCompletedEventAttributes {
|
|
145
|
+
sdk_metadata: Some(WorkflowTaskCompletedMetadata {
|
|
146
|
+
core_used_flags: vec![1],
|
|
147
|
+
lang_used_flags: vec![],
|
|
148
|
+
}),
|
|
149
|
+
..Default::default()
|
|
150
|
+
});
|
|
151
|
+
let gathered = f.gather_for_wft_complete();
|
|
152
|
+
assert_matches!(gathered.core_used_flags.as_slice(), &[]);
|
|
153
|
+
assert_matches!(gathered.lang_used_flags.as_slice(), &[]);
|
|
154
|
+
}
|
|
155
|
+
}
|
package/sdk-core/core/src/lib.rs
CHANGED
|
@@ -13,6 +13,7 @@ extern crate core;
|
|
|
13
13
|
|
|
14
14
|
mod abstractions;
|
|
15
15
|
pub mod ephemeral_server;
|
|
16
|
+
mod internal_flags;
|
|
16
17
|
mod pollers;
|
|
17
18
|
mod protosext;
|
|
18
19
|
pub mod replay;
|
|
@@ -36,13 +37,16 @@ pub use temporal_sdk_core_api as api;
|
|
|
36
37
|
pub use temporal_sdk_core_protos as protos;
|
|
37
38
|
pub use temporal_sdk_core_protos::TaskToken;
|
|
38
39
|
pub use url::Url;
|
|
40
|
+
#[cfg(feature = "save_wf_inputs")]
|
|
41
|
+
pub use worker::replay_wf_state_inputs;
|
|
39
42
|
pub use worker::{Worker, WorkerConfig, WorkerConfigBuilder};
|
|
40
43
|
|
|
41
44
|
use crate::{
|
|
42
45
|
replay::{mock_client_from_histories, Historator, HistoryForReplay},
|
|
43
46
|
telemetry::{
|
|
44
|
-
metrics::MetricsContext,
|
|
45
|
-
|
|
47
|
+
metrics::{MetricsContext, TemporalMeter},
|
|
48
|
+
remove_trace_subscriber_for_current_thread, set_trace_subscriber_for_current_thread,
|
|
49
|
+
telemetry_init, TelemetryInstance,
|
|
46
50
|
},
|
|
47
51
|
worker::client::WorkerClientBag,
|
|
48
52
|
};
|
|
@@ -51,7 +55,7 @@ use std::sync::Arc;
|
|
|
51
55
|
use temporal_client::{ConfiguredClient, TemporalServiceClientWithMetrics};
|
|
52
56
|
use temporal_sdk_core_api::{
|
|
53
57
|
errors::{CompleteActivityError, PollActivityError, PollWfError},
|
|
54
|
-
telemetry::
|
|
58
|
+
telemetry::TelemetryOptions,
|
|
55
59
|
Worker as WorkerTrait,
|
|
56
60
|
};
|
|
57
61
|
use temporal_sdk_core_protos::coresdk::ActivityHeartbeat;
|
|
@@ -62,7 +66,7 @@ use temporal_sdk_core_protos::coresdk::ActivityHeartbeat;
|
|
|
62
66
|
/// After the worker is initialized, you should use [CoreRuntime::tokio_handle] to run the worker's
|
|
63
67
|
/// async functions.
|
|
64
68
|
///
|
|
65
|
-
/// Lang implementations may pass in a [
|
|
69
|
+
/// Lang implementations may pass in a [ConfiguredClient] directly (or a
|
|
66
70
|
/// [RetryClient] wrapping one, or a handful of other variants of the same idea). When they do so,
|
|
67
71
|
/// this function will always overwrite the client retry configuration, force the client to use the
|
|
68
72
|
/// namespace defined in the worker config, and set the client identity appropriately. IE: Use
|
|
@@ -97,9 +101,12 @@ where
|
|
|
97
101
|
worker_config.use_worker_versioning,
|
|
98
102
|
));
|
|
99
103
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
Ok(Worker::new(
|
|
105
|
+
worker_config,
|
|
106
|
+
sticky_q,
|
|
107
|
+
client_bag,
|
|
108
|
+
Some(&runtime.telemetry),
|
|
109
|
+
))
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
/// Create a worker for replaying a specific history. It will auto-shutdown as soon as the history
|
|
@@ -126,7 +133,7 @@ where
|
|
|
126
133
|
let post_activate = historator.get_post_activate_hook();
|
|
127
134
|
let shutdown_tok = historator.get_shutdown_setter();
|
|
128
135
|
let client = mock_client_from_histories(historator);
|
|
129
|
-
let mut worker = Worker::new(config, None, Arc::new(client),
|
|
136
|
+
let mut worker = Worker::new(config, None, Arc::new(client), None);
|
|
130
137
|
worker.set_post_activate_hook(post_activate);
|
|
131
138
|
shutdown_tok(worker.shutdown_token());
|
|
132
139
|
Ok(worker)
|
|
@@ -258,7 +265,7 @@ impl CoreRuntime {
|
|
|
258
265
|
}
|
|
259
266
|
|
|
260
267
|
/// Returns the metric meter used for recording metrics, if they were enabled.
|
|
261
|
-
pub fn metric_meter(&self) -> Option
|
|
268
|
+
pub fn metric_meter(&self) -> Option<TemporalMeter> {
|
|
262
269
|
self.telemetry.get_metric_meter()
|
|
263
270
|
}
|
|
264
271
|
|
|
@@ -274,7 +274,7 @@ impl TryFrom<activity_execution_result::Status> for LocalActivityExecutionResult
|
|
|
274
274
|
Status::Failed(f)
|
|
275
275
|
if f.failure
|
|
276
276
|
.as_ref()
|
|
277
|
-
.map(|fail| fail.is_timeout())
|
|
277
|
+
.map(|fail| fail.is_timeout().is_some())
|
|
278
278
|
.unwrap_or_default() =>
|
|
279
279
|
{
|
|
280
280
|
Ok(LocalActivityExecutionResult::TimedOut(f))
|
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
//! users during testing.
|
|
4
4
|
|
|
5
5
|
use crate::{
|
|
6
|
-
worker::
|
|
6
|
+
worker::{
|
|
7
|
+
client::{mocks::mock_manual_workflow_client, WorkerClient},
|
|
8
|
+
PostActivateHookData,
|
|
9
|
+
},
|
|
7
10
|
Worker,
|
|
8
11
|
};
|
|
9
12
|
use futures::{FutureExt, Stream, StreamExt};
|
|
10
13
|
use once_cell::sync::OnceCell;
|
|
11
14
|
use parking_lot::Mutex;
|
|
12
15
|
use std::{
|
|
13
|
-
collections::HashMap,
|
|
14
16
|
pin::Pin,
|
|
15
17
|
sync::Arc,
|
|
16
18
|
task::{Context, Poll},
|
|
@@ -147,25 +149,18 @@ impl Historator {
|
|
|
147
149
|
|
|
148
150
|
/// Returns a callback that can be used as the post-activation hook for a worker to indicate
|
|
149
151
|
/// we're ready to replay the next history, or whatever else.
|
|
150
|
-
pub(crate) fn get_post_activate_hook(
|
|
151
|
-
|
|
152
|
+
pub(crate) fn get_post_activate_hook(
|
|
153
|
+
&self,
|
|
154
|
+
) -> impl Fn(&Worker, PostActivateHookData) + Send + Sync {
|
|
152
155
|
let done_tx = self.replay_done_tx.clone();
|
|
153
|
-
move |worker,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if last_processed_event >= le {
|
|
162
|
-
worker.request_wf_eviction(
|
|
163
|
-
activated_run_id,
|
|
164
|
-
"Always evict workflows after replay",
|
|
165
|
-
EvictionReason::LangRequested,
|
|
166
|
-
);
|
|
167
|
-
done_tx.send(activated_run_id.to_string()).unwrap();
|
|
168
|
-
}
|
|
156
|
+
move |worker, data| {
|
|
157
|
+
if !data.replaying {
|
|
158
|
+
worker.request_wf_eviction(
|
|
159
|
+
data.run_id,
|
|
160
|
+
"Always evict workflows after replay",
|
|
161
|
+
EvictionReason::LangRequested,
|
|
162
|
+
);
|
|
163
|
+
done_tx.send(data.run_id.to_string()).unwrap();
|
|
169
164
|
}
|
|
170
165
|
}
|
|
171
166
|
}
|
|
@@ -184,7 +179,7 @@ impl Stream for Historator {
|
|
|
184
179
|
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
|
185
180
|
match self.iter.poll_next_unpin(cx) {
|
|
186
181
|
Poll::Ready(Some(history)) => {
|
|
187
|
-
|
|
182
|
+
history
|
|
188
183
|
.hist
|
|
189
184
|
.extract_run_id_from_start()
|
|
190
185
|
.expect(
|
|
@@ -192,11 +187,6 @@ impl Stream for Historator {
|
|
|
192
187
|
execution started events",
|
|
193
188
|
)
|
|
194
189
|
.to_string();
|
|
195
|
-
let last_event = history.hist.last_event_id();
|
|
196
|
-
self.dat
|
|
197
|
-
.lock()
|
|
198
|
-
.run_id_to_last_event_num
|
|
199
|
-
.insert(run_id, last_event as usize);
|
|
200
190
|
Poll::Ready(Some(history))
|
|
201
191
|
}
|
|
202
192
|
Poll::Ready(None) => {
|
|
@@ -210,6 +200,5 @@ impl Stream for Historator {
|
|
|
210
200
|
|
|
211
201
|
#[derive(Default)]
|
|
212
202
|
struct HistoratorDat {
|
|
213
|
-
run_id_to_last_event_num: HashMap<String, usize>,
|
|
214
203
|
all_dispatched: bool,
|
|
215
204
|
}
|
|
@@ -139,7 +139,7 @@ impl<'a> tracing::field::Visit for JsonVisitor<'a> {
|
|
|
139
139
|
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
|
|
140
140
|
self.0.insert(
|
|
141
141
|
field.name().to_string(),
|
|
142
|
-
serde_json::json!(format!("{:?}"
|
|
142
|
+
serde_json::json!(format!("{value:?}")),
|
|
143
143
|
);
|
|
144
144
|
}
|
|
145
145
|
}
|