LazyGraphManager

Struct LazyGraphManager 

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

The lazy-loading graph manager

Manages partitioned code graphs stored in SQLite, loading them on-demand into a petgraph-based in-memory representation.

Uses interior mutability via RwLock<PetCodeGraph> to enable concurrent read access to the graph while maintaining thread safety for writes.

Implementations§

Source§

impl LazyGraphManager

Source

pub fn new(prism_dir: &Path) -> Self

Create a new lazy graph manager with default memory budget (512 MB)

§Arguments
  • prism_dir - The .codeprysm directory path
Source

pub fn with_memory_budget( prism_dir: &Path, memory_budget_bytes: Option<usize>, ) -> Self

Create a new lazy graph manager with a custom memory budget

§Arguments
  • prism_dir - The .codeprysm directory path
  • memory_budget_bytes - Optional memory budget in bytes (default: 512 MB)
Source

pub fn open(prism_dir: &Path) -> Result<Self, LazyGraphError>

Open an existing lazy graph from a .codeprysm directory

Loads the manifest but does not load any partitions yet.

Source

pub fn open_with_memory_budget( prism_dir: &Path, memory_budget_bytes: Option<usize>, ) -> Result<Self, LazyGraphError>

Open an existing lazy graph with a custom memory budget

Source

pub fn init(prism_dir: &Path) -> Result<Self, LazyGraphError>

Initialize a new lazy graph with an empty manifest

Creates the partitions directory if it doesn’t exist.

Source

pub fn init_with_memory_budget( prism_dir: &Path, memory_budget_bytes: Option<usize>, ) -> Result<Self, LazyGraphError>

Initialize a new lazy graph with a custom memory budget

Source

pub fn init_workspace( workspace_path: &Path, prism_dir: &Path, ) -> Result<Self, LazyGraphError>

Initialize a lazy graph by discovering roots in a workspace

Uses RootDiscovery to find git repositories and code directories, then registers them in the manifest for multi-root support.

§Arguments
  • workspace_path - The workspace root to discover roots in
  • prism_dir - The .codeprysm directory for storage
§Examples
use codeprysm_core::lazy::manager::LazyGraphManager;
use std::path::Path;

// Single repo workspace
let manager = LazyGraphManager::init_workspace(
    Path::new("/path/to/repo"),
    Path::new("/path/to/repo/.codeprysm"),
).unwrap();

// Multi-root workspace
let manager = LazyGraphManager::init_workspace(
    Path::new("/path/to/workspace"),
    Path::new("/path/to/workspace/.codeprysm"),
).unwrap();
Source

pub fn init_workspace_with_options( workspace_path: &Path, prism_dir: &Path, memory_budget_bytes: Option<usize>, max_discovery_depth: Option<usize>, ) -> Result<Self, LazyGraphError>

Initialize a lazy graph with custom options

§Arguments
  • workspace_path - The workspace root to discover roots in
  • prism_dir - The .codeprysm directory for storage
  • memory_budget_bytes - Optional memory budget (default: 512 MB)
  • max_discovery_depth - Optional max depth for root discovery (default: 3)
Source

pub fn roots(&self) -> impl Iterator<Item = &RootInfo>

Get the discovered roots from the manifest

Source

pub fn is_multi_root(&self) -> bool

Check if this is a multi-root workspace

Source

pub fn manifest(&self) -> &Manifest

Get the manifest

Source

pub fn manifest_mut(&mut self) -> &mut Manifest

Get mutable access to the manifest

Source

pub fn reload_manifest(&mut self) -> Result<(), LazyGraphError>

Reload manifest from disk

Source

pub fn save_manifest(&self) -> Result<(), LazyGraphError>

Save manifest to disk

Source

pub fn get_partition_for_file(&self, file: &str) -> Option<&str>

Get the partition ID for a file path

Source

pub fn get_partition_for_node(&self, node_id: &str) -> Option<String>

Get the partition ID for a node by looking at its file path

Returns owned String since registry uses interior mutability (DashMap).

Source

pub fn compute_partition_id(file: &str) -> String

👎Deprecated: Use compute_partition_id_for_root for multi-root support

Compute the partition ID for a file path (directory-based partitioning)

For multi-root workspaces, use compute_partition_id_for_root instead. Returns the parent directory path as the partition ID.

Source

pub fn compute_partition_id_for_root(root_name: &str, file: &str) -> String

Compute partition ID for a file in a specific root (multi-root support)

Returns partition ID in format {root_name}_{directory} to avoid collisions between roots with similar directory structures.

§Examples
use codeprysm_core::lazy::manager::LazyGraphManager;

let pid = LazyGraphManager::compute_partition_id_for_root("repo-a", "src/core/main.py");
assert_eq!(pid, "repo-a_src/core");

let pid = LazyGraphManager::compute_partition_id_for_root("repo-b", "src/core/main.py");
assert_eq!(pid, "repo-b_src/core");

// Root-level files use "{root}_root" partition
let pid = LazyGraphManager::compute_partition_id_for_root("myrepo", "main.py");
assert_eq!(pid, "myrepo_root");
Source

pub fn is_partition_loaded(&self, partition_id: &str) -> bool

Check if a partition is currently loaded

Source

pub fn loaded_partition_count(&self) -> usize

Get the number of loaded partitions

Source

pub fn loaded_partitions(&self) -> Vec<String>

Get the list of loaded partition IDs

Source

pub fn partition_ids(&self) -> Vec<String>

Get all partition IDs from manifest (whether loaded or not)

Source

pub fn node_ids_in_partition(&self, partition_id: &str) -> Option<Vec<String>>

Get node IDs that belong to a specific loaded partition

Returns None if the partition is not currently loaded. Use this after load_partition() to get the nodes for indexing.

Source

pub fn load_partition(&self, partition_id: &str) -> Result<(), LazyGraphError>

Load a partition from SQLite into the petgraph

Uses double-checked locking to prevent duplicate concurrent loads of the same partition while allowing concurrent loads of different partitions.

If the partition is already loaded, this is a no-op (cache hit). If memory budget is exceeded, evicts least-recently-used partitions first.

Source

pub fn ensure_partition_loaded( &self, partition_id: &str, ) -> Result<(), LazyGraphError>

Ensure a partition is loaded (load if not already loaded)

Source

pub fn load_all_partitions(&self) -> Result<usize, LazyGraphError>

Load all partitions into memory

This is useful when you need access to the entire graph, such as for full reindexing. Note that this bypasses the memory budget and may use significant memory for large repositories.

Returns the number of partitions loaded.

Source

pub fn unload_partition(&self, partition_id: &str) -> usize

Unload a partition from petgraph to free memory

Removes all nodes and edges belonging to this partition. Returns the number of nodes unloaded.

Thread-safe: Uses interior mutability via DashMap (registry), Mutex (cache), and RwLock (graph).

Source

pub fn get_node(&self, id: &str) -> Result<Option<Node>, LazyGraphError>

Get a node by ID, loading its partition if necessary

Returns an owned clone of the node for thread safety. This enables concurrent read access without holding locks across call boundaries.

Source

pub fn get_node_if_loaded(&self, id: &str) -> Option<Node>

Get a node by ID without loading (only returns if already loaded)

Returns an owned clone of the node for thread safety.

Source

pub fn contains_node(&self, id: &str) -> Result<bool, LazyGraphError>

Check if a node exists (may require loading partition)

Source

pub fn contains_node_if_loaded(&self, id: &str) -> bool

Check if a node exists in the currently loaded graph (no lazy loading)

Source

pub fn get_incoming_edges( &self, node_id: &str, ) -> Result<Vec<(Node, EdgeData)>, LazyGraphError>

Get incoming edges for a node, loading its partition if necessary

This includes both intra-partition edges (from petgraph) and cross-partition edges (from CrossRefIndex). Cross-partition source nodes are loaded as needed.

Source

pub fn get_outgoing_edges( &self, node_id: &str, ) -> Result<Vec<(Node, EdgeData)>, LazyGraphError>

Get outgoing edges from a node, loading its partition if necessary

This includes both intra-partition edges (from petgraph) and cross-partition edges (from CrossRefIndex). Cross-partition target nodes are loaded as needed.

Source

pub fn add_cross_ref(&mut self, cross_ref: CrossRef)

Add a cross-partition edge reference

Use this when an edge spans two different partitions.

Source

pub fn add_cross_refs(&mut self, refs: impl IntoIterator<Item = CrossRef>)

Add multiple cross-partition edge references

Source

pub fn get_cross_refs_by_target( &self, target_id: &str, ) -> Option<&Vec<CrossRef>>

Get cross-partition edges targeting a specific node

Source

pub fn get_cross_refs_by_source( &self, source_id: &str, ) -> Option<&Vec<CrossRef>>

Get cross-partition edges from a specific source node

Source

pub fn remove_cross_refs_by_partition(&mut self, partition: &str)

Remove all cross-partition edges involving a specific partition

Call this when a partition is being rebuilt.

Source

pub fn cross_ref_count(&self) -> usize

Get the number of cross-partition edges

Source

pub fn save_cross_refs(&self) -> Result<(), LazyGraphError>

Save cross-partition edges to SQLite

Source

pub fn reload_cross_refs(&mut self) -> Result<(), LazyGraphError>

Reload cross-partition edges from SQLite

Source

pub fn graph(&self) -> &RwLock<PetCodeGraph>

Get access to the underlying RwLock-protected PetCodeGraph

Callers must acquire read or write lock as appropriate. Use this for operations that don’t require lazy loading.

Source

pub fn graph_read(&self) -> RwLockReadGuard<'_, PetCodeGraph>

Get a read lock guard on the underlying PetCodeGraph

Convenience method for read-only graph operations.

Source

pub fn graph_write(&self) -> RwLockWriteGuard<'_, PetCodeGraph>

Get a write lock guard on the underlying PetCodeGraph

Convenience method for mutable graph operations.

Source

pub fn cache_metrics(&self) -> CacheMetrics

Get a snapshot of cache metrics (hit/miss rates, evictions)

Source

pub fn reset_cache_metrics(&self)

Reset cache metrics

Source

pub fn memory_usage_bytes(&self) -> usize

Get current memory usage in bytes

Source

pub fn memory_budget_bytes(&self) -> usize

Get memory budget in bytes

Source

pub fn memory_usage_ratio(&self) -> f64

Get memory usage as a ratio (0.0 - 1.0)

Source

pub fn is_over_budget(&self) -> bool

Check if memory usage exceeds budget

Source

pub fn stats(&self) -> LazyGraphStats

Get statistics about the lazy graph

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> 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> 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 = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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