pub struct ConcurrentTemporalHnsw<D: DistanceMetric> {
inner: RwLock<TemporalHnsw<D>>,
insert_queue: Mutex<Vec<PendingInsert>>,
}Expand description
Thread-safe spatiotemporal HNSW index with insert queue (RFC-002-04).
Uses a two-tier approach to reduce write lock contention:
- Inserts are queued into a
Mutex<Vec<...>>(sub-microsecond) flush_inserts()drains the queue under a single write lock- Searches always acquire a read lock (concurrent, unblocked during queue drain)
For immediate visibility, use insert() which still takes the write lock directly.
For high-throughput ingestion, use queue_insert() + flush_inserts().
Fields§
§inner: RwLock<TemporalHnsw<D>>§insert_queue: Mutex<Vec<PendingInsert>>Insert queue for batched commits (RFC-002-04, Option A).
Implementations§
Source§impl<D: DistanceMetric> ConcurrentTemporalHnsw<D>
impl<D: DistanceMetric> ConcurrentTemporalHnsw<D>
Sourcepub fn new(config: HnswConfig, metric: D) -> Self
pub fn new(config: HnswConfig, metric: D) -> Self
Create a new empty concurrent index.
Sourcepub fn insert(&self, entity_id: u64, timestamp: i64, vector: &[f32]) -> u32
pub fn insert(&self, entity_id: u64, timestamp: i64, vector: &[f32]) -> u32
Insert a temporal point (exclusive write lock).
Sourcepub fn search(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
) -> Vec<(u32, f32)>
pub fn search( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, ) -> Vec<(u32, f32)>
Search with temporal filtering (shared read lock).
Sourcepub fn trajectory(
&self,
entity_id: u64,
filter: TemporalFilter,
) -> Vec<(i64, u32)>
pub fn trajectory( &self, entity_id: u64, filter: TemporalFilter, ) -> Vec<(i64, u32)>
Retrieve trajectory for an entity (shared read lock).
Sourcepub fn compute_centroid(&self) -> Option<Vec<f32>>
pub fn compute_centroid(&self) -> Option<Vec<f32>>
Compute the centroid (mean vector) of all indexed vectors.
Sourcepub fn set_centroid(&self, centroid: Vec<f32>)
pub fn set_centroid(&self, centroid: Vec<f32>)
Set the centroid for anisotropy correction (write lock).
Sourcepub fn clear_centroid(&self)
pub fn clear_centroid(&self)
Clear the centroid (write lock).
Sourcepub fn centered_vector(&self, vec: &[f32]) -> Vec<f32>
pub fn centered_vector(&self, vec: &[f32]) -> Vec<f32>
Return a centered copy of the given vector (vec - centroid).
Sourcepub fn queue_insert(&self, entity_id: u64, timestamp: i64, vector: Vec<f32>)
pub fn queue_insert(&self, entity_id: u64, timestamp: i64, vector: Vec<f32>)
Queue an insert for batched processing (RFC-002-04).
This only takes a Mutex (sub-microsecond), NOT the write lock.
The insert becomes visible after flush_inserts() is called.
Sourcepub fn pending_inserts(&self) -> usize
pub fn pending_inserts(&self) -> usize
Number of pending inserts in the queue.
Sourcepub fn flush_inserts(&self) -> usize
pub fn flush_inserts(&self) -> usize
Flush all queued inserts, applying them under a single write lock.
Returns the number of inserts applied.
Trait Implementations§
Source§impl<D: DistanceMetric> IndexBackend for ConcurrentTemporalHnsw<D>
impl<D: DistanceMetric> IndexBackend for ConcurrentTemporalHnsw<D>
Source§fn insert(
&self,
entity_id: u64,
vector: &[f32],
timestamp: i64,
) -> Result<u32, IndexError>
fn insert( &self, entity_id: u64, vector: &[f32], timestamp: i64, ) -> Result<u32, IndexError>
Source§fn search(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
) -> Result<Vec<ScoredResult>, QueryError>
fn search( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, ) -> Result<Vec<ScoredResult>, QueryError>
Source§impl<D: DistanceMetric> TemporalIndexAccess for ConcurrentTemporalHnsw<D>
impl<D: DistanceMetric> TemporalIndexAccess for ConcurrentTemporalHnsw<D>
Source§fn search_raw(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
) -> Vec<(u32, f32)>
fn search_raw( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, ) -> Vec<(u32, f32)>
Source§fn trajectory(&self, entity_id: u64, filter: TemporalFilter) -> Vec<(i64, u32)>
fn trajectory(&self, entity_id: u64, filter: TemporalFilter) -> Vec<(i64, u32)>
Source§fn vector(&self, node_id: u32) -> Vec<f32>
fn vector(&self, node_id: u32) -> Vec<f32>
Source§fn regions(&self, level: usize) -> Vec<(u32, Vec<f32>, usize)>
fn regions(&self, level: usize) -> Vec<(u32, Vec<f32>, usize)>
(hub_node_id, hub_vector, n_assigned) per region.Source§fn region_members(
&self,
region_hub: u32,
level: usize,
filter: TemporalFilter,
) -> Vec<(u32, u64, i64)>
fn region_members( &self, region_hub: u32, level: usize, filter: TemporalFilter, ) -> Vec<(u32, u64, i64)>
(node_id, entity_id, timestamp) per member.Source§fn region_assignments(
&self,
level: usize,
filter: TemporalFilter,
) -> HashMap<u32, Vec<(u64, i64)>>
fn region_assignments( &self, level: usize, filter: TemporalFilter, ) -> HashMap<u32, Vec<(u64, i64)>>
Source§fn region_trajectory(
&self,
entity_id: u64,
level: usize,
window_days: i64,
alpha: f32,
) -> Vec<(i64, Vec<f32>)>
fn region_trajectory( &self, entity_id: u64, level: usize, window_days: i64, alpha: f32, ) -> Vec<(i64, Vec<f32>)>
Source§fn metadata(&self, _node_id: u32) -> HashMap<String, String>
fn metadata(&self, _node_id: u32) -> HashMap<String, String>
Source§fn search_with_metadata(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
metadata_filter: &MetadataFilter,
) -> Vec<(u32, f32)>
fn search_with_metadata( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, metadata_filter: &MetadataFilter, ) -> Vec<(u32, f32)>
Auto Trait Implementations§
impl<D> !Freeze for ConcurrentTemporalHnsw<D>
impl<D> !RefUnwindSafe for ConcurrentTemporalHnsw<D>
impl<D> Send for ConcurrentTemporalHnsw<D>
impl<D> Sync for ConcurrentTemporalHnsw<D>
impl<D> Unpin for ConcurrentTemporalHnsw<D>where
D: Unpin,
impl<D> UnwindSafe for ConcurrentTemporalHnsw<D>where
D: UnwindSafe,
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> 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 more