Skip to main content

ReadonlyRepo

Struct ReadonlyRepo 

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

A view of the repository pinned to a single OperationId.

ReadonlyRepo does not mutate state. To make changes, call start_transaction and then Transaction::commit - which returns a fresh ReadonlyRepo pinned to the new op.

All fields are behind Arc, so clone() is cheap. Sharing across threads is safe.

Implementations§

Source§

impl ReadonlyRepo

Source

pub fn init( blockstore: Arc<dyn Blockstore>, op_heads: Arc<dyn OpHeadsStore>, ) -> Result<Self, Error>

Initialize a fresh repository per SPEC §7.5.

Writes one root View (empty heads, empty refs) and one root Operation into the blockstore, registers the op as the sole op-head, and returns a ReadonlyRepo pinned to that op.

§Errors

Returns a store or codec error if blockstore writes fail.

Source

pub fn open( blockstore: Arc<dyn Blockstore>, op_heads: Arc<dyn OpHeadsStore>, ) -> Result<Self, Error>

Open an existing repository pinned to the current op-head.

If the op-heads store has more than one current head (concurrent writers landed against the same base), the 3-way merge from crate::repo::merge runs transparently: it finds the op-DAG common ancestor, 3-way merges each head’s View (emitting RefTarget::Conflicted for divergent refs), writes a synthetic merge Operation, and advances op-heads. The returned ReadonlyRepo is pinned to that merge op.

§Errors
Source

pub fn load_at( blockstore: Arc<dyn Blockstore>, op_heads: Arc<dyn OpHeadsStore>, op_id: Cid, ) -> Result<Self, Error>

Load a repository view pinned to a specific OperationId.

Does not consult the op-heads store. Used internally by open and Transaction::commit.

§Errors

Store / codec errors if loading objects fails.

Source

pub const fn op_id(&self) -> &Cid

The CID of the Operation this view is pinned to.

Source

pub fn operation(&self) -> &Operation

The Operation this view is pinned to.

Source

pub fn view(&self) -> &View

The View snapshotted by the current Operation.

Source

pub fn head_commit(&self) -> Option<&Commit>

The head Commit of the current view. None on a freshly- initialized repository that hasn’t yet received any commits.

Source

pub fn blockstore(&self) -> &Arc<dyn Blockstore>

Access the underlying blockstore (borrowed Arc).

Source

pub fn op_heads_store(&self) -> &Arc<dyn OpHeadsStore>

Access the underlying op-heads store (borrowed Arc).

Source

pub fn lookup_node(&self, id: &NodeId) -> Result<Option<Node>, Error>

Look up a node by its stable NodeId in the current commit’s node tree. Returns None if absent or if the repository has no commits yet.

§Errors

Store or codec errors while walking the Prolly tree.

Source

pub fn embedding_for( &self, node_cid: &Cid, model: &str, ) -> Result<Option<Embedding>, Error>

Look up the embedding for a node by its content-addressed NodeCid and a model identifier, walking the Commit::embeddings Prolly sidecar. Returns None when:

  • the repo has no commits yet,
  • the head commit has no embedding sidecar (embeddings = None),
  • the sidecar tree has no entry for this NodeCid, or
  • the bucket exists but does not carry a vector under the requested model string.

The Prolly key is derived via the same helper (embedding_key_for_node_cid) the write side uses, so a Transaction::set_embedding write and a subsequent embedding_for read are guaranteed to agree on the bucket location.

§Why not on Node?

The same trade documented on Commit::embeddings: dense vector bytes drift in the last bit across ORT thread counts, so storing them on the Node would couple NodeCid to thread count. The sidecar separates identity (Node) from derived bytes (Embedding) so NodeCid stays stable.

§Errors

Store or codec errors while walking the Prolly tree or decoding the bucket. A missing key is Ok(None), not an error.

Source

pub fn outgoing_edges( &self, src: &NodeId, etype_filter: Option<&[&str]>, ) -> Result<Vec<Edge>, Error>

All outgoing edges from src in the current commit, optionally filtered by edge-type label. Returns an empty vec if the node has no adjacency bucket (no authored out-edges), or if the repo has no commits yet.

Used by graph-aware retrieval (Retriever::with_graph_expand) to expand a seed set via 1-hop neighborhood traversal.

§Errors

Store or codec errors while walking the adjacency index or decoding Edge blocks.

Source

pub fn incoming_edges( &self, dst: &NodeId, etype_filter: Option<&[&str]>, ) -> Result<Vec<Edge>, Error>

All incoming edges pointing at dst in the current commit, optionally filtered by edge-type label. Returns an empty vec if the node has no incoming-adjacency bucket, if the commit’s IndexSet has no incoming tree (pre-0.3 repos), or if the repo has no commits yet.

Symmetric mirror of Self::outgoing_edges. Use this from agent-side callers that want “who points at this node” without constructing a full crate::index::Query.

§Errors

Store or codec errors while walking the incoming-adjacency index or decoding Edge blocks.

Source

pub fn incoming_edges_capped( &self, dst: &NodeId, etype_filter: Option<&[&str]>, cap: usize, ) -> Result<Vec<Edge>, Error>

Explicit-cap variant of Self::incoming_edges. Use this when a caller is prepared to handle truncation (e.g. an MCP tool that streams the bucket and renders its own “clipped at N” marker). Default Self::incoming_edges applies crate::index::Query::DEFAULT_ADJACENCY_CAP so a single high-fan-in dst can’t DoS the agent-side caller.

§Errors

Store or codec errors while walking the incoming-adjacency index or decoding Edge blocks.

Source

pub fn is_tombstoned(&self, id: &NodeId) -> bool

Whether id is listed in the current View’s tombstone map.

true means a prior commit on this view recorded a Tombstone against the node - retrieval paths filter it out by default. The underlying Node block may still exist in the node Prolly tree and remains addressable by CID; only the “show this to an agent” decision changes.

Source

pub fn tombstone_for(&self, id: &NodeId) -> Option<&Tombstone>

Fetch the tombstone record for id, if any.

Source

pub fn start_transaction(&self) -> Transaction

Start a transaction. The returned Transaction holds a cheap clone of the current repo state; multiple transactions can be started concurrently but only the first to commit wins (subsequent commits against stale heads will land on a concurrent op-head in M8.5’s merge model).

Source

pub const fn query(&self) -> Query<'_>

Convenience: Query::new(self). One-liner entry point for the agent-facing retrieval API.

let hits = repo.query().label("Person").where_eq("name", "Alice").execute()?;
Source

pub fn build_vector_index( &self, model: &str, ) -> Result<BruteForceVectorIndex, Error>

Build a full-corpus vector index over every node whose crate::objects::Embedding::model equals model. Dimensions are inferred from the first matching embedding; subsequent embeddings with a different dim are silently skipped.

Each index binds to a single (model, dim) - agents who use multiple embedding models build one index per model.

§Errors
Source

pub fn retrieve(&self) -> Retriever<'_>

Start an agent-facing retrieval builder that composes the structured query, dense vector similarity, and learned-sparse retrieval under a token budget. See crate::retrieve for the full model.

let result = repo
.retrieve()
.label("Document")
.vector("openai:text-embedding-3-small", embedding)
.token_budget(2000)
.execute()?;
Source

pub fn update_ref( &self, name: &str, expected_prev: Option<&RefTarget>, new: Option<RefTarget>, author: &str, ) -> Result<Self, Error>

Atomically update a named ref, subject to an expected-previous check (SPEC §6.4).

Semantics:

  1. Read the current value of name in the current view’s refs.
  2. If the current value does not ==-compare to expected_prev (structurally equal, not byte-exact - our RefTarget derives PartialEq and constructs canonical form), return RepoError::Stale.
  3. Otherwise, build a new View with the ref updated (insert if new is Some, remove if new is None), a new Operation wrapping it, advance op-heads, and return a fresh repo.

Per SPEC §6.4, CAS guarantees no lost update - two concurrent CAS attempts against the same base both succeed at the op-log layer, and the next read sees a conflicted refs state. For exactly-one-winner semantics, combine with Transaction::commit_opts’s linearize: true or with an out-of-process coordinator.

§Errors
  • RepoError::Stale on mismatch with expected_prev.
  • Codec / store errors on write.

Trait Implementations§

Source§

impl Clone for ReadonlyRepo

Source§

fn clone(&self) -> ReadonlyRepo

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for ReadonlyRepo

Source§

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

Formats the value using the given formatter. Read more

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