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
impl RuntimeReloadState
Sourcepub fn new(
observability_cli: ObservabilityArgs,
initial: &ResolvedConfig,
log_level_setter: LogLevelSetter,
) -> Self
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.
Sourcepub fn attach_metrics(&self, metrics: Arc<Metrics>)
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.
Sourcepub fn attach_cache(&self, engine: Option<CacheEngine>)
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.
Sourcepub fn content_denylist(&self) -> Arc<ContentDenylist> ⓘ
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.
Sourcepub fn attach_limiter(&self, limiter: Option<Arc<ConnectionLimiter>>)
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.
Sourcepub fn attach_load_shed(&self, controller: Option<Arc<LoadShedController>>)
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.
Sourcepub fn current(&self) -> ReloadSnapshot
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.
Sourcepub async fn reload(&self, path: &Path) -> Result<()>
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:
- Resolve. Each section re-derives its
Resolvedvalue fromfile(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. - 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_commitfails. The trait makes this boundary explicit. - Infallible swap. Atomic stores,
Arcswaps, andConnectionLimiter::reload. Each section also emits aconfig reload section appliedtracing event keyed bysection = 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§
Auto Trait Implementations§
impl !Freeze for RuntimeReloadState
impl !RefUnwindSafe for RuntimeReloadState
impl !UnwindSafe for RuntimeReloadState
impl Send for RuntimeReloadState
impl Sync for RuntimeReloadState
impl Unpin for RuntimeReloadState
impl UnsafeUnpin for RuntimeReloadState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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 moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request