Skip to main content

ResilientWatchConfig

Struct ResilientWatchConfig 

Source
pub struct ResilientWatchConfig {
    pub backoff: Backoff,
    pub cursor_store: Arc<dyn CursorStore>,
    pub from_cursor: Option<Cursor>,
    /* private fields */
}
Expand description

Knobs for StreamClient::resilient_watch. Reuses the Backoff and CursorStore from the ResilientSubscription resilience layer.

Fields§

§backoff: Backoff

Reconnect (and re-anchor-retry) backoff schedule.

§cursor_store: Arc<dyn CursorStore>

Where the resume cursor is persisted across reconnects and restarts.

§from_cursor: Option<Cursor>

Initial resume anchor used on the first connect when the store is empty.

Implementations§

Source§

impl ResilientWatchConfig

Source

pub fn new() -> Self

Start from the defaults (forever-retry backoff, no persistence, no initial cursor).

Source

pub fn cursor_store(self, store: Arc<dyn CursorStore>) -> Self

Persist the resume cursor through store.

Source

pub fn backoff(self, backoff: Backoff) -> Self

Override the reconnect / re-anchor-retry backoff.

Source

pub fn from_cursor(self, cursor: Cursor) -> Self

Seed the first connect’s resume anchor (used only when the store has no persisted cursor).

Source

pub fn watch_set_loader<F, Fut>(self, loader: F) -> Self
where F: Fn(WatchSetBuilder) -> Fut + Send + Sync + 'static, Fut: Future<Output = Result<(), Box<dyn Error + Send + Sync>>> + Send + 'static,

Install a canonical watch-set loader for integrators whose watch-set has a durable source-of-truth (a DB, a config file, an upstream service) outside the wrapper.

Without a loader, ResilientWatch re-registers its in-memory mirror of the add_* / remove_* calls made through it — correct when the watch-set is built once at startup and never drifts, but the mirror is empty after a process restart and goes stale if the truth changes while the stream is down. With a loader, the mirror is treated as a cache of the external truth:

  • The loader runs once after every successful (re)connect, before the consumer’s event stream resumes — so the first events pumped after a reconnect already land on a fully-populated subscription. It receives a fresh WatchSetBuilder and declares the canonical set into it (typically by querying its truth with its own awaits between calls).
  • On return, the builder’s set replaces the mirror: it is canonical. In-process add_* / remove_* calls still mutate the mirror and send live, but the next reconnect re-derives the set from the loader, so the integrator’s truth — not the accumulated in-process edits — is the record across reconnects (this is what closes the restart-loses-mirror and truth-drift-during-disconnect gaps).
  • A loader error is transient: it maps to StreamError::WatchSetLoader, which the reconnect loop backs off and retries on the next connect rather than surfacing — a momentary failure of the integrator’s truth must not crash a consumer whose contract is at-least-once. A permanent loader error (a config typo, a closure that always fails) is indistinguishable from a transient one and so is retried indefinitely: with the default backoff (max_retries: None) the stream never resumes and next simply never yields. Set Backoff::max_retries if you need a permanently-failing loader to surface a terminal error instead of retrying forever. The loader should return Err rather than panic — a panic unwinds through the reconnect and aborts the current next(); it is not caught.

The resume cursor is independent of the watch-set: it still comes from the cursor_store / from_cursor and the re-anchor runs after the loaded set is registered, exactly as without a loader.

let config = ResilientWatchConfig::new().watch_set_loader(|builder: WatchSetBuilder| async move {
    // Query the durable source-of-truth and declare the canonical set.
    let scripts = rows().await?;
    builder.add_scripts(scripts);
    Ok(())
});

Trait Implementations§

Source§

impl Debug for ResilientWatchConfig

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for ResilientWatchConfig

Source§

fn default() -> Self

Returns the “default value” for a type. 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> 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> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
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