pub struct ConcurrentEdgeStore { /* private fields */ }Expand description
A thread-safe edge store using sharded locking.
Distributes edges across multiple shards based on source node ID to reduce lock contention in multi-threaded scenarios.
§Cross-Shard Edge Storage Pattern
Edges that span different shards (source and target in different shards) are stored in BOTH shards:
- Source shard: Full edge with outgoing + label indices (
add_edge) - Target shard: Edge copy with incoming index only (
add_edge_incoming_only)
§Lock Ordering
When acquiring multiple shard locks, always acquire in ascending shard index order to prevent deadlocks.
Implementations§
Source§impl ConcurrentEdgeStore
impl ConcurrentEdgeStore
Sourcepub fn get_outgoing(&self, node_id: u64) -> Vec<GraphEdge>
pub fn get_outgoing(&self, node_id: u64) -> Vec<GraphEdge>
Gets all outgoing edges from a node (thread-safe).
Sourcepub fn get_incoming(&self, node_id: u64) -> Vec<GraphEdge>
pub fn get_incoming(&self, node_id: u64) -> Vec<GraphEdge>
Gets all incoming edges to a node (thread-safe).
Sourcepub fn get_neighbors(&self, node_id: u64) -> Vec<u64>
pub fn get_neighbors(&self, node_id: u64) -> Vec<u64>
Gets neighbors (target nodes) of a given node.
Sourcepub fn get_outgoing_by_label(&self, node_id: u64, label: &str) -> Vec<GraphEdge>
pub fn get_outgoing_by_label(&self, node_id: u64, label: &str) -> Vec<GraphEdge>
Gets outgoing edges filtered by label (thread-safe).
§Performance Note
This method delegates to the underlying EdgeStore::get_outgoing_by_label
which uses the composite index (source_id, label) -> edge_ids for O(1) lookup
when available (EPIC-019 US-003). Falls back to filtering if index not populated.
Sourcepub fn get_incoming_by_label(&self, node_id: u64, label: &str) -> Vec<GraphEdge>
pub fn get_incoming_by_label(&self, node_id: u64, label: &str) -> Vec<GraphEdge>
Gets incoming edges filtered by label (thread-safe).
Sourcepub fn get_edges_by_label(&self, label: &str) -> Vec<GraphEdge>
pub fn get_edges_by_label(&self, label: &str) -> Vec<GraphEdge>
Gets all edges with a specific label across all shards.
§Performance Warning
This method iterates through ALL shards and aggregates results.
For large graphs with many shards, this can be expensive.
Consider using get_outgoing_by_label(node_id, label) if you know
the source node, which is O(k) instead of O(shards × edges_per_label).
Sourcepub fn contains_edge(&self, edge_id: u64) -> bool
pub fn contains_edge(&self, edge_id: u64) -> bool
Checks if an edge with the given ID exists.
Sourcepub fn get_edge(&self, edge_id: u64) -> Option<GraphEdge>
pub fn get_edge(&self, edge_id: u64) -> Option<GraphEdge>
Gets an edge by ID using optimized source shard lookup.
Returns None if the edge doesn’t exist.
Sourcepub fn traverse_bfs(&self, start: u64, max_depth: u32) -> Vec<u64>
pub fn traverse_bfs(&self, start: u64, max_depth: u32) -> Vec<u64>
Traverses the graph using BFS from a starting node.
Returns all nodes reachable within max_depth hops.
Uses Read-Copy-Drop pattern to avoid holding locks during traversal.
Sourcepub fn edge_count(&self) -> usize
pub fn edge_count(&self) -> usize
Returns the total edge count across all shards.
Uses outgoing edge count to avoid double-counting edges that span shards.
Source§impl ConcurrentEdgeStore
impl ConcurrentEdgeStore
Sourcepub fn with_shards(num_shards: usize) -> Self
pub fn with_shards(num_shards: usize) -> Self
Creates a new concurrent edge store with a specific number of shards.
§Panics
Panics if num_shards is 0 (would cause division-by-zero in shard_index).
Sourcepub fn with_estimated_edges(estimated_edges: usize) -> Self
pub fn with_estimated_edges(estimated_edges: usize) -> Self
Creates a concurrent edge store with optimal shard count for estimated edge count.
FLAG-6: Uses integer bit manipulation for ceiling log2.
Sourcepub fn add_edge(&self, edge: GraphEdge) -> Result<()>
pub fn add_edge(&self, edge: GraphEdge) -> Result<()>
Adds an edge to the store (thread-safe).
Edges are stored in BOTH source and target shards:
- Source shard: for outgoing index lookups
- Target shard: for incoming index lookups
When source and target are in different shards, locks are acquired in ascending shard index order to prevent deadlocks.
§Errors
Returns Error::EdgeExists if an edge with the same ID already exists.
Sourcepub fn remove_edge(&self, edge_id: u64)
pub fn remove_edge(&self, edge_id: u64)
Removes an edge by ID using optimized 2-shard lookup.
§Concurrency Safety
Lock ordering: edge_ids FIRST, then shards in ascending order.
Sourcepub fn remove_node_edges(&self, node_id: u64)
pub fn remove_node_edges(&self, node_id: u64)
Removes all edges connected to a node (cascade delete, thread-safe).
§Concurrency Safety
Lock ordering: edge_ids FIRST, then shards in ascending order.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for ConcurrentEdgeStore
impl !RefUnwindSafe for ConcurrentEdgeStore
impl Send for ConcurrentEdgeStore
impl Sync for ConcurrentEdgeStore
impl Unpin for ConcurrentEdgeStore
impl UnsafeUnpin for ConcurrentEdgeStore
impl UnwindSafe for ConcurrentEdgeStore
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>
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);