Skip to main content

RuntimeReloadState

Struct RuntimeReloadState 

Source
pub struct RuntimeReloadState { /* private fields */ }
Expand description

Shared, mutable handles for the fields the runtime can hot-reload.

Held inside an Arc so the SIGHUP handler and the ProbeHandler can both observe updates. Each section is registered as both a concrete Arc<SectionStruct> (so attach_* and accessors can reach into its state) and as Arc<dyn ReloadableSection> (so reload() drives the three-phase iteration without a central match arm per section).

Adding a new reloadable knob: implement ReloadableSection for a new struct, Arc it once at construction, and append to the sections vec — no central touch of RuntimeReloadState::reload.

Implementations§

Source§

impl RuntimeReloadState

Source

pub fn new( observability_cli: ObservabilityArgs, initial: &ResolvedConfig, log_level_setter: LogLevelSetter, ) -> Self

Build a reload state from the resolved-at-startup values plus the closure that mutates the live tracing filter.

current_log_level is intentionally seeded to None rather than to initial.observability.log_level: at startup the live EnvFilter may have been built from RUST_LOG (see commands::run’s try_from_default_env), in which case the resolved config value is not what’s running. Forcing the first reload to apply unconditionally is simpler and more correct than trying to reflect the env-filter directive back into a LogLevel.

Source

pub fn attach_metrics(&self, metrics: Arc<Metrics>)

Attach the node metrics so failed reloads are counted. Call once, before the SIGHUP select loop runs; a second call keeps the first handle.

Source

pub fn attach_cache(&self, engine: Option<CacheEngine>)

Attach the live cache engine after it’s been built. Must be called before the SIGHUP select loop runs — see runtime::run. Detaching is permitted (pass None) but the runtime never needs to: the engine outlives the reload state by construction.

Poison handling. A poisoned mutex is recovered by replacing the inner value via PoisonError::into_inner(), but the poison flag is not cleared — Mutex::lock() will return Err again the next time anyone tries to take the guard. The first subsequent reload() will therefore skip the pinned-set swap for that section (see PinnedHashesSection::infallible_swap). Recovery here ensures the new engine is at least stored for the (non-reload-driven) live path.

Source

pub fn content_denylist(&self) -> Arc<ContentDenylist> ⓘ

The live ADR 011 deny-set, for wiring into the client handler.

Deliberately a getter rather than an attach_*: the deny-set is owned here and shared out, so there is no window in which the handler holds a deny-set the reload path cannot reach. The attach_* pattern exists for handles built after this state; this one is built with it.

Source

pub fn attach_limiter(&self, limiter: Option<Arc<ConnectionLimiter>>)

Attach the live ConnectionLimiter after it’s been built. Same shape as Self::attach_cache: must be called before the SIGHUP select loop, supports None for tests, recovers from a poisoned mutex by replacing the inner state.

Source

pub fn attach_load_shed(&self, controller: Option<Arc<LoadShedController>>)

Attach the live LoadShedController after it’s been built. Same shape as Self::attach_limiter: must be called before the SIGHUP select loop, supports None for tests, recovers from a poisoned mutex by replacing the inner state.

Source

pub fn current(&self) -> ReloadSnapshot

Snapshot the post-reload values an operator wants to confirm: the most recently applied log level.

log_level is None until the first successful reload — the startup EnvFilter may have been built from RUST_LOG rather than the resolved config (see Self::new’s docs), so reporting the resolved-at-startup level there would be misleading. After any successful reload the field tracks what the setter actually applied.

A poisoned current_log_level mutex collapses to None rather than propagating: the caller is admin_v1_reload, which has already received an Ok(()) from reload(); the snapshot is best-effort metadata.

Source

pub async fn reload(&self, path: &Path) -> Result<()>

Re-read the config file at path and apply changes to reloadable fields. Triggered by SIGHUP (see runtime::run’s select loop). On parse error the previous values are retained and the error is logged; the caller (the SIGHUP arm of the select) discards the returned error so a malformed reload never propagates and stops the node.

Three phases, each driven over the registered sections in registration order:

  1. Resolve. Each section re-derives its Resolved value from file (and any CLI overrides held on the section struct) and stashes it in its buffer cell. Any failure aborts the reload before any side-effect runs — the all-or-nothing contract.
  2. Fallible commit. The log-level filter swap is the only currently-fallible commit. Rollback boundary: commits that already succeeded stay applied even if a later section’s fallible_commit fails. The trait makes this boundary explicit.
  3. Infallible swap. Atomic stores, Arc swaps, and ConnectionLimiter::reload. Each section also emits a config reload section applied tracing event keyed by section = name().

A single “requires restart” info line is emitted for each non-reloadable section that carries a non-reloadable field in the new file (see warn_restart_required_sections) so an operator who edited one of those fields sees “you changed X but it needs a restart”. It fires on presence of the field, not on a change to it (no diff against the previous file) — best-effort operator guidance, not a correctness gate.

A failed reload counts into decdn_config_reload_failures_total once Self::attach_metrics has run.

Trait Implementations§

Source§

impl Debug for RuntimeReloadState

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self> ⓘ

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<T> MaybeSend for T
where T: Send,

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more