Skip to main content

SortedViewCache

Struct SortedViewCache 

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

Sorted view cache maintaining entities in sort order.

§Bounding

The cache holds every entity it has been given. It shares an entity’s fields with whoever gave it (see SharedEntity) rather than copying them, but it keeps them alive, so callers that feed it from a bounded source (the projector and snapshot restore feed it from the LRU-capped EntityCache) should use upsert_bounded or trim_to_max_entries with that source’s cap.

Entries are evicted from the bottom of the sort order, not by recency. Evicting the least-recently-updated entries (mirroring the entity cache) would drop a top-ranked entity that simply has not updated recently and break leaderboard-style sort + take views. Evicting everything beyond position max_entries keeps every window with skip + take <= max_entries exact. An evicted entity re-enters on its next update, because the projector re-reads the full entity from the entity cache before upserting.

Known edge: after entities are removed from (or move down out of) the top of the order, a previously evicted entity that has not updated since is missing from the cache until it next updates, so a window near the cap can under-fill or show a lower-ranked entity in its place until then.

Implementations§

Source§

impl SortedViewCache

Source

pub fn new(view_id: String, sort_field: Vec<String>, order: SortOrder) -> Self

Source

pub fn view_id(&self) -> &str

Source

pub fn len(&self) -> usize

Source

pub fn is_empty(&self) -> bool

Source

pub fn upsert( &mut self, entity_key: String, entity: impl Into<SharedEntity>, ) -> UpsertResult

Insert or update an entity, returns the position where it was inserted

An update merges into the entity held, keeping fields the update lacks. When it lacks none, which is the case for a whole entity, the cache shares the update’s fields instead of copying them.

Finding the position walks the order up to it; Self::put does the same upsert without it.

Source

pub fn put(&mut self, entity_key: String, entity: impl Into<SharedEntity>)

Self::upsert without reporting where the entity landed.

Source

pub fn would_keep<E: EntityFields + ?Sized>( &self, entity_key: &str, entity: &E, max_entries: usize, ) -> bool

Whether upserting entity under entity_key into a cache bounded at max_entries would keep it: the cache already holds the key, has room, or the entity sorts before its current last entry.

Lets a caller skip copying an entity that Self::upsert_bounded would evict straight away, which in a busy view is most of them.

Source

pub fn upsert_bounded( &mut self, entity_key: String, entity: impl Into<SharedEntity>, max_entries: usize, ) -> UpsertResult

Upsert an entity, then evict from the bottom of the sort order so the cache holds at most max_entries entities.

If the upserted entity itself sorts beyond max_entries it is evicted immediately and the returned position is >= max_entries.

Source

pub fn upsert_if_kept( &mut self, entity_key: &str, entity: &SharedEntity, max_entries: usize, ) -> bool

Self::upsert_bounded for an entity Self::would_keep keeps, without reporting its position: the cache ends up as it would after would_keep and upsert_bounded, reading the entity’s sort value once and sharing (cloning) the entity only if the cache keeps it. Returns whether it does.

Source

pub fn trim_to_max_entries(&mut self, max_entries: usize) -> usize

Evict entities from the bottom of the sort order until at most max_entries remain. Returns the number of evicted entities.

Each eviction is an O(log n) pop from the end of the ordered index, so a batch of evictions (e.g. after a bulk rebuild) costs no more than the inserts that caused it. The ordered-keys cache is truncated in place when it is current, so trimming does not force a full rebuild.

Source

pub fn clear(&mut self)

Remove an entity, returns the position it was at

Source

pub fn remove(&mut self, entity_key: &str) -> Option<usize>

Finding the position walks the order up to it; Self::remove_key removes without it.

Source

pub fn remove_key(&mut self, entity_key: &str) -> bool

Remove an entity, returning whether the cache held it.

Source

pub fn get(&self, entity_key: &str) -> Option<&SharedEntity>

Get entity by key

Source

pub fn ordered_keys(&mut self) -> &[String]

Get ordered keys (rebuilds cache if dirty)

The other readers walk the order itself, so only this one pays for copying every key after a change.

Source

pub fn get_window(&mut self, skip: usize, take: usize) -> Vec<(String, Value)>

Get a window of entities, as copies.

Source

pub fn iter_ordered(&self) -> impl Iterator<Item = (&str, &SharedEntity)> + '_

Every entity in sort order, borrowed: a window read walks only as far as it reads, skip included.

Source

pub fn get_all_ordered(&mut self) -> Vec<(String, Value)>

Copies of every entity in deterministic sort order.

Source

pub fn ordered_entities(&mut self) -> Vec<(String, SharedEntity)>

Every entity in deterministic sort order for query-side filtering, sharing their fields with the cache rather than copying them.

Source

pub fn compute_window_deltas( &mut self, old_window_keys: &[String], skip: usize, take: usize, ) -> Vec<ViewDelta>

Compute deltas for a client with a specific window

Trait Implementations§

Source§

impl Debug for SortedViewCache

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> 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> 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, 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