atlas_rdma/env.rs
1// SPDX-License-Identifier: AGPL-3.0-only
2//
3// Rail-env resolution helpers. The five RDMA clients share the SHAPE of this
4// logic but not the semantics: two distinct empty-string behaviors exist in
5// the deployed configs and BOTH must be preserved exactly —
6//
7// * `first_set` — an exported-but-EMPTY var counts as set (the
8// `Result::or_else` / `unwrap_or_else` chains: KV / expert / snapshot
9// single-key reads and the LoRA DEV chain).
10// * `first_nonempty` — an empty var is SKIPPED (weight tier's `env_str`,
11// which lets `ATLAS_WEIGHT_RDMA_DEV=""` fall through to the EXPERT name).
12//
13// Each client passes its EXACT key list; the fallback chains are per-tier
14// deployment surface (e.g. LoRA's GID reads ONLY `ATLAS_LORA_RDMA_GID` — no
15// WEIGHT/EXPERT fallback), so no chain is hardcoded here.
16
17/// First key whose var is present in the environment — even if empty.
18pub fn first_set(keys: &[&str], default: &str) -> String {
19 for k in keys {
20 if let Ok(v) = std::env::var(k) {
21 return v;
22 }
23 }
24 default.to_string()
25}
26
27/// First key whose var is present AND non-empty (weight-tier semantics).
28pub fn first_nonempty(keys: &[&str], default: &str) -> String {
29 for k in keys {
30 if let Ok(v) = std::env::var(k)
31 && !v.is_empty()
32 {
33 return v;
34 }
35 }
36 default.to_string()
37}
38
39/// First key whose var is present AND parses as `u32`; otherwise `default`.
40/// (A set-but-unparseable var falls through — the behavior of every existing
41/// per-client `env_u32`, single- and multi-key alike.)
42pub fn first_set_u32(keys: &[&str], default: u32) -> u32 {
43 for k in keys {
44 if let Some(v) = std::env::var(k).ok().and_then(|s| s.parse().ok()) {
45 return v;
46 }
47 }
48 default
49}