Skip to main content

Store

Trait Store 

Source
pub trait Store: Resolver + Sealed {
Show 29 methods // Required methods fn put_descriptor(&self, bytes: &[u8]) -> Result<String>; fn put_receipt(&self, bytes: &[u8]) -> Result<String>; fn put_blob(&self, bytes: &[u8]) -> Result<String>; fn blob(&self, sha256: &str) -> Result<Option<Cow<'_, [u8]>>>; fn put_version( &self, cell_id: &str, tx: &str, receipt_hash: &str, ) -> Result<()>; fn version_asof(&self, cell_id: &str, asof: &str) -> Result<Option<Version>>; fn versions( &self, cell_id: &str, from: &str, to: &str, ) -> Result<Vec<Version>>; fn latest(&self, cell_id: &str) -> Result<Option<Version>>; fn dependents(&self, receipt_hash: &str) -> Result<Vec<String>>; fn inputs(&self, receipt_hash: &str) -> Result<Vec<String>>; fn put_namespace( &self, host: &str, keydoc_bytes: &[u8], validated_at: &str, ) -> Result<()>; fn namespace(&self, host: &str) -> Result<Option<Namespace>>; fn bind_name(&self, fn_name: &str, fn_hash: &str, tx: &str) -> Result<()>; fn resolve_name(&self, fn_name: &str, asof: &str) -> Result<Option<String>>; fn resolve_binding( &self, fn_name: &str, asof: &str, ) -> Result<Option<Binding>>; fn put_computed( &self, cell_id: &str, tx: &str, receipt_hash: &str, ) -> Result<()>; fn computed_asof( &self, cell_id: &str, asof: &str, ) -> Result<Option<Version>>; fn stored_asof(&self, cell_id: &str, asof: &str) -> Result<Option<Version>>; fn cell_dependents(&self, cell_id: &str) -> Result<Vec<String>>; fn put_manifest(&self, bytes: &[u8]) -> Result<String>; fn member_manifests(&self, receipt_hash: &str) -> Result<Vec<String>>; fn slice_entries(&self, receipt_hash: &str) -> Result<Vec<String>>; fn slice_dependents(&self, entry: &str) -> Result<Vec<String>>; fn slice_members( &self, slice: &Slice, asof: &str, ) -> Result<Vec<SliceMember>>; fn versions_between( &self, cell_id: &str, from: &str, to: &str, asof: &str, ) -> Result<Vec<SliceMember>>; fn slice_values(&self, slice: &Slice, asof: &str) -> Result<Vec<SliceValue>>; fn slice_changed_after(&self, slice: &Slice, asof: &str) -> Result<bool>; // Provided methods fn computed_asof_with_receipt( &self, cell_id: &str, asof: &str, ) -> Result<Option<(Version, Cow<'_, [u8]>)>> { ... } fn stored_asof_with_receipt( &self, cell_id: &str, asof: &str, ) -> Result<Option<(Version, Cow<'_, [u8]>)>> { ... }
}
Expand description

A Datumesh store: a Resolver that can also be written to.

Instants are SPEC 3.3 instants (YYYY-MM-DDTHH:MM:SS.ffffffZ), hashes and cell ids 64 lowercase hex digits, hosts DNS names and function names fully qualified. Every method, read or write, refuses anything else with the core’s error code (Error::Invalid), and reports a database failure as Error::Database (or Error::PoolTimeout): a read answers Ok(None) / Ok(vec![]) only when the store really holds nothing.

The Resolver methods keep the core’s Option signatures: there a malformed argument or a database failure is None (logged with tracing when it is a failure), which verify reports as unavailable.

Only this crate implements Store (it is sealed, since 0.3.0): the store is the trust boundary, where every receipt is verified against its host’s key document before it is kept, and what a store answers is relied on as checked. An implementation elsewhere could answer anything. Store stays object-safe (Arc<dyn Store + Send + Sync>). Even a complete implementation that delegates every method to a PgStore is refused (E0277: the private supertrait is not implemented; tests/sealed.rs checks that this is the only error):

ⓘ
use std::borrow::Cow;
use datumesh_core::{Cell, Scalar};
use datumesh_core::Slice;
use datumesh_store::{Binding, Namespace, PgStore, Resolver, Result, SliceMember, SliceValue, Store, Version};

struct Wrapper(PgStore);
impl Resolver for Wrapper {
    fn descriptor(&self, h: &str) -> Option<Cow<'_, [u8]>> { self.0.descriptor(h) }
    fn receipt(&self, h: &str) -> Option<Cow<'_, [u8]>> { self.0.receipt(h) }
    fn evaluate(&self, c: &Cell, a: &str) -> Option<Scalar> { self.0.evaluate(c, a) }
    fn manifest(&self, e: &str) -> Option<Cow<'_, [u8]>> { self.0.manifest(e) }
}
impl Store for Wrapper {
    fn put_descriptor(&self, b: &[u8]) -> Result<String> { self.0.put_descriptor(b) }
    fn put_receipt(&self, b: &[u8]) -> Result<String> { self.0.put_receipt(b) }
    fn put_blob(&self, b: &[u8]) -> Result<String> { self.0.put_blob(b) }
    fn blob(&self, s: &str) -> Result<Option<Cow<'_, [u8]>>> { self.0.blob(s) }
    fn put_version(&self, c: &str, t: &str, r: &str) -> Result<()> { self.0.put_version(c, t, r) }
    fn version_asof(&self, c: &str, a: &str) -> Result<Option<Version>> { self.0.version_asof(c, a) }
    fn versions(&self, c: &str, f: &str, t: &str) -> Result<Vec<Version>> { self.0.versions(c, f, t) }
    fn latest(&self, c: &str) -> Result<Option<Version>> { self.0.latest(c) }
    fn dependents(&self, r: &str) -> Result<Vec<String>> { self.0.dependents(r) }
    fn inputs(&self, r: &str) -> Result<Vec<String>> { self.0.inputs(r) }
    fn put_namespace(&self, h: &str, k: &[u8], v: &str) -> Result<()> { self.0.put_namespace(h, k, v) }
    fn namespace(&self, h: &str) -> Result<Option<Namespace>> { self.0.namespace(h) }
    fn bind_name(&self, n: &str, f: &str, t: &str) -> Result<()> { self.0.bind_name(n, f, t) }
    fn resolve_name(&self, n: &str, a: &str) -> Result<Option<String>> { self.0.resolve_name(n, a) }
    fn resolve_binding(&self, n: &str, a: &str) -> Result<Option<Binding>> { self.0.resolve_binding(n, a) }
    fn put_computed(&self, c: &str, t: &str, r: &str) -> Result<()> { self.0.put_computed(c, t, r) }
    fn computed_asof(&self, c: &str, a: &str) -> Result<Option<Version>> { self.0.computed_asof(c, a) }
    fn stored_asof(&self, c: &str, a: &str) -> Result<Option<Version>> { self.0.stored_asof(c, a) }
    fn cell_dependents(&self, c: &str) -> Result<Vec<String>> { self.0.cell_dependents(c) }
    fn put_manifest(&self, b: &[u8]) -> Result<String> { self.0.put_manifest(b) }
    fn member_manifests(&self, r: &str) -> Result<Vec<String>> { self.0.member_manifests(r) }
    fn slice_entries(&self, r: &str) -> Result<Vec<String>> { self.0.slice_entries(r) }
    fn slice_dependents(&self, e: &str) -> Result<Vec<String>> { self.0.slice_dependents(e) }
    fn slice_members(&self, s: &Slice, a: &str) -> Result<Vec<SliceMember>> { self.0.slice_members(s, a) }
    fn versions_between(&self, c: &str, f: &str, t: &str, a: &str) -> Result<Vec<SliceMember>> { self.0.versions_between(c, f, t, a) }
    fn slice_values(&self, s: &Slice, a: &str) -> Result<Vec<SliceValue>> { self.0.slice_values(s, a) }
    fn slice_changed_after(&self, s: &Slice, a: &str) -> Result<bool> { self.0.slice_changed_after(s, a) }
}

Required Methods§

Source

fn put_descriptor(&self, bytes: &[u8]) -> Result<String>

Stores a descriptor (checked and canonicalised by the core); returns its function hash. Idempotent.

Source

fn put_receipt(&self, bytes: &[u8]) -> Result<String>

Stores a receipt that verifies (SPEC 10.1 steps 1-6) against the key document stored for its signer host with put_namespace, in canonical form, with an edge to each of its inputs; returns its hash. An input that is a slice entry (slice:<slice id>:<members hash>, since 0.3.1) is recorded as such (slice_entries); its manifest need not be stored, before or after (it is needed only to recompute, SPEC 10.1 step 7.5). The receipt’s cell is indexed by its typed arguments (slice_members). A receipt that does not verify is refused with verify’s code (no key document for the host: E_KEY_UNAVAILABLE). Idempotent: bytes whose canonical form is the stored copy return its hash without checking the signature again (it verified when stored), even if the key has since been revoked. Other bytes with a stored hash are verified first, then refused as Error::Conflict.

Source

fn put_blob(&self, bytes: &[u8]) -> Result<String>

Stores blob content; returns its SHA-256 (lowercase hex). Idempotent.

Source

fn blob(&self, sha256: &str) -> Result<Option<Cow<'_, [u8]>>>

Blob content by SHA-256.

Source

fn put_version(&self, cell_id: &str, tx: &str, receipt_hash: &str) -> Result<()>

Appends a version: from tx on, cell_id has the value of receipt receipt_hash, which must be stored, of that cell and at that tx. tx must be later than the cell’s latest version (Error::NotLater).

Source

fn version_asof(&self, cell_id: &str, asof: &str) -> Result<Option<Version>>

The cell’s latest version with tx <= asof.

Source

fn versions(&self, cell_id: &str, from: &str, to: &str) -> Result<Vec<Version>>

The cell’s versions with from <= tx <= to, in tx order.

Source

fn latest(&self, cell_id: &str) -> Result<Option<Version>>

The cell’s latest version.

Source

fn dependents(&self, receipt_hash: &str) -> Result<Vec<String>>

The stored receipts that list receipt_hash among their inputs, by hash. Only as an input of its own: a receipt read as a member of a slice is found through its manifests (member_manifests, then slice_dependents).

Source

fn inputs(&self, receipt_hash: &str) -> Result<Vec<String>>

The inputs of a stored receipt that are receipt hashes (whether or not they are stored). Its slice entries are slice_entries.

Source

fn put_namespace( &self, host: &str, keydoc_bytes: &[u8], validated_at: &str, ) -> Result<()>

Records a host’s key document, checked as a 200 response for that host would be (SPEC 9.2, 9.3), validated at validated_at. Re-validation replaces the document; a validated_at earlier than the recorded one is Error::NotLater. Receipts already stored are not re-checked: they verified when they were stored (and putting one again stays idempotent).

Source

fn namespace(&self, host: &str) -> Result<Option<Namespace>>

A host’s recorded key document.

Source

fn bind_name(&self, fn_name: &str, fn_hash: &str, tx: &str) -> Result<()>

Appends a binding: from tx on, the fully qualified function name fn_name means fn_hash, whose descriptor must be stored. tx must be later than the name’s latest binding (Error::NotLater).

Source

fn resolve_name(&self, fn_name: &str, asof: &str) -> Result<Option<String>>

The function hash fn_name meant as of asof: the hash of resolve_binding’s binding.

Source

fn resolve_binding(&self, fn_name: &str, asof: &str) -> Result<Option<Binding>>

The binding of fn_name that answers as of asof: the one with the latest tx <= asof, with its function hash and its tx, when it began; None before the first. A name bound again to a hash it meant before (even the hash of the binding before it) begins again: the later binding’s tx. Since 0.3.0.

Source

fn put_computed( &self, cell_id: &str, tx: &str, receipt_hash: &str, ) -> Result<()>

Records that receipt_hash (stored, a receipt of cell_id at tx) is a computed version of the cell. Insert-only, in any order (an older version may be added after a newer one): tx need not be later than anything. The version’s asof is the receipt’s. Idempotent for the same (cell_id, tx, asof, receipt_hash); another receipt for an existing (cell_id, tx, asof) is Error::Conflict (its hash is the receipt refused) and the stored one is kept. The receipt is checked as for put_version: Error::NotFound when it is not stored, Error::Mismatch when it is of another cell or at another tx. Since 0.2.0.

Source

fn computed_asof(&self, cell_id: &str, asof: &str) -> Result<Option<Version>>

The computed version that answers as of asof: the one with the greatest asof <= asof (between equal asof, the greatest tx), or None. Since 0.2.0.

Source

fn stored_asof(&self, cell_id: &str, asof: &str) -> Result<Option<Version>>

The stored version that answers as of asof: the latest version (by tx) with tx <= asof whose receipt’s asof is also <= asof, or None. A version whose receipt is late-signed (asof later than tx) answers only from its asof on; until then the version before it answers. (version_asof keeps its tx-only meaning.) Since 0.2.0.

Source

fn cell_dependents(&self, cell_id: &str) -> Result<Vec<String>>

The cells that read cell_id: the cell ids of the stored receipts that list, among their inputs, any stored receipt of cell_id (lineage: edges joined to receipts), or (since 0.3.1) a slice entry whose stored manifest lists one as a member. Ascending, each once. Since 0.2.0.

Source

fn put_manifest(&self, bytes: &[u8]) -> Result<String>

Stores a manifest (SPEC 15.13), {"members": [...], "slice": {...}}: parsed strictly and checked by the core (Manifest::from_json: structure, members, their order and limit, the slice object), kept in canonical form under its entry slice:<slice id>:<members hash>, which it returns, and recorded for each member (member_manifests). The members need not be stored. Idempotent; insert-only (the entry is a hash of the content, so a stored entry always has these bytes). Served by manifest. Since 0.3.1.

Source

fn member_manifests(&self, receipt_hash: &str) -> Result<Vec<String>>

The entries of the stored manifests that list receipt_hash among their members, ascending: from a member, the slices it was read in (then slice_dependents). Since 0.3.1.

Source

fn slice_entries(&self, receipt_hash: &str) -> Result<Vec<String>>

The slice entries among the inputs of a stored receipt, ascending. Since 0.3.1.

Source

fn slice_dependents(&self, entry: &str) -> Result<Vec<String>>

The stored receipts whose inputs list the slice entry entry, by hash, ascending. An entry is slice: and two 64-digit hashes (E_CANON_HEX otherwise). Since 0.3.1.

Source

fn slice_members(&self, slice: &Slice, asof: &str) -> Result<Vec<SliceMember>>

The members of slice as of asof (SPEC 15.13), with the stored version of each that answers as of asof and its receipt’s bytes.

For a slice of cells: the cells of the slice’s function (its fn_hash, ns and fn, with the same argument names) whose bound arguments are the same typed scalar, whose ranged arguments are of the range’s type and within it (lo <= v <= hi, inclusive, in the type’s order: numbers as exact decimals, dates and instants chronologically, strings by code point; lo after hi is empty), any value for an open argument, and that have a stored version answering as of asof: as stored_asof, the latest version with tx <= asof whose receipt’s asof <= asof (so a late-signed version is not a member’s answer before its asof, and a correction replaces a member’s version from its asof on). Computed versions are not members. In key order: by the open and ranged arguments in ascending name order, each in its type’s order (false before true; blobs as text); the cell id last, for two cells whose key arguments are of different types.

For a version slice {"cell", "from", "to"}: versions_between of its cell. Empty when nothing matches. Since 0.3.1.

Source

fn versions_between( &self, cell_id: &str, from: &str, to: &str, asof: &str, ) -> Result<Vec<SliceMember>>

The stored versions of cell_id with from <= tx <= to that answer as of asof (tx <= asof and the receipt’s asof <= asof), ascending by tx, each with its receipt’s bytes: SPEC 15.13’s version slice. Empty when from is after to. Since 0.3.1.

Source

fn slice_values(&self, slice: &Slice, asof: &str) -> Result<Vec<SliceValue>>

The members slice_members gives, in its order and by its answering rule, each as its version, its receipt’s typed value and its cell (with its arguments), without the receipt’s bytes (the value is a stored column of the receipt and the cell comes from the typed-argument index, neither parsed per call). Since 0.3.2.

Source

fn slice_changed_after(&self, slice: &Slice, asof: &str) -> Result<bool>

Whether the members of slice, or their versions, may answer differently as of some time after asof: whether a cell matching the slice has a stored version whose receipt’s asof is after asof (its tx is never later than that), for a version slice one with tx in [from, to]. false means slice_members (and slice_values) give the same answer as of every time from asof on, until a version is stored with an asof after it; true may be conservative (a late-signed version superseded before its asof never answers). Index scans only, whatever the slice’s size: two bounded probes (at most 10,001 entries each) choose whether to walk the function’s receipts with an asof after asof or the slice’s candidate cells, whichever is fewer, and one query walks it, stopping at the first match. Since 0.3.2.

Provided Methods§

Source

fn computed_asof_with_receipt( &self, cell_id: &str, asof: &str, ) -> Result<Option<(Version, Cow<'_, [u8]>)>>

computed_asof and the bytes of the version’s receipt (as receipt returns them), which is what a caller reads next. The default asks for the two in turn (a receipt that cannot be read then is Error::NotFound); PgStore answers both with one query. Since 0.2.0.

Source

fn stored_asof_with_receipt( &self, cell_id: &str, asof: &str, ) -> Result<Option<(Version, Cow<'_, [u8]>)>>

stored_asof and the bytes of the version’s receipt, as computed_asof_with_receipt does. Since 0.2.0.

Dyn Compatibility§

This trait is dyn compatible.

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

Implementors§