pub struct SupervisorConfig {
pub initial_backoff: Duration,
pub max_backoff: Duration,
pub mandatory_stop: Duration,
pub max_attempts: Option<u32>,
pub anti_thrash_threshold: Option<AntiThrashThreshold>,
pub drop_grace: Duration,
pub max_backoff_after_thrash: Duration,
}Expand description
Configuration for the auto-reconnect supervisor.
The supervisor uses an exponential-backoff schedule between reconnect attempts.
All durations are wall-clock; jitter is applied deterministically (seeded from
Backoff::new).
Fields§
§initial_backoff: DurationInitial backoff delay applied to the first reconnect attempt after a drop.
max_backoff: DurationMaximum backoff delay; subsequent doubled delays clamp here.
mandatory_stop: DurationCumulative-elapsed cap before the schedule snaps to max_backoff. Mirrors
Java’s Backoff.mandatoryStop.
max_attempts: Option<u32>Maximum total reconnect attempts. None means infinite — keep reconnecting
forever (matching Java’s default). Some(N) gives up after N consecutive
failures and surfaces the last error to the caller.
anti_thrash_threshold: Option<AntiThrashThreshold>Anti-thrash detector threshold (ADR-0028). None (the default)
disables the detector and preserves current behaviour — the
supervisor uses only per-handle backoff and the in-band transient
retry path.
When Some(threshold), the supervisor escalates to a
connection-level cooldown once
threshold.successful_attaches consecutive re-attaches succeed and
each is followed by a TCP-level drop within threshold.drop_within
(all inside threshold.window). The cooldown floor is
Self::max_backoff_after_thrash.
Recommended starting values when opting in (see ADR-0028 §“Defaults
and migration”):
AntiThrashThreshold { successful_attaches: 5, window: Duration::from_secs(2), drop_within: Duration::from_millis(50) } with
max_backoff_after_thrash = Duration::from_secs(30).
drop_grace: DurationDriver-side grace window for attributing a transport close to a
recent successful re-attach. When a TransportClosed arrives within
drop_grace of the most recent
ConnectionEvent::ProducerReady
or ConnectionEvent::SubscribeAcked,
the engine driver feeds it into the anti-thrash detector as a
ReAttachOutcomeKind::TcpDropAfterReAttach.
Defaults to Duration::from_millis(500).
The stricter per-pair drop_within knob on
AntiThrashThreshold decides whether the paired entry actually
counts toward the threshold — drop_grace is the engine-side
attribution window only.
max_backoff_after_thrash: DurationCooldown floor applied once
Self::anti_thrash_threshold trips. Stacks above the per-handle
backoff; the supervisor sleeps until at least
now + max_backoff_after_thrash before its next Transport::connect
once the cooldown engages. Default Duration::from_secs(30).
Implementations§
Source§impl SupervisorConfig
impl SupervisorConfig
Sourcepub fn build_backoff(&self, seed: u64) -> Backoff
pub fn build_backoff(&self, seed: u64) -> Backoff
Build a Backoff from this config. seed controls jitter; pass 0 for
the deterministic default seed.
Sourcepub fn should_reset_backoff(&self, socket_alive: Duration) -> bool
pub fn should_reset_backoff(&self, socket_alive: Duration) -> bool
Policy gate for the engine drivers’ persisted Backoff schedule:
returns true when the previous socket survived past Self::drop_grace
— i.e. when the previous reconnect counts as stable and the engine
should call Backoff::reset at the top of the next reconnect cycle.
Sockets that died inside drop_grace of the most recent successful
attach are treated as thrashes: the schedule keeps growing, so
successive ProducerReady-then-drop cycles slow down geometrically up
to max_backoff. This is the per-handle defence in depth that pairs
with the connection-level anti-thrash cooldown (ADR-0028) — both must
be wired for the supervisor to bound CPU under the storm pattern hit
by clients sitting behind the Apache Pulsar Proxy.
Engines call this from the top of the supervisor outer loop with the
wall-clock-elapsed time between the previous socket coming up and
driver_loop_inner returning (i.e. the socket’s lifetime).
Sourcepub fn should_give_up(&self, attempts: u32) -> bool
pub fn should_give_up(&self, attempts: u32) -> bool
Give-up policy gate for the engine drivers’ reconnect budget (ADR-0061).
Returns true once attempts post-drop dial+handshake attempts have
been spent without landing a stable session — i.e. when the supervisor
must stop reconnecting and surface the last error to the caller.
max_attempts == None (the default) never gives up, matching Java’s
infinite reconnect.
attempts is the COUNT OF FAILED CYCLES, hoisted so it spans the FULL
dial+handshake cycle: a TCP-dial failure AND a post-dial handshake
failure each count as one. Behind a TCP-accepting proxy / LB whose
backend is down — the storm class the anti-thrash supervision was built
for — the dial always succeeds but the Pulsar handshake never completes;
counting only dial failures (the pre-ADR-0061 behaviour) let the budget
never fire, so the driver retried forever. Counting EVERY post-dial
failure uniformly (without distinguishing broker-said-no from
connection-dropped) is the simplest rule and matches Java’s bounded
reconnect.
The counter is reset to 0 by the engine ONLY when
Self::should_reset_backoff is true for the previous socket’s
lifetime — so give-up-reset and backoff-reset share ONE stability
definition (a connection that survived drop_grace). A socket that
merely accepted TCP and handshaked but died inside drop_grace does NOT
reset the budget.
Trait Implementations§
Source§impl Clone for SupervisorConfig
impl Clone for SupervisorConfig
Source§fn clone(&self) -> SupervisorConfig
fn clone(&self) -> SupervisorConfig
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more