pub struct SchemaStore { /* private fields */ }decode only.Expand description
Per-producer schema sets, fetched lazily and cached for the process.
Bounded (#340). All three maps are keyed by a producer name lifted out
of arbitrary bus traffic, so all three are BoundedLru at
DEFAULT_MAX_PRODUCERS, and each keeps its own eviction count —
SchemaStore::bounds, beside SchemaStore::known.
Implementations§
Source§impl SchemaStore
impl SchemaStore
pub fn new(base: impl Into<String>, timeout: Duration) -> Self
Sourcepub fn bounded(
base: impl Into<String>,
timeout: Duration,
max_producers: usize,
) -> Self
pub fn bounded( base: impl Into<String>, timeout: Duration, max_producers: usize, ) -> Self
A store that remembers at most max_producers producers (#340).
Sourcepub fn bounds(&self) -> StoreBounds
pub fn bounds(&self) -> StoreBounds
What the bounds hold and what they have cost (#340, RFC 13 §3 O6).
Read it beside known: that says what the store can
answer for, this says what it stopped being able to answer for.
Sourcepub fn seal(&self) -> Sealed<'_>
pub fn seal(&self) -> Sealed<'_>
Stop decodes from going to the bus until the guard drops (#337).
A judging window’s drain loop calls decode_sample per sample, and
on a cache miss that used to be a describe GET, awaited inside the
loop, bounded by this store’s timeout. Nobody drains the monitor’s
bounded broadcast while it is in flight, so the window loses samples
to its own decode — and loses them twice over, because the window’s
deadline does not extend to cover the wait. Self-inflicted
Dropped(n) in the one place where the whole product is a verdict
about a window (RFC 13 §3 O6).
Sealed, a miss is simply a miss: set_for answers
from the cache or returns None, which reads through as
NotValidated(NoSchema) — “asked, none served” — and records nothing,
because a seal is a fact about the observer, not about the producer.
It does not stop the store talking to the fleet: prewarm still
asks. That is the distinction — a deliberate ask, made where the
caller has decided it is safe to wait, is fine; an incidental one from
inside a drain loop is not.
Sourcepub fn register_decoder(&self, decoder: Box<dyn PayloadDecoder>)
pub fn register_decoder(&self, decoder: Box<dyn PayloadDecoder>)
Register a custom kind’s codec (RFC 08 §7 is open to kinds beyond the built-ins; later registrations win on conflict).
Takes &self, unlike the decoders_mut it replaces: every frontend
shares one store through an Arc, so a &mut self setter could only
be called before the store was shared — which is to say, not by the
code that has the store.
Sourcepub fn insert(&self, producer: impl Into<String>, set: SchemaSet)
pub fn insert(&self, producer: impl Into<String>, set: SchemaSet)
Pre-warm one producer’s served set with a describe reply the caller
already holds (RFC 08 §7).
The doctor fetches every producer’s describe document in its GET phase and then opens a listen window; without this the window’s store starts empty and re-asks the fleet, mid-window, for documents the same run already has — load this tool put on the fleet for nothing.
Authoritative, not a hint: it overwrites whatever the store held, including a negative entry still inside its backoff.
Sourcepub async fn schema_for(
&self,
session: &Session,
producer: &str,
type_name: &str,
) -> Option<TypeSchema>
pub async fn schema_for( &self, session: &Session, producer: &str, type_name: &str, ) -> Option<TypeSchema>
The schema for type_name as served by producer, fetching
@rpc/<producer>/describe on first miss. None = the producer does
not serve describe or does not describe this type — render
structurally (never an error; RFC 08 §7 is a SHOULD for
self-describing encodings).
A bare &Session rather than a crate::Fleet: the store was
constructed with the base and composes the Fleet itself, so a
caller cannot hand it a second base for the two to disagree over.
Same for set_for and everything built on them.
Sourcepub async fn set_for(
&self,
session: &Session,
producer: &str,
) -> Option<Arc<SchemaSet>>
pub async fn set_for( &self, session: &Session, producer: &str, ) -> Option<Arc<SchemaSet>>
The producer’s whole served set, on the same fetch-and-cache path
as schema_for (issue #51: zenctl schema show <producer> dumps the inventory, and asking type-by-type would be a
different question than the one describe answers).
None = the producer does not serve describe — an honest
degradation, never an error.
Sourcepub fn forget(&self, producer: &str)
pub fn forget(&self, producer: &str)
Forget what we learned about one producer, so the next question goes to the bus (issue #101).
The queriers are kept: they are idle routing state, and re-declaring them is exactly the cost #37 removed.
Sourcepub fn forget_all(&self)
pub fn forget_all(&self)
Forget every producer — the “re-ask schemas” action a frontend offers.
Covers the case the backoff cannot: a positive entry never expires, so a producer that changes its served set mid-session is otherwise read with the schemas it had at first contact.
Sourcepub fn known(&self) -> Vec<(String, bool)>
pub fn known(&self) -> Vec<(String, bool)>
Producers currently answered-for, and whether each served a set — what a frontend shows next to its re-ask button.
Sourcepub fn decode(
&self,
schema: &TypeSchema,
encoding: &WireEncoding,
bytes: &[u8],
) -> Result<DecodedPayload, DecodeError>
pub fn decode( &self, schema: &TypeSchema, encoding: &WireEncoding, bytes: &[u8], ) -> Result<DecodedPayload, DecodeError>
Decode bytes under a schema, if one resolves.
Sourcepub fn encode(
&self,
schema: &TypeSchema,
value: &Value,
target: &WireEncoding,
) -> Result<Vec<u8>, DecodeError>
pub fn encode( &self, schema: &TypeSchema, value: &Value, target: &WireEncoding, ) -> Result<Vec<u8>, DecodeError>
The other direction (issue #97): a JSON value framed for the wire. The store owns the decoder table, so the write path resolves its codec exactly where the read path does — one registration, both directions.
Auto Trait Implementations§
impl !Freeze for SchemaStore
impl RefUnwindSafe for SchemaStore
impl Send for SchemaStore
impl Sync for SchemaStore
impl Unpin for SchemaStore
impl UnsafeUnpin for SchemaStore
impl UnwindSafe for SchemaStore
Blanket Implementations§
Source§impl<Source> AccessAs for Source
impl<Source> AccessAs for Source
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
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 more