diff options
Diffstat (limited to 'src/swarm')
| -rw-r--r-- | src/swarm/members.rs | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/src/swarm/members.rs b/src/swarm/members.rs index 05c6501..a534c04 100644 --- a/src/swarm/members.rs +++ b/src/swarm/members.rs @@ -10,7 +10,8 @@ //! //! Besides its tier, an entry holds the alias a node gives itself (`--alias`), a name //! for people reading /peers and metrics (not unique and never an identity: the public -//! key stays that), where it can be reached (`addresses`, as its transport gives them: +//! key stays that), where people reach its dashboard (`--dashboard-url`, `dashboard`), +//! where it can be reached (`addresses`, as its transport gives them: //! hints for the others' transports), and an `alive` stamp the node renews now and //! then: the members renewed within `--electorate-window` are the electorate of a //! remake. @@ -114,6 +115,34 @@ fn set_alias(doc: &mut impl Transactable, pk: &str, alias: Option<&str>) -> Resu } } +fn dashboard_path(pk: &str) -> Vec<String> { + let mut path = member_path(pk); + path.push("dashboard".to_owned()); + path +} + +/// Where people reach `pk`'s dashboard, if it says. +pub(crate) fn dashboard(doc: &Document, pk: &str) -> Option<String> { + match store::read_path(doc, &dashboard_path(pk)) { + Ok(Some(JsonValue::String(url))) => Some(url), + _ => None, + } +} + +fn set_dashboard( + doc: &mut impl Transactable, + pk: &str, + url: Option<&str>, +) -> Result<(), StoreError> { + match url { + Some(url) => store::write_path(doc, &dashboard_path(pk), &json!(url)), + None => match store::delete_path(doc, &dashboard_path(pk), false) { + Err(StoreError::NotFound) => Ok(()), + result => result, + }, + } +} + fn addresses_path(pk: &str) -> Vec<String> { let mut path = member_path(pk); path.push("addresses".to_owned()); @@ -260,8 +289,9 @@ const RENEWAL_MOST_OFTEN: Duration = Duration::from_secs(3600); pub(crate) const MIN_ELECTORATE_WINDOW: Duration = Duration::from_secs(7 * RENEWAL_MOST_OFTEN.as_secs()); -/// Registers this node if it is ready and its entry is missing, keeps its alias as -/// configured (set, changed or removed after a restart with another `--alias`) and its +/// Registers this node if it is ready and its entry is missing, keeps its alias and its +/// dashboard's URL as configured (set, changed or removed after a restart with another +/// `--alias` or `--dashboard-url`) and its /// addresses as the transport gives them, and renews its `alive` stamp now and then /// (see `electorate`). pub(crate) async fn ensure_registered(state: &AppState) { @@ -271,7 +301,15 @@ pub(crate) async fn ensure_registered(state: &AppState) { let local = state.local_id().to_owned(); let own = member_path(&local); let window = state.electorate_window.as_millis() as u64; - let (registered, recorded_alias, recorded_addresses, alive, recorded_window, shortest) = { + let ( + registered, + recorded_alias, + recorded_dashboard, + recorded_addresses, + alive, + recorded_window, + shortest, + ) = { let replica = state.doc.read().await; let registered = store::read_path(&replica.doc, &own) .ok() @@ -280,6 +318,7 @@ pub(crate) async fn ensure_registered(state: &AppState) { ( registered, alias(&replica.doc, &local), + dashboard(&replica.doc, &local), addresses(&replica.doc, &local), millis_at(&replica.doc, &alive_path(&local)), millis_at(&replica.doc, &window_path(&local)), @@ -301,6 +340,9 @@ pub(crate) async fn ensure_registered(state: &AppState) { if let Some(alias) = &wanted { entry["alias"] = json!(alias); } + if let Some(url) = &state.dashboard_url { + entry["dashboard"] = json!(url); + } match state .mutate_doc(move |doc| store::write_path(doc, &own, &entry)) .await @@ -352,6 +394,21 @@ pub(crate) async fn ensure_registered(state: &AppState) { } } + if recorded_dashboard != state.dashboard_url { + let url = state.dashboard_url.clone(); + let local = local.clone(); + match state + .mutate_doc(move |doc| set_dashboard(doc, &local, url.as_deref())) + .await + { + Ok(()) => info!( + url = state.dashboard_url.as_deref(), + "Dashboard URL updated in the member list" + ), + Err(error) => warn!(error = %error, "Failed to record our dashboard URL"), + } + } + if recorded_alias == wanted { return; } |
