@temporalio/core-bridge 1.12.0 → 1.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +64 -119
- package/Cargo.toml +1 -1
- package/index.js +3 -2
- package/package.json +3 -3
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.cargo/config.toml +1 -2
- package/sdk-core/.github/workflows/per-pr.yml +2 -0
- package/sdk-core/AGENTS.md +7 -0
- package/sdk-core/Cargo.toml +9 -5
- package/sdk-core/README.md +6 -5
- package/sdk-core/client/Cargo.toml +3 -2
- package/sdk-core/client/src/lib.rs +17 -8
- package/sdk-core/client/src/metrics.rs +57 -23
- package/sdk-core/client/src/raw.rs +33 -15
- package/sdk-core/core/Cargo.toml +11 -9
- package/sdk-core/core/benches/workflow_replay.rs +114 -15
- package/sdk-core/core/src/core_tests/activity_tasks.rs +18 -18
- package/sdk-core/core/src/core_tests/child_workflows.rs +4 -4
- package/sdk-core/core/src/core_tests/determinism.rs +6 -6
- package/sdk-core/core/src/core_tests/local_activities.rs +20 -20
- package/sdk-core/core/src/core_tests/mod.rs +40 -5
- package/sdk-core/core/src/core_tests/queries.rs +25 -16
- package/sdk-core/core/src/core_tests/replay_flag.rs +3 -3
- package/sdk-core/core/src/core_tests/updates.rs +3 -3
- package/sdk-core/core/src/core_tests/workers.rs +9 -7
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +40 -42
- package/sdk-core/core/src/ephemeral_server/mod.rs +1 -19
- package/sdk-core/core/src/lib.rs +10 -1
- package/sdk-core/core/src/pollers/poll_buffer.rs +2 -2
- package/sdk-core/core/src/replay/mod.rs +3 -3
- package/sdk-core/core/src/telemetry/metrics.rs +306 -152
- package/sdk-core/core/src/telemetry/mod.rs +11 -4
- package/sdk-core/core/src/telemetry/otel.rs +134 -131
- package/sdk-core/core/src/telemetry/prometheus_meter.rs +885 -0
- package/sdk-core/core/src/telemetry/prometheus_server.rs +48 -28
- package/sdk-core/core/src/test_help/mod.rs +27 -12
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +7 -7
- package/sdk-core/core/src/worker/activities.rs +4 -4
- package/sdk-core/core/src/worker/client/mocks.rs +10 -3
- package/sdk-core/core/src/worker/client.rs +68 -5
- package/sdk-core/core/src/worker/heartbeat.rs +229 -0
- package/sdk-core/core/src/worker/mod.rs +35 -14
- package/sdk-core/core/src/worker/tuner/resource_based.rs +4 -4
- package/sdk-core/core/src/worker/workflow/history_update.rs +71 -19
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -2
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -1
- package/sdk-core/core/src/worker/workflow/machines/nexus_operation_state_machine.rs +31 -48
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -2
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +3 -3
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +4 -1
- package/sdk-core/core/src/worker/workflow/managed_run.rs +1 -1
- package/sdk-core/core/src/worker/workflow/mod.rs +15 -15
- package/sdk-core/core-api/Cargo.toml +2 -2
- package/sdk-core/core-api/src/envconfig.rs +204 -99
- package/sdk-core/core-api/src/lib.rs +9 -0
- package/sdk-core/core-api/src/telemetry/metrics.rs +548 -100
- package/sdk-core/core-api/src/worker.rs +11 -5
- package/sdk-core/core-c-bridge/Cargo.toml +49 -0
- package/sdk-core/core-c-bridge/build.rs +26 -0
- package/sdk-core/core-c-bridge/include/temporal-sdk-core-c-bridge.h +817 -0
- package/sdk-core/core-c-bridge/src/client.rs +679 -0
- package/sdk-core/core-c-bridge/src/lib.rs +245 -0
- package/sdk-core/core-c-bridge/src/metric.rs +682 -0
- package/sdk-core/core-c-bridge/src/random.rs +61 -0
- package/sdk-core/core-c-bridge/src/runtime.rs +445 -0
- package/sdk-core/core-c-bridge/src/testing.rs +282 -0
- package/sdk-core/core-c-bridge/src/tests/context.rs +644 -0
- package/sdk-core/core-c-bridge/src/tests/mod.rs +178 -0
- package/sdk-core/core-c-bridge/src/tests/utils.rs +108 -0
- package/sdk-core/core-c-bridge/src/worker.rs +1069 -0
- package/sdk-core/etc/deps.svg +64 -64
- package/sdk-core/sdk/src/activity_context.rs +6 -4
- package/sdk-core/sdk/src/lib.rs +49 -27
- package/sdk-core/sdk/src/workflow_future.rs +18 -25
- package/sdk-core/sdk-core-protos/protos/api_upstream/README.md +4 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/buf.yaml +0 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +630 -83
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +632 -78
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/batch/v1/message.proto +4 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +6 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/common/v1/message.proto +2 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/deployment/v1/message.proto +32 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/common.proto +10 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/deployment.proto +26 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/reset.proto +4 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +47 -31
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +4 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/schedule/v1/message.proto +7 -1
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/worker/v1/message.proto +134 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +14 -11
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +148 -37
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +21 -0
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +4 -4
- package/sdk-core/sdk-core-protos/src/history_builder.rs +9 -5
- package/sdk-core/sdk-core-protos/src/lib.rs +96 -6
- package/sdk-core/test-utils/src/lib.rs +11 -3
- package/sdk-core/tests/cloud_tests.rs +3 -3
- package/sdk-core/tests/heavy_tests.rs +11 -3
- package/sdk-core/tests/integ_tests/client_tests.rs +12 -13
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +1 -1
- package/sdk-core/tests/integ_tests/metrics_tests.rs +188 -83
- package/sdk-core/tests/integ_tests/polling_tests.rs +1 -1
- package/sdk-core/tests/integ_tests/queries_tests.rs +56 -40
- package/sdk-core/tests/integ_tests/update_tests.rs +2 -7
- package/sdk-core/tests/integ_tests/worker_tests.rs +3 -4
- package/sdk-core/tests/integ_tests/worker_versioning_tests.rs +3 -7
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +3 -5
- package/sdk-core/tests/integ_tests/workflow_tests/nexus.rs +24 -17
- package/src/client.rs +6 -0
- package/src/metrics.rs +6 -6
|
@@ -69,7 +69,13 @@ pub enum ConfigError {
|
|
|
69
69
|
InvalidConfig(String),
|
|
70
70
|
|
|
71
71
|
#[error("Configuration loading error: {0}")]
|
|
72
|
-
LoadError(
|
|
72
|
+
LoadError(Box<dyn std::error::Error>),
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
impl From<std::env::VarError> for ConfigError {
|
|
76
|
+
fn from(e: std::env::VarError) -> Self {
|
|
77
|
+
Self::LoadError(e.into())
|
|
78
|
+
}
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
impl From<std::str::Utf8Error> for ConfigError {
|
|
@@ -198,6 +204,33 @@ pub struct ClientConfigFromTOMLOptions {
|
|
|
198
204
|
pub strict: bool,
|
|
199
205
|
}
|
|
200
206
|
|
|
207
|
+
/// A source for environment variables, which can be either a provided HashMap or the system's
|
|
208
|
+
/// environment. This allows for deferred/lazy reading of system env vars.
|
|
209
|
+
enum EnvProvider<'a> {
|
|
210
|
+
Map(&'a HashMap<String, String>),
|
|
211
|
+
System,
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
impl<'a> EnvProvider<'a> {
|
|
215
|
+
fn get(&self, key: &str) -> Result<Option<String>, ConfigError> {
|
|
216
|
+
match self {
|
|
217
|
+
EnvProvider::Map(map) => Ok(map.get(key).cloned()),
|
|
218
|
+
EnvProvider::System => match std::env::var(key) {
|
|
219
|
+
Ok(v) => Ok(Some(v)),
|
|
220
|
+
Err(std::env::VarError::NotPresent) => Ok(None),
|
|
221
|
+
Err(e) => Err(e.into()),
|
|
222
|
+
},
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
fn contains_key(&self, key: &str) -> Result<bool, ConfigError> {
|
|
227
|
+
match self {
|
|
228
|
+
EnvProvider::Map(map) => Ok(map.contains_key(key)),
|
|
229
|
+
EnvProvider::System => Ok(std::env::var(key).is_ok()),
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
201
234
|
/// Read bytes from a file path, returning Ok(None) if it doesn't exist
|
|
202
235
|
fn read_path_bytes(path: &str) -> Result<Option<Vec<u8>>, ConfigError> {
|
|
203
236
|
if !Path::new(path).exists() {
|
|
@@ -210,24 +243,32 @@ fn read_path_bytes(path: &str) -> Result<Option<Vec<u8>>, ConfigError> {
|
|
|
210
243
|
}
|
|
211
244
|
}
|
|
212
245
|
|
|
213
|
-
/// Load client configuration from TOML.
|
|
214
|
-
///
|
|
215
|
-
///
|
|
246
|
+
/// Load client configuration from TOML. This function uses environment variables (which are
|
|
247
|
+
/// taken from the system if not provided) to locate the configuration file. It does not apply
|
|
248
|
+
/// other environment variable values; that is handled by [load_client_config_profile]. This will
|
|
249
|
+
/// not fail if the file does not exist.
|
|
216
250
|
pub fn load_client_config(
|
|
217
251
|
options: LoadClientConfigOptions,
|
|
218
252
|
env_vars: Option<&HashMap<String, String>>,
|
|
219
253
|
) -> Result<ClientConfig, ConfigError> {
|
|
254
|
+
let env_provider = match env_vars {
|
|
255
|
+
Some(map) => EnvProvider::Map(map),
|
|
256
|
+
None => EnvProvider::System,
|
|
257
|
+
};
|
|
258
|
+
|
|
220
259
|
// Get which bytes to load from TOML
|
|
221
260
|
let toml_data = match options.config_source {
|
|
222
261
|
Some(DataSource::Data(d)) => Some(d),
|
|
223
262
|
Some(DataSource::Path(p)) => read_path_bytes(&p)?,
|
|
224
263
|
None => {
|
|
225
|
-
let file_path =
|
|
226
|
-
.
|
|
264
|
+
let file_path = if let Some(path) = env_provider
|
|
265
|
+
.get("TEMPORAL_CONFIG_FILE")?
|
|
227
266
|
.filter(|p| !p.is_empty())
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
267
|
+
{
|
|
268
|
+
path
|
|
269
|
+
} else {
|
|
270
|
+
get_default_config_file_path()?
|
|
271
|
+
};
|
|
231
272
|
read_path_bytes(&file_path)?
|
|
232
273
|
}
|
|
233
274
|
};
|
|
@@ -244,7 +285,20 @@ pub fn load_client_config(
|
|
|
244
285
|
}
|
|
245
286
|
}
|
|
246
287
|
|
|
247
|
-
/// Load a specific client configuration profile
|
|
288
|
+
/// Load a specific client configuration profile.
|
|
289
|
+
///
|
|
290
|
+
/// This function is the primary entry point for loading client configuration. It orchestrates loading
|
|
291
|
+
/// from a TOML file (if not disabled) and then applies overrides from environment variables (if not disabled).
|
|
292
|
+
///
|
|
293
|
+
/// The resolution order is as follows:
|
|
294
|
+
/// 1. A profile is loaded from a TOML file. The file is located by checking `options.config_source`,
|
|
295
|
+
/// then the `TEMPORAL_CONFIG_FILE` environment variable, then a default path. The profile within
|
|
296
|
+
/// the file is determined by `options.config_file_profile`, then the `TEMPORAL_PROFILE`
|
|
297
|
+
/// environment variable, then the "default" profile.
|
|
298
|
+
/// 2. Environment variables are applied on top of the loaded profile.
|
|
299
|
+
///
|
|
300
|
+
/// If `env_vars` is provided as a `HashMap`, it will be used as the source for environment
|
|
301
|
+
/// variables. If it is `None`, the function will fall back to using the system's environment variables.
|
|
248
302
|
pub fn load_client_config_profile(
|
|
249
303
|
options: LoadClientConfigProfileOptions,
|
|
250
304
|
env_vars: Option<&HashMap<String, String>>,
|
|
@@ -255,6 +309,15 @@ pub fn load_client_config_profile(
|
|
|
255
309
|
));
|
|
256
310
|
}
|
|
257
311
|
|
|
312
|
+
let env_provider = if options.disable_env {
|
|
313
|
+
None
|
|
314
|
+
} else {
|
|
315
|
+
Some(match env_vars {
|
|
316
|
+
Some(map) => EnvProvider::Map(map),
|
|
317
|
+
None => EnvProvider::System,
|
|
318
|
+
})
|
|
319
|
+
};
|
|
320
|
+
|
|
258
321
|
let mut profile = if options.disable_file {
|
|
259
322
|
ClientConfigProfile::default()
|
|
260
323
|
} else {
|
|
@@ -268,13 +331,17 @@ pub fn load_client_config_profile(
|
|
|
268
331
|
)?;
|
|
269
332
|
|
|
270
333
|
// Determine profile name
|
|
271
|
-
let (profile_name, profile_unset) =
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
334
|
+
let (profile_name, profile_unset) = if let Some(p) = options.config_file_profile.as_deref()
|
|
335
|
+
{
|
|
336
|
+
(p.to_string(), false)
|
|
337
|
+
} else {
|
|
338
|
+
match env_provider.as_ref() {
|
|
339
|
+
Some(provider) => match provider.get("TEMPORAL_PROFILE")? {
|
|
340
|
+
Some(p) if !p.is_empty() => (p, false),
|
|
341
|
+
_ => (DEFAULT_PROFILE.to_string(), true),
|
|
342
|
+
},
|
|
343
|
+
None => (DEFAULT_PROFILE.to_string(), true),
|
|
344
|
+
}
|
|
278
345
|
};
|
|
279
346
|
|
|
280
347
|
if let Some(prof) = config.profiles.get(&profile_name) {
|
|
@@ -288,9 +355,7 @@ pub fn load_client_config_profile(
|
|
|
288
355
|
|
|
289
356
|
// Apply environment variables if not disabled
|
|
290
357
|
if !options.disable_env {
|
|
291
|
-
|
|
292
|
-
profile.apply_env_vars(vars)?;
|
|
293
|
-
}
|
|
358
|
+
profile.load_from_env(env_vars)?;
|
|
294
359
|
}
|
|
295
360
|
|
|
296
361
|
// Apply API key → TLS auto-enabling logic
|
|
@@ -332,33 +397,35 @@ impl ClientConfig {
|
|
|
332
397
|
}
|
|
333
398
|
|
|
334
399
|
impl ClientConfigProfile {
|
|
335
|
-
/// Apply environment variable overrides to this profile
|
|
336
|
-
|
|
400
|
+
/// Apply environment variable overrides to this profile.
|
|
401
|
+
/// If `env_vars` is `None`, the system's environment variables will be used as the source.
|
|
402
|
+
pub fn load_from_env(
|
|
337
403
|
&mut self,
|
|
338
|
-
env_vars:
|
|
404
|
+
env_vars: Option<&HashMap<String, String>>,
|
|
339
405
|
) -> Result<(), ConfigError> {
|
|
406
|
+
let env_provider = match env_vars {
|
|
407
|
+
Some(map) => EnvProvider::Map(map),
|
|
408
|
+
None => EnvProvider::System,
|
|
409
|
+
};
|
|
340
410
|
// Apply basic settings
|
|
341
|
-
if let Some(address) =
|
|
342
|
-
self.address = Some(address
|
|
411
|
+
if let Some(address) = env_provider.get("TEMPORAL_ADDRESS")? {
|
|
412
|
+
self.address = Some(address);
|
|
343
413
|
}
|
|
344
|
-
if let Some(namespace) =
|
|
345
|
-
self.namespace = Some(namespace
|
|
414
|
+
if let Some(namespace) = env_provider.get("TEMPORAL_NAMESPACE")? {
|
|
415
|
+
self.namespace = Some(namespace);
|
|
346
416
|
}
|
|
347
|
-
if let Some(api_key) =
|
|
348
|
-
self.api_key = Some(api_key
|
|
417
|
+
if let Some(api_key) = env_provider.get("TEMPORAL_API_KEY")? {
|
|
418
|
+
self.api_key = Some(api_key);
|
|
349
419
|
}
|
|
350
420
|
|
|
351
|
-
self.apply_tls_env_vars(
|
|
352
|
-
self.apply_codec_env_vars(
|
|
353
|
-
self.apply_grpc_meta_env_vars(
|
|
421
|
+
self.apply_tls_env_vars(&env_provider)?;
|
|
422
|
+
self.apply_codec_env_vars(&env_provider)?;
|
|
423
|
+
self.apply_grpc_meta_env_vars(&env_provider)?;
|
|
354
424
|
|
|
355
425
|
Ok(())
|
|
356
426
|
}
|
|
357
427
|
|
|
358
|
-
fn apply_tls_env_vars(
|
|
359
|
-
&mut self,
|
|
360
|
-
env_vars: &HashMap<String, String>,
|
|
361
|
-
) -> Result<(), ConfigError> {
|
|
428
|
+
fn apply_tls_env_vars(&mut self, env_provider: &EnvProvider) -> Result<(), ConfigError> {
|
|
362
429
|
const TLS_ENV_VARS: &[&str] = &[
|
|
363
430
|
"TEMPORAL_TLS",
|
|
364
431
|
"TEMPORAL_TLS_CLIENT_CERT_PATH",
|
|
@@ -371,82 +438,91 @@ impl ClientConfigProfile {
|
|
|
371
438
|
"TEMPORAL_TLS_DISABLE_HOST_VERIFICATION",
|
|
372
439
|
];
|
|
373
440
|
|
|
374
|
-
if
|
|
441
|
+
if self.tls.is_none() && has_any_env_var(env_provider, TLS_ENV_VARS)? {
|
|
375
442
|
self.tls = Some(ClientConfigTLS::default());
|
|
376
443
|
}
|
|
377
444
|
|
|
378
445
|
if let Some(ref mut tls) = self.tls {
|
|
379
|
-
if let Some(disabled_str) =
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
446
|
+
if let Some(disabled_str) = env_provider.get("TEMPORAL_TLS")?
|
|
447
|
+
&& let Some(disabled) = env_var_to_bool(&disabled_str)
|
|
448
|
+
{
|
|
449
|
+
tls.disabled = !disabled;
|
|
383
450
|
}
|
|
384
451
|
|
|
385
452
|
apply_data_source_env_var(
|
|
386
|
-
|
|
453
|
+
env_provider,
|
|
387
454
|
"cert",
|
|
388
455
|
"TEMPORAL_TLS_CLIENT_CERT_PATH",
|
|
389
456
|
"TEMPORAL_TLS_CLIENT_CERT_DATA",
|
|
390
457
|
&mut tls.client_cert,
|
|
391
458
|
)?;
|
|
392
459
|
apply_data_source_env_var(
|
|
393
|
-
|
|
460
|
+
env_provider,
|
|
394
461
|
"key",
|
|
395
462
|
"TEMPORAL_TLS_CLIENT_KEY_PATH",
|
|
396
463
|
"TEMPORAL_TLS_CLIENT_KEY_DATA",
|
|
397
464
|
&mut tls.client_key,
|
|
398
465
|
)?;
|
|
399
466
|
apply_data_source_env_var(
|
|
400
|
-
|
|
467
|
+
env_provider,
|
|
401
468
|
"server CA cert",
|
|
402
469
|
"TEMPORAL_TLS_SERVER_CA_CERT_PATH",
|
|
403
470
|
"TEMPORAL_TLS_SERVER_CA_CERT_DATA",
|
|
404
471
|
&mut tls.server_ca_cert,
|
|
405
472
|
)?;
|
|
406
473
|
|
|
407
|
-
if let Some(v) =
|
|
408
|
-
tls.server_name = Some(v
|
|
474
|
+
if let Some(v) = env_provider.get("TEMPORAL_TLS_SERVER_NAME")? {
|
|
475
|
+
tls.server_name = Some(v);
|
|
409
476
|
}
|
|
410
|
-
if let Some(v) =
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
477
|
+
if let Some(v) = env_provider.get("TEMPORAL_TLS_DISABLE_HOST_VERIFICATION")?
|
|
478
|
+
&& let Some(b) = env_var_to_bool(&v)
|
|
479
|
+
{
|
|
480
|
+
tls.disable_host_verification = b;
|
|
414
481
|
}
|
|
415
482
|
}
|
|
416
483
|
Ok(())
|
|
417
484
|
}
|
|
418
485
|
|
|
419
|
-
fn apply_codec_env_vars(
|
|
420
|
-
&mut self,
|
|
421
|
-
env_vars: &HashMap<String, String>,
|
|
422
|
-
) -> Result<(), ConfigError> {
|
|
486
|
+
fn apply_codec_env_vars(&mut self, env_provider: &EnvProvider) -> Result<(), ConfigError> {
|
|
423
487
|
const CODEC_ENV_VARS: &[&str] = &["TEMPORAL_CODEC_ENDPOINT", "TEMPORAL_CODEC_AUTH"];
|
|
424
|
-
if
|
|
488
|
+
if self.codec.is_none() && has_any_env_var(env_provider, CODEC_ENV_VARS)? {
|
|
425
489
|
self.codec = Some(ClientConfigCodec::default());
|
|
426
490
|
}
|
|
427
491
|
|
|
428
492
|
if let Some(ref mut codec) = self.codec {
|
|
429
|
-
if let Some(endpoint) =
|
|
430
|
-
codec.endpoint = Some(endpoint
|
|
493
|
+
if let Some(endpoint) = env_provider.get("TEMPORAL_CODEC_ENDPOINT")? {
|
|
494
|
+
codec.endpoint = Some(endpoint);
|
|
431
495
|
}
|
|
432
|
-
if let Some(auth) =
|
|
433
|
-
codec.auth = Some(auth
|
|
496
|
+
if let Some(auth) = env_provider.get("TEMPORAL_CODEC_AUTH")? {
|
|
497
|
+
codec.auth = Some(auth);
|
|
434
498
|
}
|
|
435
499
|
}
|
|
436
500
|
Ok(())
|
|
437
501
|
}
|
|
438
502
|
|
|
439
|
-
fn apply_grpc_meta_env_vars(
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
503
|
+
fn apply_grpc_meta_env_vars(&mut self, env_provider: &EnvProvider) -> Result<(), ConfigError> {
|
|
504
|
+
let mut handle_meta_var = |header_name: &str, value: &str| {
|
|
505
|
+
let normalized_name = normalize_grpc_meta_key(header_name);
|
|
506
|
+
if value.is_empty() {
|
|
507
|
+
self.grpc_meta.remove(&normalized_name);
|
|
508
|
+
} else {
|
|
509
|
+
self.grpc_meta.insert(normalized_name, value.to_string());
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
match env_provider {
|
|
514
|
+
EnvProvider::Map(map) => {
|
|
515
|
+
for (key, value) in map.iter() {
|
|
516
|
+
if let Some(header_name) = key.strip_prefix("TEMPORAL_GRPC_META_") {
|
|
517
|
+
handle_meta_var(header_name, value);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
EnvProvider::System => {
|
|
522
|
+
for (key, value) in std::env::vars() {
|
|
523
|
+
if let Some(header_name) = key.strip_prefix("TEMPORAL_GRPC_META_") {
|
|
524
|
+
handle_meta_var(header_name, &value);
|
|
525
|
+
}
|
|
450
526
|
}
|
|
451
527
|
}
|
|
452
528
|
}
|
|
@@ -462,47 +538,51 @@ impl ClientConfigProfile {
|
|
|
462
538
|
}
|
|
463
539
|
}
|
|
464
540
|
|
|
541
|
+
/// Helper to check if any of the given environment variables are set.
|
|
542
|
+
fn has_any_env_var(env_provider: &EnvProvider, keys: &[&str]) -> Result<bool, ConfigError> {
|
|
543
|
+
for &key in keys {
|
|
544
|
+
if env_provider.contains_key(key)? {
|
|
545
|
+
return Ok(true);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
Ok(false)
|
|
549
|
+
}
|
|
550
|
+
|
|
465
551
|
/// Helper for applying env vars to a data source.
|
|
466
552
|
fn apply_data_source_env_var(
|
|
467
|
-
|
|
553
|
+
env_provider: &EnvProvider,
|
|
468
554
|
name: &str,
|
|
469
555
|
path_var: &str,
|
|
470
556
|
data_var: &str,
|
|
471
557
|
dest: &mut Option<DataSource>,
|
|
472
558
|
) -> Result<(), ConfigError> {
|
|
473
|
-
let
|
|
474
|
-
let
|
|
559
|
+
let path_val = env_provider.get(path_var)?;
|
|
560
|
+
let data_val = env_provider.get(data_var)?;
|
|
475
561
|
|
|
476
|
-
|
|
477
|
-
|
|
562
|
+
match (path_val, data_val) {
|
|
563
|
+
(Some(_), Some(_)) => Err(ConfigError::InvalidConfig(format!(
|
|
478
564
|
"Cannot specify both {path_var} and {data_var}"
|
|
479
|
-
)))
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
"Cannot specify {name} data via {data_var} when {name} path is already specified"
|
|
489
|
-
)));
|
|
565
|
+
))),
|
|
566
|
+
(Some(path), None) => {
|
|
567
|
+
if let Some(DataSource::Data(_)) = dest {
|
|
568
|
+
return Err(ConfigError::InvalidConfig(format!(
|
|
569
|
+
"Cannot specify {name} path via {path_var} when {name} data is already specified"
|
|
570
|
+
)));
|
|
571
|
+
}
|
|
572
|
+
*dest = Some(DataSource::Path(path));
|
|
573
|
+
Ok(())
|
|
490
574
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
return Err(ConfigError::InvalidConfig(format!(
|
|
500
|
-
"Cannot specify {name} path via {path_var} when {name} data is already specified"
|
|
501
|
-
)));
|
|
575
|
+
(None, Some(data)) => {
|
|
576
|
+
if let Some(DataSource::Path(_)) = dest {
|
|
577
|
+
return Err(ConfigError::InvalidConfig(format!(
|
|
578
|
+
"Cannot specify {name} data via {data_var} when {name} path is already specified"
|
|
579
|
+
)));
|
|
580
|
+
}
|
|
581
|
+
*dest = Some(DataSource::Data(data.into_bytes()));
|
|
582
|
+
Ok(())
|
|
502
583
|
}
|
|
503
|
-
|
|
584
|
+
(None, None) => Ok(()),
|
|
504
585
|
}
|
|
505
|
-
Ok(())
|
|
506
586
|
}
|
|
507
587
|
|
|
508
588
|
/// Parse a boolean value from string (supports "true", "false", "1", "0")
|
|
@@ -1541,4 +1621,29 @@ address = "some-address"
|
|
|
1541
1621
|
// TLS should not be enabled
|
|
1542
1622
|
assert!(profile.tls.is_none());
|
|
1543
1623
|
}
|
|
1624
|
+
|
|
1625
|
+
#[test]
|
|
1626
|
+
fn test_load_client_config_profile_from_system_env() {
|
|
1627
|
+
// Set up system env vars. These tests can't be run in parallel.
|
|
1628
|
+
unsafe {
|
|
1629
|
+
std::env::set_var("TEMPORAL_ADDRESS", "system-address");
|
|
1630
|
+
std::env::set_var("TEMPORAL_NAMESPACE", "system-namespace");
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
let options = LoadClientConfigProfileOptions {
|
|
1634
|
+
disable_file: true, // Don't load from any files
|
|
1635
|
+
..Default::default()
|
|
1636
|
+
};
|
|
1637
|
+
|
|
1638
|
+
// Pass None for env_vars to trigger system env var loading
|
|
1639
|
+
let profile = load_client_config_profile(options, None).unwrap();
|
|
1640
|
+
assert_eq!(profile.address.as_ref().unwrap(), "system-address");
|
|
1641
|
+
assert_eq!(profile.namespace.as_ref().unwrap(), "system-namespace");
|
|
1642
|
+
|
|
1643
|
+
// Clean up
|
|
1644
|
+
unsafe {
|
|
1645
|
+
std::env::remove_var("TEMPORAL_ADDRESS");
|
|
1646
|
+
std::env::remove_var("TEMPORAL_NAMESPACE");
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1544
1649
|
}
|
|
@@ -138,3 +138,12 @@ pub trait Worker: Send + Sync {
|
|
|
138
138
|
/// functions have returned `ShutDown` errors.
|
|
139
139
|
async fn finalize_shutdown(self);
|
|
140
140
|
}
|
|
141
|
+
|
|
142
|
+
macro_rules! dbg_panic {
|
|
143
|
+
($($arg:tt)*) => {
|
|
144
|
+
use tracing::error;
|
|
145
|
+
error!($($arg)*);
|
|
146
|
+
debug_assert!(false, $($arg)*);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
pub(crate) use dbg_panic;
|