Expand description
A PostgreSQL store for Datumesh: function descriptors, receipts,
blobs, versions of cells over transaction time, lineage, namespaces and function names.
PgStore implements Store, and through it datumesh_core’s Resolver, so
datumesh_core::verify can recompute receipts of stored cells from it.
The API is synchronous (the postgres driver, a small connection pool). Async callers run
it on a blocking thread, e.g. tokio::task::spawn_blocking.
What is stored, and how:
- Descriptors are checked by the core (
Descriptor::from_json) and stored in canonical form (JCS) under their hash. Receipts are verified (datumesh_core::verify, SPEC 10.1 steps 1-6) against the key document stored for their signer host, so nothing unverified enters the store, and are stored canonical under their hash. Storing the same thing twice stores it once. A second, different valid signature over the same payload (possible only with a randomised signer: the payload names the key, so a rotated key gives a new hash) is refused (Error::Conflict) and the stored receipt kept. - Blobs are stored in the database, under the SHA-256 of their content.
- Versions: from transaction time
txon, cellcell_idhas the value of a receipt. Append-only and in tx order per cell, enforced by the database (triggers) as well as byStore::put_version, which also checks that the receipt is stored and is of that cell at that tx. - Lineage:
put_receiptrecords an edge to each of the receipt’sinputs, held or not. - Namespaces: a host’s key document (checked as SPEC 9.2 requires), with when it was validated. Store it before the host’s receipts. Replacing it later (a key revoked or dropped) does not touch receipts already stored: they verified when they were stored, and putting one of them again is still idempotent.
- Names: which function hash a fully qualified function name meant from a transaction time on. Append-only, like versions.
Instants are compared as text (fixed width, COLLATE "C"), which is exact; each is also
stored as timestamptz, which round-trips every instant of the specification exactly.
Every Store method returns a Result: a malformed argument is Error::Invalid with
the core’s code, a database failure Error::Database. The Resolver methods keep the
core’s Option signatures; there a failure is logged with tracing (target
datumesh_store) and answered None, which verify reports as unavailable.
The schema comes from migrate::apply (the datumesh-store migrate command).
Re-exports§
pub use postgres;
Modules§
- migrate
- Schema migrations: plain SQL files (
migrations/*.sql, embedded), applied in order with a tracking table, and a schema check that compares the live database’s catalog with the catalog the migrations produce in a scratch database.
Structs§
- Namespace
- A namespace’s host and its key document.
- PgStore
- The store on PostgreSQL, with a connection pool.
Send + Sync: share one per process (behind anArc); each call checks a connection out for its duration. - Pool
Options - How the pool behaves.
- Version
- A version of a cell: from transaction time
txon, the cell’s value is that of the receiptreceipt_hash.
Enums§
Traits§
- Resolver
- What step 7 of SPEC 10.1 obtains: the descriptor, the input receipts and the evaluated
value. This crate evaluates no functions and fetches nothing; the caller supplies a
resolver, and
verifyasks it only for what step 7 reaches for the receipt at hand: - Store
- A Datumesh store: a
Resolverthat can also be written to.