diff options
| author | tv <tv@krebsco.de> | 2026-10-24 06:53:17 +0200 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-24 06:53:17 +0200 |
| commit | 8ee3b7f0d2f9b76cb24f0049431bd58d09d6c5a4 (patch) | |
| tree | 6e9774ff74634029309e6720e7c8eccce62766cf /src/swarm/members.rs | |
| parent | eeae01887aa7bf5ab4dc4d9c5dc90e06c465accd (diff) | |
add node aliases
Diffstat (limited to 'src/swarm/members.rs')
| -rw-r--r-- | src/swarm/members.rs | 89 |
1 files changed, 78 insertions, 11 deletions
diff --git a/src/swarm/members.rs b/src/swarm/members.rs index e64dd20..e02dba4 100644 --- a/src/swarm/members.rs +++ b/src/swarm/members.rs @@ -7,6 +7,12 @@ //! while it is alive. An operator's forget (`DELETE /peers/{pk}`) removes the entry //! together with writing the forget record; a forgotten node that turns out to be alive //! cancels the record and registers again. +//! +//! Besides its tier, an entry holds the alias a node gives itself (`--alias`), a name +//! for people reading /peers, metrics and logs. Not unique and never an identity: the +//! public key stays that. + +use std::collections::HashMap; use automerge::AutoCommit; use serde_json::{Value as JsonValue, json}; @@ -69,27 +75,88 @@ pub(crate) fn set_tier(doc: &mut AutoCommit, pk: &str, tier: Tier) -> Result<(), store::write_path(doc, &tier_path(pk), &json!(tier.as_str())) } -/// Registers this node if it is ready and its entry is missing. +fn alias_path(pk: &str) -> Vec<String> { + let mut path = member_path(pk); + path.push("alias".to_owned()); + path +} + +/// `pk`'s alias, if it gave itself one. +pub(crate) fn alias(doc: &AutoCommit, pk: &str) -> Option<String> { + match store::read_path(doc, &alias_path(pk)) { + Ok(Some(JsonValue::String(alias))) => Some(alias), + _ => None, + } +} + +/// The aliases of all members that have one. +pub(crate) fn aliases(doc: &AutoCommit) -> HashMap<String, String> { + members(doc) + .into_iter() + .filter_map(|pk| alias(doc, &pk).map(|alias| (pk, alias))) + .collect() +} + +fn set_alias(doc: &mut AutoCommit, pk: &str, alias: Option<&str>) -> Result<(), StoreError> { + match alias { + Some(alias) => store::write_path(doc, &alias_path(pk), &json!(alias)), + None => match store::delete_path(doc, &alias_path(pk), false) { + Err(StoreError::NotFound) => Ok(()), + result => result, + }, + } +} + +/// Registers this node if it is ready and its entry is missing, and keeps its alias +/// as configured (set, changed or removed after a restart with another `--alias`). pub(crate) async fn ensure_registered(state: &AppState) { if !state.is_ready().await { return; } - let own = member_path(state.local_id()); - let registered = store::read_path(&state.doc.read().await.doc, &own) - .ok() - .flatten() - .is_some(); - if registered { + let local = state.local_id().to_owned(); + let own = member_path(&local); + let (registered, recorded_alias) = { + let replica = state.doc.read().await; + let registered = store::read_path(&replica.doc, &own) + .ok() + .flatten() + .is_some(); + (registered, alias(&replica.doc, &local)) + }; + let wanted = state.alias.clone(); + + if !registered { + let mut entry = json!({ "since": unix_millis() }); + if let Some(alias) = &wanted { + entry["alias"] = json!(alias); + } + match state + .mutate_doc(move |doc| store::write_path(doc, &own, &entry)) + .await + { + Ok(()) => info!( + alias = wanted.as_deref(), + "Registered in the swarm's member list" + ), + Err(error) => warn!(error = %error, "Failed to register in the member list"), + } return; } - let entry = json!({ "since": unix_millis() }); + if recorded_alias == wanted { + return; + } + let alias = wanted.clone(); match state - .mutate_doc(move |doc| store::write_path(doc, &own, &entry)) + .mutate_doc(move |doc| set_alias(doc, &local, alias.as_deref())) .await { - Ok(()) => info!("Registered in the swarm's member list"), - Err(error) => warn!(error = %error, "Failed to register in the member list"), + Ok(()) => info!( + alias = wanted.as_deref(), + previous = recorded_alias.as_deref(), + "Alias updated in the member list" + ), + Err(error) => warn!(error = %error, "Failed to record our alias"), } } |
