72 lines
3.1 KiB
Rust
72 lines
3.1 KiB
Rust
//! One swarm-queue connection, shared by every consumer in this process.
|
|
//!
|
|
//! [`swarm_status`](crate::swarm_status) and
|
|
//! [`swarm_notices`](crate::swarm_notices) both need the swarm queue, and
|
|
//! both authenticate as the *same* identity (`hive-<name>`, minted for
|
|
//! this hive — see `swarm-authelia.nix`). Two independent `connect()`
|
|
//! calls would be two token mints and two live connections for one
|
|
//! identity, not two different credentials — the same shape that turned
|
|
//! `swarm-controller`'s own connect into the shared `swarm-queue-client`
|
|
//! crate in the first place, one layer up. This module is that same move
|
|
//! made again, this time between two consumers *inside* one process.
|
|
//!
|
|
//! Connects lazily on first use rather than at boot — nothing here
|
|
//! blocks `hive-c0re` starting up on hosts with no queue configured,
|
|
//! which is the ordinary case.
|
|
|
|
use tokio::sync::OnceCell;
|
|
|
|
/// Env var prefix for this daemon's swarm-queue credentials — see
|
|
/// [`swarm_queue_client::QueueConfig::from_env`]. All four or none.
|
|
const ENV_PREFIX: &str = "HIVE_C0RE";
|
|
|
|
static CLIENT: OnceCell<Option<async_nats::Client>> = OnceCell::const_new();
|
|
|
|
/// The shared swarm-queue client, connecting on first call and memoized
|
|
/// for the rest of the process's life.
|
|
///
|
|
/// `None` covers both "no queue configured" (the ordinary case, logged
|
|
/// once at `info`) and "config present but connecting failed" (bannered
|
|
/// once via [`crate::warnings::set_boot_warning`] the first time this is
|
|
/// called) — either way, a caller with `None` should just skip whatever
|
|
/// it was about to publish. No caller needs to distinguish the two: both
|
|
/// mean "this hive is not offering anything to the swarm right now."
|
|
pub async fn client() -> Option<async_nats::Client> {
|
|
CLIENT.get_or_init(connect_once).await.clone()
|
|
}
|
|
|
|
async fn connect_once() -> Option<async_nats::Client> {
|
|
let cfg = match swarm_queue_client::QueueConfig::from_env(ENV_PREFIX) {
|
|
Ok(Some(cfg)) => cfg,
|
|
Ok(None) => {
|
|
tracing::info!("no swarm queue configured; this hive offers nothing upward");
|
|
return None;
|
|
}
|
|
Err(e) => {
|
|
// A one-shot startup step with no later retry to clear it —
|
|
// exactly what `set_boot_warning` is for. `chain`, not
|
|
// `{:#}`: this is `swarm_queue_client::Error`, whose
|
|
// `Display` ignores the alternate flag (see `chain`'s own
|
|
// doc comment), so `{:#}` would drop which env vars are
|
|
// actually missing.
|
|
crate::warnings::set_boot_warning(
|
|
"swarm_queue_config",
|
|
"warn",
|
|
format!("swarm queue is off: {}", swarm_queue_client::chain(&e)),
|
|
);
|
|
return None;
|
|
}
|
|
};
|
|
|
|
match swarm_queue_client::connect(cfg).await {
|
|
Ok(client) => Some(client),
|
|
Err(e) => {
|
|
crate::warnings::set_boot_warning(
|
|
"swarm_queue_config",
|
|
"warn",
|
|
format!("swarm queue is off: {}", swarm_queue_client::chain(&e)),
|
|
);
|
|
None
|
|
}
|
|
}
|
|
}
|