Skip to main content

Document

Trait Document 

Source
pub trait Document:
    Serialize
    + DeserializeOwned
    + 'static {
    const COLLECTION: &'static str;
    const VERSION: u32;

    // Provided methods
    fn migrate(_dynamic: Dynamic, from_version: u32) -> Result<Self> { ... }
    fn historical_schemas() -> Vec<(u32, DynamicSchema)> { ... }
    fn indexes() -> Vec<IndexSpec> { ... }
}
Expand description

The trait every user document type implements.

Document types are serde::Serialize + DeserializeOwned so they round-trip through postcard. Each implementation provides two associated constants:

  • COLLECTION — the collection name under which records of this type are stored. The catalog resolves it to a numeric collection_id at registration time; the codec takes that id as an argument to encode/decode.
  • VERSION — the type’s schema version. Stored in every record’s header; the decoder routes a stored- version mismatch through Document::migrate.

Document is 'static so type-erased catalog rows can carry the collection name as &'static str. M5 ships hand-impls; M9 introduces a #[derive(obj::Document)] proc macro.

Required Associated Constants§

Source

const COLLECTION: &'static str

The collection name this document type stores into.

Must be a stable, application-chosen identifier. The catalog resolves it to a collection_id on first registration; subsequent opens reuse the existing id.

Source

const VERSION: u32

The schema version of this Document implementation.

Bump on any breaking change (added/removed/renamed fields, changed semantics). The decoder enforces:

Provided Methods§

Source

fn migrate(_dynamic: Dynamic, from_version: u32) -> Result<Self>

Transform an older stored record into Self.

The codec calls migrate when a stored record’s type_version is strictly less than VERSION. dynamic is a structured Dynamic view of the older record — the codec walks the on-disk payload through the schema registered for from_version (see historical_schemas) and hands the resulting map-shaped Dynamic to this method. Concrete overrides read the fields they care about with Dynamic::get / Dynamic::get_str / Dynamic::deserialize and construct the target Self.

from_version is the on-disk type_version — always < Self::VERSION when this is invoked by the codec.

§Default body

Returns Error::SchemaMigrationNotImplemented. Real types override this method to handle older versions.

§Errors

User overrides MAY return any Error variant. The default returns Error::SchemaMigrationNotImplemented.

Source

fn historical_schemas() -> Vec<(u32, DynamicSchema)>

Schemas for stored records of OLDER type_versions than VERSION.

Returns a list of (version, schema) pairs sorted strictly ascending by version. The codec consults this list whenever it observes header.type_version < Self::VERSION:

  1. Look up the matching version.
  2. Walk the on-disk payload bytes through Dynamic::from_postcard_bytes using the registered schema.
  3. Hand the resulting structured Dynamic to migrate along with the stored version.

A miss (no entry for the stored version) surfaces as Error::SchemaNotRegistered. The default body returns an empty list — a Document with no historical_schemas() cannot migrate any older payload.

§Ordering

The returned slice MUST be sorted strictly ascending by version. The codec debug-asserts on read; out-of-order entries are a programming bug.

§Power-of-ten posture
  • Rule 9. Static dispatch — concrete Document implementations return their own Vec<(u32, DynamicSchema)>; the codec never reaches for a dyn Trait.
  • Rule 7. Empty default is intentional — a Document that has never been versioned cannot have historical schemas.
Source

fn indexes() -> Vec<IndexSpec>

Declared secondary indexes for this Document type.

Default body returns the empty vector — no indexes. Override to declare per-collection indexes; the catalog reconciler (M7 #57) compares this list against the catalog’s stored descriptors on the FIRST WriteTxn::collection::<T>() call per process per collection and:

  • declares specs absent from the catalog,
  • flips active descriptors absent from this list to DroppedPending,
  • leaves unchanged matches alone (idempotent).

The reconciler runs inside the user’s WAL transaction so a rolled-back txn leaves the catalog clean.

&self is intentionally not taken — indexes are a type-level property of the Document, not a per-instance one.

Dyn Compatibility§

This trait is not dyn compatible.

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

Implementors§