pub trait GraphStore:
Send
+ Sync
+ 'static {
Show 25 methods
// Required methods
fn upsert_edge<'life0, 'async_trait>(
&'life0 self,
edge: Edge,
) -> Pin<Box<dyn Future<Output = StorageResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn upsert_edges<'life0, 'async_trait>(
&'life0 self,
edges: Vec<Edge>,
) -> Pin<Box<dyn Future<Output = StorageResult<BatchWriteSummary>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn get_edge<'life0, 'async_trait>(
&'life0 self,
id: LinkId,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Edge>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn get_edge_including_deleted<'life0, 'async_trait>(
&'life0 self,
id: LinkId,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Edge>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn get_edge_by_natural_key_including_deleted<'life0, 'life1, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
source_id: Uuid,
target_id: Uuid,
relation: EdgeRelation,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Edge>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn delete_edge<'life0, 'async_trait>(
&'life0 self,
id: LinkId,
mode: DeleteMode,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn query_edges<'life0, 'async_trait>(
&'life0 self,
filter: EdgeFilter,
sort: Vec<SortOrder<EdgeSortField>>,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Edge>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn count_edges<'life0, 'async_trait>(
&'life0 self,
filter: EdgeFilter,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn count_edges_by_relation<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(EdgeRelation, u64)>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn query_edges_after<'life0, 'async_trait>(
&'life0 self,
filter: EdgeFilter,
after: Option<Uuid>,
limit: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<EdgeSeekPage>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn neighbors<'life0, 'async_trait>(
&'life0 self,
node_id: Uuid,
query: NeighborQuery,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<NeighborHit>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn traverse<'life0, 'async_trait>(
&'life0 self,
request: TraversalRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<GraphPath>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn purge_incident_edges<'life0, 'async_trait>(
&'life0 self,
node_id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
// Provided methods
fn replace_edge_if_unchanged<'life0, 'async_trait>(
&'life0 self,
_edge: Edge,
_expected_updated_at: DateTime<Utc>,
_expected_deleted_at: Option<DateTime<Utc>>,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn upsert_edge_guarded<'life0, 'async_trait>(
&'life0 self,
_edge: Edge,
) -> Pin<Box<dyn Future<Output = StorageResult<GuardedWriteOutcome>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn upsert_edges_guarded<'life0, 'async_trait>(
&'life0 self,
_edges: Vec<Edge>,
) -> Pin<Box<dyn Future<Output = StorageResult<GuardedBatchOutcome>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn query_edges_in_namespaces<'life0, 'life1, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
filter: EdgeFilter,
sort: Vec<SortOrder<EdgeSortField>>,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Edge>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn count_edges_in_namespaces<'life0, 'life1, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
filter: EdgeFilter,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn count_edges_by_relation_in_namespaces<'life0, 'life1, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(EdgeRelation, u64)>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn edge_sequence<'life0, 'async_trait>(
&'life0 self,
_id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<i64>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn edge_sequences<'life0, 'life1, 'async_trait>(
&'life0 self,
ids: &'life1 [Uuid],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(Uuid, i64)>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn query_edges_sequence_after<'life0, 'async_trait>(
&'life0 self,
_filter: EdgeFilter,
_after: Option<SeekCursor>,
_limit: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<SeekPage<Edge>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn neighbors_both_directions<'life0, 'async_trait>(
&'life0 self,
node_id: Uuid,
query: NeighborQuery,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<DirectedNeighborHit>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn get_edges<'life0, 'life1, 'async_trait>(
&'life0 self,
ids: &'life1 [LinkId],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Edge>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn batch_neighbors<'life0, 'life1, 'async_trait>(
&'life0 self,
sources: &'life1 [Uuid],
query: NeighborQuery,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(Uuid, NeighborHit)>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
}Expand description
Directed edge CRUD and graph traversal over the knowledge graph.
Required Methods§
Sourcefn upsert_edge<'life0, 'async_trait>(
&'life0 self,
edge: Edge,
) -> Pin<Box<dyn Future<Output = StorageResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn upsert_edge<'life0, 'async_trait>(
&'life0 self,
edge: Edge,
) -> Pin<Box<dyn Future<Output = StorageResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Insert or update a single edge.
Sourcefn upsert_edges<'life0, 'async_trait>(
&'life0 self,
edges: Vec<Edge>,
) -> Pin<Box<dyn Future<Output = StorageResult<BatchWriteSummary>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn upsert_edges<'life0, 'async_trait>(
&'life0 self,
edges: Vec<Edge>,
) -> Pin<Box<dyn Future<Output = StorageResult<BatchWriteSummary>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Insert or update a batch of edges.
Sourcefn get_edge<'life0, 'async_trait>(
&'life0 self,
id: LinkId,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_edge<'life0, 'async_trait>(
&'life0 self,
id: LinkId,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Fetch an edge by link ID, returning None if absent. Filters soft-deleted rows.
Sourcefn get_edge_including_deleted<'life0, 'async_trait>(
&'life0 self,
id: LinkId,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_edge_including_deleted<'life0, 'async_trait>(
&'life0 self,
id: LinkId,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Fetch an edge by link ID including soft-deleted rows. Used by the runtime hard-delete path to locate and namespace-check an already-soft-deleted edge before purging it.
Sourcefn get_edge_by_natural_key_including_deleted<'life0, 'life1, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
source_id: Uuid,
target_id: Uuid,
relation: EdgeRelation,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_edge_by_natural_key_including_deleted<'life0, 'life1, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
source_id: Uuid,
target_id: Uuid,
relation: EdgeRelation,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Fetch an edge by natural key (namespace, source, target, relation) including
soft-deleted rows. Used by the atomic-apply result renderer for a symmetric-relation
update whose surviving canonical row may be tombstoned (ADR-039 DO NOTHING) — the
normal query_edges/list_edges path filters deleted_at IS NULL and would report
“not found” for exactly that row.
namespace is the natural key’s own namespace column value (part of the
UNIQUE(namespace, source_id, target_id, relation) constraint this method queries by)
— it is passed explicitly rather than implied by whichever store instance self is,
so a caller who resolved the record’s namespace independently of its own ambient token
(the atomic-apply renderer, which knows the committed edge’s namespace from its prepare-
time EdgeNaturalKey, not from the caller’s token) cannot accidentally query the wrong
namespace by relying on implicit store scoping.
Sourcefn delete_edge<'life0, 'async_trait>(
&'life0 self,
id: LinkId,
mode: DeleteMode,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn delete_edge<'life0, 'async_trait>(
&'life0 self,
id: LinkId,
mode: DeleteMode,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Delete an edge by link ID using the specified delete mode.
Sourcefn query_edges<'life0, 'async_trait>(
&'life0 self,
filter: EdgeFilter,
sort: Vec<SortOrder<EdgeSortField>>,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn query_edges<'life0, 'async_trait>(
&'life0 self,
filter: EdgeFilter,
sort: Vec<SortOrder<EdgeSortField>>,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Query edges with filter, sort, and pagination.
Sourcefn count_edges<'life0, 'async_trait>(
&'life0 self,
filter: EdgeFilter,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn count_edges<'life0, 'async_trait>(
&'life0 self,
filter: EdgeFilter,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Count edges matching the given filter.
Sourcefn count_edges_by_relation<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(EdgeRelation, u64)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn count_edges_by_relation<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(EdgeRelation, u64)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Count edges grouped by relation, ignoring soft-deleted rows. Cheap
aggregate (GROUP BY relation) used to report the true per-relation
population for full-graph audits (#702.3).
Sourcefn query_edges_after<'life0, 'async_trait>(
&'life0 self,
filter: EdgeFilter,
after: Option<Uuid>,
limit: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<EdgeSeekPage>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn query_edges_after<'life0, 'async_trait>(
&'life0 self,
filter: EdgeFilter,
after: Option<Uuid>,
limit: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<EdgeSeekPage>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Seek-pagination page of edges ordered by id ascending, using an
indexed range scan (id > after) against the (namespace, id)
primary key instead of OFFSET. after is exclusive; None starts
from the beginning of the set. This remains an efficient compatibility
path for a fixed edge set, but random UUIDs inserted concurrently may
sort behind an issued boundary. Public concurrent walks use
Self::query_edges_sequence_after instead (#1424).
Sourcefn neighbors<'life0, 'async_trait>(
&'life0 self,
node_id: Uuid,
query: NeighborQuery,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<NeighborHit>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn neighbors<'life0, 'async_trait>(
&'life0 self,
node_id: Uuid,
query: NeighborQuery,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<NeighborHit>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Return immediate neighbors of a graph node.
Sourcefn traverse<'life0, 'async_trait>(
&'life0 self,
request: TraversalRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<GraphPath>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn traverse<'life0, 'async_trait>(
&'life0 self,
request: TraversalRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<GraphPath>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Bounded multi-hop BFS traversal from the given roots.
Implementations must validate TraversalRequest::validate, count
adjacency rows before first-visit de-duplication against the request’s
shared execution budget, stop a root as soon as its effective result
limit is filled, and return an error rather than partial paths when the
work or time budget expires. Minimum-depth BFS selection is normative;
same-depth tie ordering is not.
Sourcefn purge_incident_edges<'life0, 'async_trait>(
&'life0 self,
node_id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn purge_incident_edges<'life0, 'async_trait>(
&'life0 self,
node_id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Hard-delete every incident edge (source or target) for node_id, regardless of soft-delete
state. Used during endpoint hard-delete to prevent dangling graph_edges rows (ADR-002
no-dangling-references contract).
Provided Methods§
Sourcefn replace_edge_if_unchanged<'life0, 'async_trait>(
&'life0 self,
_edge: Edge,
_expected_updated_at: DateTime<Utc>,
_expected_deleted_at: Option<DateTime<Utc>>,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn replace_edge_if_unchanged<'life0, 'async_trait>(
&'life0 self,
_edge: Edge,
_expected_updated_at: DateTime<Utc>,
_expected_deleted_at: Option<DateTime<Utc>>,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Replace an edge only when the persisted row still matches the caller’s read snapshot.
expected_updated_at is the snapshot revision and
expected_deleted_at closes the soft-delete race. The replacement
edge’s updated_at must be strictly greater than that persisted
revision. Returns false when the row disappeared, changed, or was
supplied a non-advancing replacement revision. This is the full-edge
compare-and-swap seam used when a caller derives coupled fields from
that snapshot before persistence — mirrors
crate::NoteStore::replace_note_if_unchanged. The default returns
Unsupported rather than falling back to an unguarded upsert and
reintroducing the stale-snapshot race.
Sourcefn upsert_edge_guarded<'life0, 'async_trait>(
&'life0 self,
_edge: Edge,
) -> Pin<Box<dyn Future<Output = StorageResult<GuardedWriteOutcome>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn upsert_edge_guarded<'life0, 'async_trait>(
&'life0 self,
_edge: Edge,
) -> Pin<Box<dyn Future<Output = StorageResult<GuardedWriteOutcome>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Insert or update a single edge, re-checking that both endpoints still exist (and are not soft-deleted) as part of the same write, not a separate prior read. Closes the TOCTOU window between an async prepare-time existence check and a later, unconditional write: a concurrent hard-delete of an endpoint that lands between the two can otherwise leave a durably dangling edge (#769).
Returns GuardedWriteOutcome::Refused naming exactly which
endpoint(s) were missing, determined by the guard’s own in-transaction
probe — never reconstructed by a caller re-reading the endpoints after
the write already failed, since a concurrent write landing between the
refusal and any such later read could misreport which endpoint was
actually missing at write time.
Default returns StorageError::Unsupported: a backend that does not
override this method cannot honor the endpoint-existence guarantee,
and silently falling back to GraphStore::upsert_edge would
reintroduce the TOCTOU window this method exists to close.
Sourcefn upsert_edges_guarded<'life0, 'async_trait>(
&'life0 self,
_edges: Vec<Edge>,
) -> Pin<Box<dyn Future<Output = StorageResult<GuardedBatchOutcome>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn upsert_edges_guarded<'life0, 'async_trait>(
&'life0 self,
_edges: Vec<Edge>,
) -> Pin<Box<dyn Future<Output = StorageResult<GuardedBatchOutcome>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Batch form of GraphStore::upsert_edge_guarded. All-or-nothing:
if any edge’s endpoints are missing at write time, no edge from the
batch is persisted, BatchWriteSummary::affected is 0, and
GuardedBatchOutcome::refused names the first failing batch entry and
its missing endpoint(s) — determined by the same in-transaction
pre-check that aborted the batch, not a post-hoc re-read.
Default returns StorageError::Unsupported, for the same reason as
GraphStore::upsert_edge_guarded’s default.
Sourcefn query_edges_in_namespaces<'life0, 'life1, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
filter: EdgeFilter,
sort: Vec<SortOrder<EdgeSortField>>,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn query_edges_in_namespaces<'life0, 'life1, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
filter: EdgeFilter,
sort: Vec<SortOrder<EdgeSortField>>,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Query edges across the given namespaces in one deterministic query
with real SQL paging. The multi-namespace analogue of
Self::query_edges: a single statement with namespace IN (...)
keeps offset continuation coherent, where fetching per-namespace
prefixes and slicing a client-side merge floats the window between
calls (silent duplicate/skip enumeration). Backends without batched
namespace support retain the single-namespace path and reject
multi-namespace requests explicitly.
Sourcefn count_edges_in_namespaces<'life0, 'life1, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
filter: EdgeFilter,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn count_edges_in_namespaces<'life0, 'life1, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
filter: EdgeFilter,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Count edges across the given namespaces in one aggregate query. Backends without batched namespace support retain the single-namespace path and reject multi-namespace requests explicitly.
Sourcefn count_edges_by_relation_in_namespaces<'life0, 'life1, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(EdgeRelation, u64)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn count_edges_by_relation_in_namespaces<'life0, 'life1, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(EdgeRelation, u64)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Count edges grouped by relation across the given namespaces in one aggregate query.
Sourcefn edge_sequence<'life0, 'async_trait>(
&'life0 self,
_id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<i64>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn edge_sequence<'life0, 'async_trait>(
&'life0 self,
_id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<i64>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Resolve an edge id to its immutable insertion sequence.
Sourcefn edge_sequences<'life0, 'life1, 'async_trait>(
&'life0 self,
ids: &'life1 [Uuid],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(Uuid, i64)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn edge_sequences<'life0, 'life1, 'async_trait>(
&'life0 self,
ids: &'life1 [Uuid],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(Uuid, i64)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Resolve edge ids to immutable insertion sequences. Implementations may override this to batch the lookup; the default preserves correctness.
Sourcefn query_edges_sequence_after<'life0, 'async_trait>(
&'life0 self,
_filter: EdgeFilter,
_after: Option<SeekCursor>,
_limit: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<SeekPage<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn query_edges_sequence_after<'life0, 'async_trait>(
&'life0 self,
_filter: EdgeFilter,
_after: Option<SeekCursor>,
_limit: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<SeekPage<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Seek-pagination page ordered by immutable insertion sequence. This is the stable public-list contract for walks overlapping inserts (#1424).
Sourcefn neighbors_both_directions<'life0, 'async_trait>(
&'life0 self,
node_id: Uuid,
query: NeighborQuery,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<DirectedNeighborHit>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn neighbors_both_directions<'life0, 'async_trait>(
&'life0 self,
node_id: Uuid,
query: NeighborQuery,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<DirectedNeighborHit>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Return neighbors in BOTH directions in a single call, each tagged with
the direction (Out/In) it was found in. query.direction is
ignored — this always fetches both directions.
Exists so a caller that needs both-direction neighbors labeled by
direction (e.g. the context verb) can do so with one storage query
instead of two separate direction-scoped neighbors calls. The
default implementation preserves the original two-call behavior for
backends that don’t override it; SqlGraphStore overrides this with a
single UNION ALL query that projects a direction literal per arm.
Sourcefn get_edges<'life0, 'life1, 'async_trait>(
&'life0 self,
ids: &'life1 [LinkId],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_edges<'life0, 'life1, 'async_trait>(
&'life0 self,
ids: &'life1 [LinkId],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Edge>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Fetch multiple edges by their link IDs in a single round-trip.
IDs that are not found (absent or soft-deleted) are silently skipped;
the returned Vec may be shorter than ids. Backends that support
batched IN (...) queries should override this; the default loops
get_edge so non-SQLite backends keep compiling unchanged.
Callers must chunk large ID lists before calling if they need a strict size bound; this method does not enforce a maximum.
Sourcefn batch_neighbors<'life0, 'life1, 'async_trait>(
&'life0 self,
sources: &'life1 [Uuid],
query: NeighborQuery,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(Uuid, NeighborHit)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn batch_neighbors<'life0, 'life1, 'async_trait>(
&'life0 self,
sources: &'life1 [Uuid],
query: NeighborQuery,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<(Uuid, NeighborHit)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Return neighbors for multiple source nodes in a single round-trip,
yielding (source_id, hit) pairs.
The query parameters (direction, relations, min_weight) are applied
uniformly to every source node. query.limit is applied per source:
each source returns at most limit hits. Backends that support batched
source_id IN (...) queries should override this; the default loops
neighbors so non-SQLite backends keep compiling unchanged.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".