Skip to main content

SchemaPrefetch

Struct SchemaPrefetch 

Source
pub struct SchemaPrefetch { /* private fields */ }
Expand description

The async half of a registry-backed codec: it resolves, on the broker’s async edges, every schema the synchronous codec will read.

A Codec is synchronous on both ends and a registry lookup is not, and no amount of arranging makes those meet inside encode or decode: blocking a runtime worker from a sync function is not an option and guessing a schema is corruption. So the lookups move to the two places that are already async and already know when they have to happen - the broker’s connect, for the subjects a codec publishes under, and each subscription’s delivery path, for the writer schema an arriving envelope names. By the time a codec runs, what it needs is in the shared cache, and its own work is pure computation.

This is a distinct attachment from KafkaBroker::schema_registry on purpose. That one rewrites deliveries into JSON, which is the transcoding compatibility path; this one leaves every payload exactly as it arrived and only fills a cache. Attaching both to one broker is contradictory - the transcode would hand a JSON document to a codec expecting the Confluent wire format - and the prefetch runs first so it still sees the envelope.

§Examples

use apache_avro::AvroSchema;
use ruststream_rdkafka::avro::AvroCodec;
use ruststream_rdkafka::prelude::*;
use ruststream_rdkafka::{SchemaPrefetch, SchemaRegistry};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, AvroSchema)]
struct Order {
    id: i64,
}

#[derive(Serialize, AvroSchema, Outgoing)]
#[outgoing(name = "shipments")]
struct Shipment {
    order_id: i64,
}

#[subscriber("orders", reply)]
async fn ship(order: &Order) -> Shipment {
    Shipment { order_id: order.id }
}

fn app() -> RustStream {
    let prefetch = SchemaPrefetch::new(SchemaRegistry::new("http://localhost:8081"));
    // Every type a codec registers records its subject here, so `connect` resolves it and a
    // subject that is missing is settled by the prefetch's policy rather than at first publish.
    let codec = AvroCodec::registry(&prefetch).register::<Shipment>("shipments-value");
    let broker = KafkaBroker::new(["localhost:9092"])
        .default_group("shipping-svc")
        .schema_prefetch(prefetch);
    // The scope's codec decodes every delivery; the reply names it again, at its own position.
    let replies = codec.clone();
    RustStream::new(AppInfo::new("shipping", "0.1.0")).with_broker_codec(broker, codec, |b| {
        b.include(ship).out_reply(Publish::default()).codec(replies);
    })
}

Implementations§

Source§

impl SchemaPrefetch

Source

pub fn new(registry: SchemaRegistry) -> Self

Builds the prefetch over registry. Construction is synchronous and does no I/O; the resolving happens on the broker’s async edges.

Source

pub fn check_compatibility(self, check: bool) -> Self

Whether connect checks each registered type’s schema the way registering it would be checked, and refuses to start when the registry says they are incompatible.

The subject’s compatibility level decides the versions the schema is held against: the latest one for BACKWARD, FORWARD and FULL, every version for their _TRANSITIVE forms. A schema this check passes is one the registry would accept.

It stands where Confluent’s latest.compatibility.strict does, and is on for the same reason it is on by default there: a model that has drifted from its subject is a fact worth learning while the app is starting rather than from a consumer that cannot read what it wrote. The registry’s own account of what differs, down to the field, travels in the error.

Turn it off for a registry whose compatibility level is deliberately NONE, or a client that cannot answer the question - a RegistryClient that does not implement is_compatible skips it regardless.

Source

pub fn on_missing_subject(self, policy: MissingSubject) -> Self

What to do about a registered subject the registry does not hold; see MissingSubject. Defaults to Refuse.

Configure before building codecs from it: each copies the policy as it is built.

Source

pub fn registry(&self) -> &SchemaRegistry

The client the codecs share a cache with.

Trait Implementations§

Source§

impl Clone for SchemaPrefetch

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SchemaPrefetch

Source§

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

Formats the value using the given formatter. 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> ErasedDestructor for T
where T: 'static,

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> PublishedThrough<DefaultSlot> for T

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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<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