mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-02 21:06:14 +00:00
Remove the duplicated immutable fields (config, identity, startup_epoch, started_at, is_leaf_only, max_connections/peers/links) from the Node struct so the Arc<NodeContext> bundle is the single source of truth. Previously Node owned these fields and a parallel context copy, kept in lockstep by rebuild_context() at every mutation site — pure overhead that existed only because of the duplication. - Replace rebuild_context() with replace_context(): a clone-edit-swap of the whole Arc. The per-instance context stays immutable; mutation swaps the Arc. This is the sole runtime mutation path (constructors, leaf_only, update_peers). - Add Copy-returning accessors startup_epoch() and max_connections()/ max_peers()/max_links(); migrate the remaining direct field readers onto the accessors. node_addr()/npub()/Debug now read identity/is_leaf_only from the context. - update_peers reads the pre-update peer set from the live context Arc before building a fresh Config + context and swapping — preserving the read-before-write ordering its mutation-window test depends on. - Remove the test-only set_max_* setters; tests set the limits on Config at construction instead (new make_node_with_max_peers/links helpers). - Add a ci-local guard that fails if the Node struct re-declares a bundled field, so the single-store invariant can't silently regress. cargo test --lib 1291/0; clippy -D warnings and release build clean.
74 lines
2.3 KiB
Rust
74 lines
2.3 KiB
Rust
//! Shared immutable context bundle.
|
|
//!
|
|
//! [`NodeContext`] groups the [`Node`](super::Node)'s effectively-immutable
|
|
//! fields behind a single `Arc` so that handlers can borrow a cheap
|
|
//! `&NodeContext` clone instead of `&self`.
|
|
//!
|
|
//! It is the **sole store** of these fields: the `Node` no longer keeps
|
|
//! duplicate copies. The bundle itself is immutable; the rare mutation of a
|
|
//! bundled field (the constructors, [`leaf_only`](super::Node::leaf_only),
|
|
//! and [`update_peers`](super::Node::update_peers)) is done by building a fresh
|
|
//! `NodeContext` and swapping the whole `Arc` via
|
|
//! [`Node::replace_context`](super::Node::replace_context). Readers reach the
|
|
//! fields through the `Node` accessors (`config()`, `identity()`,
|
|
//! `startup_epoch()`, `is_leaf_only()`, `max_*()`, `uptime()`).
|
|
|
|
use std::sync::Arc;
|
|
|
|
use crate::{Config, Identity};
|
|
|
|
/// Effectively-immutable `Node` state, shared via `Arc<NodeContext>`.
|
|
#[derive(Clone)]
|
|
pub(crate) struct NodeContext {
|
|
/// Loaded configuration. A static snapshot: replaced wholesale (never
|
|
/// interior-mutated) when `update_peers` rebuilds the runtime peer list.
|
|
pub config: Arc<Config>,
|
|
|
|
/// This node's cryptographic identity.
|
|
pub identity: Identity,
|
|
|
|
/// Random epoch generated at startup for peer restart detection.
|
|
pub startup_epoch: [u8; 8],
|
|
|
|
/// Instant when the node was created, for uptime reporting.
|
|
pub started_at: std::time::Instant,
|
|
|
|
/// Whether this is a leaf-only node.
|
|
pub is_leaf_only: bool,
|
|
|
|
/// Maximum connections (0 = unlimited).
|
|
pub max_connections: usize,
|
|
|
|
/// Maximum peers (0 = unlimited).
|
|
pub max_peers: usize,
|
|
|
|
/// Maximum links (0 = unlimited).
|
|
pub max_links: usize,
|
|
}
|
|
|
|
impl NodeContext {
|
|
/// Build a context bundle from the individual values.
|
|
#[allow(clippy::too_many_arguments)]
|
|
pub fn new(
|
|
config: Arc<Config>,
|
|
identity: Identity,
|
|
startup_epoch: [u8; 8],
|
|
started_at: std::time::Instant,
|
|
is_leaf_only: bool,
|
|
max_connections: usize,
|
|
max_peers: usize,
|
|
max_links: usize,
|
|
) -> Self {
|
|
Self {
|
|
config,
|
|
identity,
|
|
startup_epoch,
|
|
started_at,
|
|
is_leaf_only,
|
|
max_connections,
|
|
max_peers,
|
|
max_links,
|
|
}
|
|
}
|
|
}
|