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§
- Object
Front - 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.
- Session
Find - 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 withObjectFront::session). Clones share the slot, the shape the pipeline’sfind.clone()calls assume within one session.
Functions§
- key_
to_ oid - The object id behind a family key —
Someonly for aGitObjectSha1key (the family the front serves; ADR-019 §1’s loose-form keying, alkblobs ADR-018); any other algorithm isNone(the0x01/0x02blob members and the0x04member 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::putputs it, the read legs parse the header back out throughgix_object::decode::loose_header. - oid_key
- The key the derivation family derives an object’s oid to:
[0x03] + the oid bytes, decoded throughKey::from_bytesover the physical encoding — family-explicit, rejects-never-guesses (alkblobs ADR-018; ADR-020 §Decision 5’s external-oid shape). A non-sha1 oid isStorageError::Invalid(OQ-05: never silently re-addressed).