pub struct DeferredIndexer { /* private fields */ }Expand description
Buffers vectors for deferred HNSW insertion with brute-force searchability.
See the module-level docs for design details.
Implementations§
Source§impl DeferredIndexer
impl DeferredIndexer
Sourcepub fn new(config: DeferredIndexerConfig) -> Self
pub fn new(config: DeferredIndexerConfig) -> Self
Creates a new DeferredIndexer with the given configuration.
The buffer starts inactive. If config.enabled is false, all
write operations are no-ops.
Sourcepub fn is_enabled(&self) -> bool
pub fn is_enabled(&self) -> bool
Whether deferred indexing is enabled.
Sourcepub fn push(&self, id: u64, vector: Vec<f32>) -> bool
pub fn push(&self, id: u64, vector: Vec<f32>) -> bool
Pushes a vector into the write buffer.
Activates the buffer lazily on first write. Returns true if
the buffer has reached merge_threshold, signaling the caller
to trigger a merge.
No-op if deferred indexing is disabled.
§TOCTOU note
The enabled check and len() >= threshold read are not atomic with
the push. This is benign: a concurrent drain may reset the count
between push and the threshold check, causing a missed merge signal.
The next push will re-trigger.
A previous TOCTOU window existed where swap_and_drain could
deactivate the buffer between ensure_buffer_active and the
underlying buffer.push, causing the vector to be silently dropped.
This is fixed: swap_and_drain now re-activates the buffer after
draining so pushes between drain and the next merge succeed.
Sourcepub fn extend(&self, entries: impl IntoIterator<Item = (u64, Vec<f32>)>) -> bool
pub fn extend(&self, entries: impl IntoIterator<Item = (u64, Vec<f32>)>) -> bool
Batch-pushes vectors into the write buffer.
Returns true if the buffer has reached merge_threshold.
No-op if deferred indexing is disabled.
Sourcepub fn remove(&self, id: u64)
pub fn remove(&self, id: u64)
Marks id as deleted, removing it from the buffer.
The ID is added to deleted_ids so that search results are filtered
even if the vector was already snapshot for a concurrent search.
Sourcepub fn search(
&self,
query: &[f32],
k: usize,
metric: DistanceMetric,
) -> Vec<(u64, f32)>
pub fn search( &self, query: &[f32], k: usize, metric: DistanceMetric, ) -> Vec<(u64, f32)>
Brute-force searches the buffer, filtering deleted IDs.
Results are sorted by the metric ordering and truncated to k.
To compensate for post-filter attrition, the buffer is queried with
k + deleted_ids.len() candidates. This is bounded: deleted_ids
never exceeds merge_threshold entries (cleared on every drain).
§TOCTOU note
The deleted_ids snapshot is read under a separate lock from the
buffer search. A concurrent delete between the buffer snapshot and the
deleted_ids read is benign: the ID will be filtered on the next
search after the delete completes.
Sourcepub fn merge_with_hnsw(
&self,
hnsw_results: Vec<(u64, f32)>,
query: &[f32],
k: usize,
metric: DistanceMetric,
) -> Vec<(u64, f32)>
pub fn merge_with_hnsw( &self, hnsw_results: Vec<(u64, f32)>, query: &[f32], k: usize, metric: DistanceMetric, ) -> Vec<(u64, f32)>
Merges HNSW results with deferred buffer results.
Buffer is authoritative on duplicate IDs (more recent data): when a
point is upserted while deferred indexing is active, the new vector
goes to the buffer while HNSW still holds the stale vector. On ID
conflict the buffer score is kept, mirroring merge_with_delta in
delta.rs.
Deleted IDs are filtered from buffer results but not from HNSW results (HNSW has its own tombstone system).
Sourcepub fn swap_and_drain(&self) -> Vec<(u64, Vec<f32>)>
pub fn swap_and_drain(&self) -> Vec<(u64, Vec<f32>)>
Drains the buffer and returns vectors for HNSW insertion.
After this call the buffer is empty but re-activated so that
pushes arriving between drain and the next merge are not silently
dropped. The deleted_ids set is cleared because the caller is
expected to apply deletions to HNSW after merge.
Serialized by an internal mutex so concurrent calls are safe (the second caller gets an empty drain).
Sourcepub fn pending_count(&self) -> usize
pub fn pending_count(&self) -> usize
Total number of pending (not yet indexed) vectors in the buffer.
Sourcepub fn should_merge(&self) -> bool
pub fn should_merge(&self) -> bool
Returns true if the buffer has reached merge_threshold.
Sourcepub fn is_searchable(&self) -> bool
pub fn is_searchable(&self) -> bool
Returns true if deferred indexing is enabled and the buffer has
searchable data.
Auto Trait Implementations§
impl !Freeze for DeferredIndexer
impl !RefUnwindSafe for DeferredIndexer
impl Send for DeferredIndexer
impl Sync for DeferredIndexer
impl Unpin for DeferredIndexer
impl UnsafeUnpin for DeferredIndexer
impl !UnwindSafe for DeferredIndexer
Blanket Implementations§
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
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 moreSource§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);