Skip to main content

Module odb

Module odb 

Source
Expand description

The substrate object front (wave 7): alkblobs as the git-object store under the derivation family, and the sync Find the pack pipelines consume (gix_object::Find + gix_object::Exists, gix_pack::Find) — substrate.md §object storage; ADR-019 §1; the POC-O SubstrateOdb pattern.

§The derivation family (alkblobs ADR-018)

Loose objects live under the git-object derivation family (registry byte 0x03; 0x04 is the sha256 member, registered but untouched here — OQ-05 keeps every serving-path oid sha1). The stored preimage is git’s loose-object form — <type> <len>\0 + content, the header inside the value — so the digest is byte-identically git’s oid of the object, every kind included, and external-oid addressing is map-free: the key is [0x03] + oid bytes (oid_key), built by Key::from_bytes over the physical encoding (family-explicit, rejects-never-guesses).

The odb layer owns the header the family stores: it composes the loose form (loose_form) it puts through the known-length derivation seam (put_as(Algorithm::GitObjectSha1, len, stream) — alkblobs 0.2’s post-ADR-020 shape) and parses the header back out through gix_object::decode::loose_header on read. Verification-on- put is the oid re-derivation (the store derives the digest from the stored bytes; a put whose returned key does not re-derive to the object’s oid is rejected — corruption cannot enter), and the front re-derives on every read as well, so entries the store’s kv tier does not cover (large-tier payloads are not re-derived at open) fail the read too. stat returns the preimage length — the stored value’s length, git’s header included, never the content length (the family semantic, alkblobs ADR-018 §Decision 3).

§The Find front and the one-time construction

ObjectFront is constructed once over the store (the handle-sharing shape — backend.md §crate and feature model; ADR-004’s status clause: the retired disk-odb handle sharing is realized as this front, constructed once with per-session views). ObjectFront::session mints a per-session SessionFind: a view sharing the front’s store + runtime handles that carries its own lookup-miss slot, so one session’s failed walk cannot contaminate another’s. Clones of a view share that session’s slot (the pipeline clones the find — the core crate’s MemFind double’s sharing within one session).

MemFind is the core crate’s test-double form of this exact shape (tests/common/mod.rs). The location/entry/pack-offset (gix_pack::Find::location_by_oid, gix_pack::Find::pack_offsets_and_oid, gix_pack::Find::entry_by_location) legs answer “not in any pack”: the substrate has no packed objects — the pipeline’s FindExt blanket impls pick up the rest. No disk odb exists anywhere on the serving path (gix-odb is deliberately absent from the manifest).

A lookup miss is recorded on the view (SessionFind::missed_object) so a failed walk/count stage maps its not-found error back to the seam’s StorageError::ObjectMissing abort (ADR-004), naming the missing object rather than the want.

§The sync Find / async store bridge — owned once, in one place

gitoxide’s Find traits are sync by design; the substrate store is async. The bridge is this module’s ObjectFront::block_on (Handle::block_on against the runtime handle captured at construction) — consumed from blocking pipeline tasks (tokio::task::spawn_blocking), never from async contexts, where it panics (the POC-O panic shape, learned live; poco-findings §trait posture). Async contexts that must reach the store bridge with ObjectFront::block_in_place (block_in_place there — it parks the worker and makes block_on legal). The eventual GitPackGen/GitPackIngest impls and the liveness source consume these two postures — no consumer constructs its own Handle.

§Error model

The async legs (ObjectFront::put, ObjectFront::get, ObjectFront::stat) surface the seam’s StorageError family: backing-store failures are StorageError::Io (message-only, no engine source types — the same discipline as the other backend impls), corruption detected at the front (a header that does not parse back, a body that does not match its header, a re-derivation mismatch) is StorageError::Invalid (“structurally invalid backend state”). The sync trait layer maps those into gix_error::Error; misses stay Ok(None) — a miss is a recorded result, not an error. A non-sha1 oid (oid_key) is StorageError::Invalid: OQ-05’s rejects-never-guesses posture at the front.

Structs§

ObjectFront
The one-time object front over the substrate’s alkblobs store: the handle-sharing shape’s constructed-once half (backend.md §crate and feature model). The object pool is global, not per-repo-namespaced — repo scoping is the refs rows’ and liveness sources’ business.
SessionFind
A per-session view of the ObjectFront: the object lookup Find the pack pipelines consume, carrying the session’s lookup-miss slot (one session’s failed walk cannot leak another’s miss — mint one with ObjectFront::session). Clones share the slot, the shape the pipeline’s find.clone() calls assume within one session.

Functions§

key_to_oid
The object id behind a family key — Some only for a GitObjectSha1 key (the family the front serves; ADR-019 §1’s loose-form keying, alkblobs ADR-018); any other algorithm is None (the 0x01/0x02 blob members and the 0x04 member are not oid-addressable from here).
loose_form
The stored preimage of a git object: git’s loose-object form — <type> <len>\0 + content, the header inside the value (alkblobs ADR-018; the digest over exactly these bytes is git’s oid). The odb layer owns this composition — ObjectFront::put puts it, the read legs parse the header back out through gix_object::decode::loose_header.
oid_key
The key the derivation family derives an object’s oid to: [0x03] + the oid bytes, decoded through Key::from_bytes over the physical encoding — family-explicit, rejects-never-guesses (alkblobs ADR-018; ADR-020 §Decision 5’s external-oid shape). A non-sha1 oid is StorageError::Invalid (OQ-05: never silently re-addressed).