Skip to main content

Ingest

Struct Ingest 

Source
pub struct Ingest<R> {
    pub(crate) tx: Arc<[Sender<Job<R>>]>,
    pub(crate) turn: Arc<AtomicU64>,
    pub(crate) rejects: &'static Rejects,
    pub(crate) wal: Option<Arc<Wal>>,
    pub(crate) signal: Signal,
}
Expand description

The write handle for one signal. R is that signal’s OTLP export request.

Fields§

§tx: Arc<[Sender<Job<R>>]>§turn: Arc<AtomicU64>

Where the next export that cannot go to shard 0 starts looking. Shared across clones, because the point of it is to spread waiters over shards rather than over handles.

§rejects: &'static Rejects§wal: Option<Arc<Wal>>§signal: Signal

Implementations§

Source§

impl<R> Ingest<R>

Source

fn reserve(&self) -> Option<Permit<'_, Job<R>>>

A slot in the first shard that has one, or None if every shard is full or gone.

First fit from shard 0 rather than round-robin, and that is the whole sharding policy. Round-robin spreads a trickle of exports over every shard, and since each shard owns its own open block, a node doing two exports a second would publish shards nearly-empty blocks every max_block_age instead of one — the small-file explosion section 4 rejects hash sharding for, arrived at from the other direction. First fit keeps a node that is not saturating one flusher behaving exactly as it did with one, and starts using the second shard at the moment the first one’s queue stops draining, which is the moment the consumer’s service time became the curve.

Ordering across shards is not preserved and does not need to be: two exports are two OTLP requests, the spec orders neither against the other, and block timestamps come from the data. Ordering within a shard still is, which is what the carry rule in flusher needs.

Source§

impl<R: Message> Ingest<R>

Source

pub async fn submit(&self, req: R) -> Result<(), Rejected>

Enqueue and wait for durability.

What “durable” means here is the one thing Config::wal decides. Without a log this returns once the block containing the request has been fsynced and renamed into place, which is correct and costs a whole max_block_age at the tail. With one it returns once the request is a frame in the log’s page cache, which is section 11’s 2.6 s p99 turned into microseconds and is why the log exists.

Source§

impl<R: Message + Default> Ingest<R>

Source

pub fn replay(&self, body: &[u8], seq: u64) -> Result<(), Rejected>

Push one frame recovered from the log back into this signal’s flusher, under the sequence it already has.

Not submit: the frame is in the log already, so re-appending it would number it above every watermark and the block storing it would claim the copy instead of the original — which replays again on the next boot, and the one after that. Nothing waits for the ack either; the client that sent this got its answer before the crash, or gave up long ago.

Blocking, and deliberately: this is called from a spawn_blocking hop at boot, and the bounded channel is the only thing keeping a multi- gigabyte log from being decoded into memory faster than it can be sealed. The two failures are worth telling apart: Rejected::Failed is one frame that will never decode, which is a line in the log and the next frame; Rejected::Closed is the flusher being gone, which means the rest of the replay would go nowhere.

Trait Implementations§

Source§

impl<R> Clone for Ingest<R>

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

Auto Trait Implementations§

§

impl<R> Freeze for Ingest<R>

§

impl<R> RefUnwindSafe for Ingest<R>

§

impl<R> Send for Ingest<R>
where R: Send,

§

impl<R> Sync for Ingest<R>
where R: Send,

§

impl<R> Unpin for Ingest<R>

§

impl<R> UnsafeUnpin for Ingest<R>

§

impl<R> UnwindSafe for Ingest<R>

Blanket Implementations§

§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,

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
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

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

§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

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.

§

impl<T> IntoRequest<T> for T

§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
§

impl<L> LayerExt<L> for L

§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in [Layered].
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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 = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more