The RIB handles swallowed every failure of their actor: an UPDATE applied to a stopped Adj-RIB-In vanished, and a snapshot of it came back empty. Sessions stayed up, peers' routes went nowhere, and the status page showed a healthy router with no routes. An actor stops only by panicking, so this is the state the server would be in after a bug. - Every operation on AdjRibIn and LocalRib returns Result<_, RibStopped>. LocalRibError is replaced by it. - The server waits on both actors, the advertiser and the dialers. If one stops it sends every peer Cease / Administrative Shutdown and returns an error, so the process exits and can be restarted. Before, the tasks' handles were held and never looked at. - A session that cannot store an UPDATE ends with the same Cease. - The HTTP API answers 503 with the reason for anything that needs a table it cannot read, including /metricz: a scrape that fails is noticed, last known sizes are not. Also: - The routes of a session are now removed even if its task is torn down without running its cleanup (a panic), instead of staying in the table as routes of a peer that is gone. - Table sizes for the status page and metrics are asked for as a count instead of copying the whole table to take its length. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
15 lines
622 B
Rust
15 lines
622 B
Rust
/// A RIB's actor is no longer running, so the table can be neither read nor
|
|
/// changed.
|
|
///
|
|
/// The actor runs for as long as a handle to it exists; it stops early only
|
|
/// by panicking. That is a bug, and one the server cannot work around:
|
|
/// routes would be accepted from peers and go nowhere. Callers pass this up
|
|
/// until the process exits and is restarted, rather than carry on with a
|
|
/// table that looks empty.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
|
|
#[error("the {rib} has stopped")]
|
|
pub struct RibStopped {
|
|
/// Which table: "Adj-RIB-In" or "local RIB".
|
|
pub rib: &'static str,
|
|
}
|