Skip to main content

GraphStorageClientV1

Trait GraphStorageClientV1 

Source
pub trait GraphStorageClientV1: Send + Sync {
    // Required methods
    fn register_types<'life0, 'life1, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        batch: Vec<TypeRegistration>,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<TypeRecord>, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn get_type<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        type_id: &'life2 String,
    ) -> Pin<Box<dyn Future<Output = Result<TypeRecord, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             Self: 'async_trait;
    fn list_types<'life0, 'life1, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        query: TypeQuery,
    ) -> Pin<Box<dyn Future<Output = Result<Page<TypeRecord>, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn ingest<'life0, 'life1, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        request: IngestRequest,
    ) -> Pin<Box<dyn Future<Output = Result<IngestOutcome, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn delete_node<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        node_key: &'life2 String,
    ) -> Pin<Box<dyn Future<Output = Result<DeleteOutcome, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             Self: 'async_trait;
    fn delete_edge<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        edge_key: &'life2 String,
    ) -> Pin<Box<dyn Future<Output = Result<DeleteOutcome, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             Self: 'async_trait;
    fn get_node<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        node_key: &'life2 String,
        adjacency_limit: Option<u32>,
    ) -> Pin<Box<dyn Future<Output = Result<NodeView, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             Self: 'async_trait;
    fn project_nodes<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        type_patterns: &'life2 [String],
        query: ODataQuery,
    ) -> Pin<Box<dyn Future<Output = Result<Page<NodeRow>, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             Self: 'async_trait;
    fn search<'life0, 'life1, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        request: SearchRequest,
    ) -> Pin<Box<dyn Future<Output = Result<SearchResponse, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn traverse<'life0, 'life1, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        request: TraverseRequest,
    ) -> Pin<Box<dyn Future<Output = Result<TraversalResponse, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn neighborhood<'life0, 'life1, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
        request: NeighborhoodRequest,
    ) -> Pin<Box<dyn Future<Output = Result<TraversalResponse, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn revision<'life0, 'life1, 'async_trait>(
        &'life0 self,
        ctx: &'life1 SecurityContext,
    ) -> Pin<Box<dyn Future<Output = Result<GraphRevision, CanonicalError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
}
Expand description

Object-safe client for in-process consumption by other gears (version 1).

§Errors

Every method returns the same CanonicalError taxonomy the REST surface renders (DESIGN § Error Model), and the same category for the same failure, because both adapters call one service. Documented once here rather than per method: the vocabulary is the contract, and repeating it twelve times would let the copies drift.

  • invalid_argument — a malformed request, a per-item schema violation (SCHEMA_VIOLATION, addressed by JSON pointer), a request the gear cannot interpret (INVALID_ARGUMENT), or two bounds that cannot hold at once (LIMIT_COMBINATION).
  • out_of_range (LIMIT_EXCEEDED) — a value outside a documented hard range: batch size, depth, page size, an oversized key or query.
  • not_found — the row is absent or the caller may not see it. The two are indistinguishable by contract (anti-enumeration), so a client must not read absence as permission to create.
  • permission_denied (SOURCE_NAMESPACE_FORBIDDEN) — the one denial that names itself, because the caller wrote under a source namespace another producer owns, and that owner is a fact about the tenant rather than about them.
  • aborted — CAS_CONFLICT (a same-key type change, a stale expected_version, a scope owned by another producer), SERIALIZATION, or IDEMPOTENCY_MISMATCH. Re-read and retry.
  • failed_precondition — STALE_GENERATION, IDEMPOTENCY_KEY_EXPIRED, SCOPE_UNSERVABLE, EMBEDDING_SPACE_MISMATCH. Not retryable unchanged.
  • unavailable — a dependency is down: the PDP, the database, the embedding provider. Retry later.
  • deadline_exceeded, cancelled — the operation ran out of the budget it started with, or the caller went away.
  • unimplemented — a capability the selected engine or store does not provide (traversal on an engine without it, labels, topology).
  • unknown, data_loss — an unexpected internal failure, or detected corruption. Escalate rather than retry.

Required Methods§

Source

fn register_types<'life0, 'life1, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, batch: Vec<TypeRegistration>, ) -> Pin<Box<dyn Future<Output = Result<Vec<TypeRecord>, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Register a batch of GTS types, atomically. Byte-identical re-registration converges; a different schema for a registered identifier conflicts.

Source

fn get_type<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, type_id: &'life2 String, ) -> Pin<Box<dyn Future<Output = Result<TypeRecord, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Source

fn list_types<'life0, 'life1, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, query: TypeQuery, ) -> Pin<Box<dyn Future<Output = Result<Page<TypeRecord>, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

One page of the type catalogue.

Continue while next_cursor is Some, even when items is empty. This endpoint does not follow the common “stop when the page is empty” convention. A pattern is applied after rows are read, and the scan gives up its pass after a bounded number of rows; when no row in that pass matches, the answer is an empty page carrying the cursor to resume from. An empty page therefore means “nothing here yet”, not “nothing left” – only a next_cursor of None means that. A client that stops on the empty page silently drops every match beyond it, which is most likely exactly where a selective pattern finds them.

Source

fn ingest<'life0, 'life1, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, request: IngestRequest, ) -> Pin<Box<dyn Future<Output = Result<IngestOutcome, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Apply one atomic ingest batch. request.idempotency_key carries the same value the REST path reads from the Idempotency-Key header.

The key is optional, and it is what makes a retry safe after an unknown commit outcome – the case where the batch committed and the response was lost. With a key, an identical retry returns the recorded outcome and touches no graph state; the same key with a different request is a conflict. Without one, none of that happens: no receipt is read and none is written, so a retry is a new logical request that re-runs the write path. That is not always harmless – a batch that replaces a scope removes what it does not re-declare, and running it twice is not the same as running it once. A producer that retries on timeout should send a key.

Source

fn delete_node<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, node_key: &'life2 String, ) -> Pin<Box<dyn Future<Output = Result<DeleteOutcome, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Soft-delete a node together with its incident edges.

Source

fn delete_edge<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, edge_key: &'life2 String, ) -> Pin<Box<dyn Future<Output = Result<DeleteOutcome, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Soft-delete one edge.

Source

fn get_node<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, node_key: &'life2 String, adjacency_limit: Option<u32>, ) -> Pin<Box<dyn Future<Output = Result<NodeView, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Node by key with payload and bounded bidirectional adjacency. adjacency_limit = None uses the configured default.

Source

fn project_nodes<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, type_patterns: &'life2 [String], query: ODataQuery, ) -> Pin<Box<dyn Future<Output = Result<Page<NodeRow>, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Tabular projection over declared index paths, bound to the platform OData options.

type_patterns narrows the projection to the types they resolve to; the effective set is that intersected with the pattern of the permission that authorized the request. Empty means every authorized type. Patterns are resolved by the shared GTS implementation, never compiled into SQL.

Source

fn search<'life0, 'life1, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, request: SearchRequest, ) -> Pin<Box<dyn Future<Output = Result<SearchResponse, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Lexical, vector or hybrid search.

Source

fn traverse<'life0, 'life1, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, request: TraverseRequest, ) -> Pin<Box<dyn Future<Output = Result<TraversalResponse, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Seeded, depth-bounded traversal.

Source

fn neighborhood<'life0, 'life1, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, request: NeighborhoodRequest, ) -> Pin<Box<dyn Future<Output = Result<TraversalResponse, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Bounded neighborhood projection.

Source

fn revision<'life0, 'life1, 'async_trait>( &'life0 self, ctx: &'life1 SecurityContext, ) -> Pin<Box<dyn Future<Output = Result<GraphRevision, CanonicalError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

The caller-visible (source_epoch, graph_revision) identity.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§