Skip to main content

PgGraphMemory

Struct PgGraphMemory 

Source
pub struct PgGraphMemory<N, E> { /* private fields */ }
Expand description

Postgres-backed GraphMemory<N, E>.

Cheap to clone — internal state is an Arc<PgPool> plus two owned table-name strings.

Implementations§

Source§

impl<N, E> PgGraphMemory<N, E>

Source

pub fn builder() -> PgGraphMemoryBuilder<N, E>

Start a fluent builder. connection_string is the only required field; everything else has a sensible default.

Source

pub async fn list_nodes( &self, ns: &Namespace, limit: usize, offset: usize, ) -> Result<Vec<NodeId>>

Paginated node-id enumeration, ascending by id (UUID v7 mint-time order). Operator-side admin / migration path.

Source

pub async fn list_node_records( &self, ns: &Namespace, limit: usize, offset: usize, ) -> Result<Vec<(NodeId, N)>>

Paginated (NodeId, N) enumeration — single round-trip versus list_nodes + per-id node(). Operator-side bulk-export path.

Source

pub async fn list_edges( &self, ns: &Namespace, limit: usize, offset: usize, ) -> Result<Vec<EdgeId>>

Paginated edge-id enumeration. Operator-side migration path.

Source

pub async fn list_edge_records( &self, ns: &Namespace, limit: usize, offset: usize, ) -> Result<Vec<GraphHop<E>>>

Paginated GraphHop<E> enumeration — full structural body in one round-trip. Operator-side bulk-export path.

Source

pub async fn prune_orphan_nodes(&self, ns: &Namespace) -> Result<usize>

Drop every node with no incident edge — single SQL anti-join against the edges table. Two-phase prune companion to prune_older_than: the edge sweep leaves orphans that this call cleans up. Operator-side admin path.

Trait Implementations§

Source§

impl<N, E> Clone for PgGraphMemory<N, E>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<N, E> Debug for PgGraphMemory<N, E>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<N, E> GraphMemory<N, E> for PgGraphMemory<N, E>
where N: Clone + Send + Sync + Serialize + DeserializeOwned + 'static, E: Clone + Send + Sync + Serialize + DeserializeOwned + 'static,

Source§

fn add_node<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, node: N, ) -> Pin<Box<dyn Future<Output = Result<NodeId>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Insert node and return its assigned id.
Source§

fn add_edge<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, from: &'life3 NodeId, to: &'life4 NodeId, edge: E, timestamp: DateTime<Utc>, ) -> Pin<Box<dyn Future<Output = Result<EdgeId>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait,

Insert an edge from from to to carrying edge. timestamp is supplied by the caller so re-inserting after a replay produces deterministic edges.
Source§

fn add_edges_batch<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, edges: Vec<(NodeId, NodeId, E, DateTime<Utc>)>, ) -> Pin<Box<dyn Future<Output = Result<Vec<EdgeId>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Insert a batch of edges atomically. Each tuple is (from, to, edge, timestamp); endpoints must already exist (same contract as Self::add_edge). Returns the assigned EdgeIds in input order. Read more
Source§

fn get_node<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, id: &'life3 NodeId, ) -> Pin<Box<dyn Future<Output = Result<Option<N>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Look up a node by id (verb-family get per .claude/rules/naming.md — single-item primary-key lookup).
Source§

fn get_edge<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, edge_id: &'life3 EdgeId, ) -> Pin<Box<dyn Future<Output = Result<Option<GraphHop<E>>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Look up an edge by id and return the full structural body (GraphHop<E>from, to, edge, timestamp). Operators rarely want the payload alone for edges; the endpoints and timestamp are usually load-bearing for any follow-up decision (audit context, freshness check, neighbour navigation). Returning the full hop saves a second lookup. Read more
Source§

fn neighbors<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, node: &'life3 NodeId, direction: Direction, ) -> Pin<Box<dyn Future<Output = Result<Vec<(EdgeId, NodeId, E)>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Edges incident to node in the requested direction. Each triple is (EdgeId, neighbour NodeId, edge payload).
Source§

fn traverse<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, start: &'life3 NodeId, direction: Direction, max_depth: usize, ) -> Pin<Box<dyn Future<Output = Result<Vec<GraphHop<E>>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Breadth-first traversal starting at start, expanding up to max_depth hops along edges in the requested direction. Returns the visited hops in BFS order (excluding the seed node, which has no inbound edge in this traversal). Use Direction::Both for relationship-graph queries that don’t care about edge polarity (knowledge graphs typically want this).
Source§

fn find_path<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, from: &'life3 NodeId, to: &'life4 NodeId, direction: Direction, max_depth: usize, ) -> Pin<Box<dyn Future<Output = Result<Option<Vec<GraphHop<E>>>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait,

Shortest unweighted path from from to to (BFS) along edges in the requested direction. Returns the sequence of hops; Some(vec![]) means from == to (already at destination — no edges traversed); None means no path exists within max_depth hops.
Source§

fn temporal_filter<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, from: DateTime<Utc>, to: DateTime<Utc>, ) -> Pin<Box<dyn Future<Output = Result<Vec<GraphHop<E>>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Edges whose timestamp falls in [from, to). Useful for audit-log style queries (“what relationships did the agent learn last week”).
Source§

fn node_count<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, ) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Count nodes in ns. Cheap operator metric for size-based decisions (paginate vs stream, fast-fail empty-namespace check, audit / dashboard surface). Default impl returns 0.
Source§

fn edge_count<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, ) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Count edges in ns. Cheap operator metric — same rationale as Self::node_count. Default impl returns 0.
Source§

fn delete_edge<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, edge_id: &'life3 EdgeId, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Drop one edge by id. Idempotent — deleting an absent edge succeeds. Required — backends that don’t support edge deletion are degenerate; closed the CRUD-completeness gap.
Source§

fn delete_node<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, node_id: &'life3 NodeId, ) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Drop one node by id and every edge incident to it. Cascades — operators that don’t want cascading delete every incident edge first via Self::delete_edge and then call this. Returns the count of removed edges so callers can log or expose cleanup metrics; 0 when the node had no edges (or was absent — the operation is idempotent). Read more
Source§

fn prune_older_than<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _ctx: &'life1 ExecutionContext, ns: &'life2 Namespace, ttl: Duration, ) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Drop every edge in ns whose timestamp is older than ttl ago. Returns the count of removed edges so callers can log or expose pruning metrics. Read more

Auto Trait Implementations§

§

impl<N, E> Freeze for PgGraphMemory<N, E>

§

impl<N, E> !RefUnwindSafe for PgGraphMemory<N, E>

§

impl<N, E> Send for PgGraphMemory<N, E>

§

impl<N, E> Sync for PgGraphMemory<N, E>

§

impl<N, E> Unpin for PgGraphMemory<N, E>

§

impl<N, E> UnsafeUnpin for PgGraphMemory<N, E>

§

impl<N, E> !UnwindSafe for PgGraphMemory<N, E>

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: 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: 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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<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