swarm-queue-based lifecycle notices, replacing push_todo(MANAGER_AGENT)
This commit is contained in:
parent
10a294a2f8
commit
e44ea9d8d4
12 changed files with 388 additions and 142 deletions
72
hive-c0re/src/swarm_queue.rs
Normal file
72
hive-c0re/src/swarm_queue.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
//! 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
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue