Skip to main content

BodyRenderer

Struct BodyRenderer 

Source
pub struct BodyRenderer(/* private fields */);
Expand description

The path from a stored content_html row to a BodyRender, with the three bounds. One process-wide instance, BodyRenderer::shared, serves the reader; tests build their own with smaller parameters.

For a body of n bytes a render costs, in order:

  1. nothing but a length check if n > MAX_RENDER_HTML_BYTES (BodyRender::TooLarge);
  2. a SHA-256 of the body and a cache lookup, on the blocking pool;
  3. on a miss, single flight: if the same body is already being cleaned, this request waits for that result and takes no permit; otherwise it becomes the leader and spawns the clean as its own task, so a requester that disconnects neither cancels the clean nor leaves anyone waiting on a leader that is gone;
  4. the leader waits up to RENDER_WAIT for one of RENDER_PERMITS permits (BodyRender::Unavailable for everyone waiting if none comes), then cleans on the blocking pool holding the permit, caches the result and publishes it.

So each distinct body is cleaned at most once at a time; a fast body again only after it leaves the cache; and a body that was slow to clean (SLOW_CLEAN, 500 ms) at most once per process — after its result leaves the cache it renders as BodyRender::TooSlow instead (SlowSet). A slow body therefore costs one clean, holding one permit, per process. The async worker is never blocked: the hash, the lookup and the clean run on the blocking pool, and every wait is an async one.

What these bounds are for. A stored body may be slow to re-clean: ingest can store one (#226; real bodies p50 31 µs, max 3.5 ms, but a hostile feed’s 2 MiB of nested <div>s re-cleans in ~37 s, a & run in 2.4 s), and such rows may already exist in databases upgraded from ≤ 0.4.6. The bounds here cap what such a row can cost other readers: it is cleaned once per process, holding one of two permits, and everyone else’s uncached body waits at most RENDER_WAIT before a note. They do not predict or reduce its own cost.

Implementations§

Source§

impl BodyRenderer

Source

pub fn new( permits: usize, wait: Duration, cache_bytes: usize, cache_entries: usize, ) -> Self

A renderer with its own permits and cache. The reader uses BodyRenderer::shared; this is for tests and for the shared instance’s construction.

Source

pub fn shared() -> &'static BodyRenderer

The process-wide renderer, with RENDER_PERMITS, RENDER_WAIT, CACHE_MAX_BYTES and CACHE_MAX_ENTRIES.

Source

pub async fn render(&self, raw: String) -> Result<BodyRender>

A stored body, cleaned for this render — or the reason it is not.

Err only if the blocking pool failed to run the task (a panic in the sanitizer, or runtime shutdown); the two bounded outcomes are values.

Source

pub fn cleans(&self) -> usize

How many times this renderer has run the sanitizer.

Source

pub fn in_flight(&self) -> usize

How many bodies are being cleaned right now.

Source

pub fn cache_size(&self) -> (usize, usize)

Bodies in the cache, and the bytes of cleaned markup they hold.

Trait Implementations§

Source§

impl Clone for BodyRenderer

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§

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

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

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

Source§

fn from_ref(input: &T) -> T

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

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

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

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. 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> 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