Expand description
Which implementation of each trait a store is built on. One selector,
read once at construction, never per operation — arms::StoreConfig.
Which implementation of each trait a store is built on — one selector,
read once, never per operation.
Three traits in this crate have more than one implementation, every one of them written and benchmarked (PLAN §7, §8):
| trait | arms | what varies |
|---|---|---|
ArchiveWrite | WriterArm::Fast / Safe / Uring | the durability contract, and nothing else |
ObjectIndex | IndexArm::OneTableFourColumns / FourTables / PackedPayload | the payload layout behind the same stree |
[Gc] | GcArm::NewGeneration / CompactInPlace | whether the old generation survives until the new one is proven |
Until this module existed, GitStore named one of each by hand, so none of
them could be A/B’d through a server or a bench without editing the source.
StoreConfig is that choice made data.
§The default is the shipping combination and it did not move
StoreConfig::DEFAULT is SafeWriter + ObjectReadStack<OneTableFourColumns>
NewGeneration, which is exactly whatGitStore::openbuilt before this module and is exactly what it builds now.openandopen_withdo not read the environment at all — an operator who exports a variable cannot silently change the durability contract under a caller that never asked for a selector. Choosing an arm is something a caller does on purpose, throughopen_with_armsoropen_from_env.
§Read once, at construction. Never per operation.
Every getenv this crate performs goes through [read_env] and happens
either inside StoreConfig::from_env (which a store calls once, while
it is being opened — the three arms and, since 2026-08-21, the cache ceiling
with them) or behind a process-wide OnceLock for the knobs that never vary
between two stores in one process. A std::env::var in a copy loop would be
one syscall per object served, and that exact defect was found and fixed in
gunnar the day before this was written. It is not a style rule here, it is
asserted: env_reads_here counts every read this module makes on the
calling thread, and
the_selector_is_read_once_at_construction_and_never_per_operation pushes
and serves a whole pack across an unchanged counter.
Five reads at construction — three arms, the cache ceiling and the explode
policy — and zero per operation. env_reads is the same count
process-wide; see env_reads_here for why the guard asserts on the
thread-local one. The complete roster of keys is ALL_ENV.
§The names, so an operator can type them
ZNIPPY_GIT_WRITER = fast | safe | uring (default: safe)
ZNIPPY_GIT_INDEX = one-table | four-tables | packed (default: one-table)
ZNIPPY_GIT_GC = new-generation | in-place (default: new-generation)
ZNIPPY_GIT_REDB_CACHE_BYTES = <bytes> (default: 67108864)
ZNIPPY_GIT_EXPLODE = off | graph | full (default: see exploded_arrow.rs)
ZNIPPY_GIT_BOUNDARY_DELTA = 0 | off | false to disable (default: on)
ZNIPPY_GIT_REACH_COMMITS = <commits> (default: 512)
ZNIPPY_GIT_EMIT_WORKERS = <workers>, 0 = all cores (default: 4)The first four are per store and are what StoreConfig holds and prints;
the last four are per process. ALL_ENV is all eight, and a consumer that
has to carry any of them across a boundary asserts its list against it.
An unset variable takes the default. A variable set to something else is an error, named and listing what is accepted — a typo that silently fell back to the default would make an operator believe a measurement came from an arm that never ran, which is worse than a failed open.
⚠ The fourth one is not an arm, and it is the only variable here that
GitStore::open reads. It selects no
implementation and changes no contract — it is a memory ceiling, and redb’s
own default for it is 1 GiB per database. See redb_cache_bytes.
Structs§
- Store
Config - One implementation of each trait, chosen.
Enums§
- GcArm
- Which
GcGitOps::gcruns as its third step, after reachability and after the dead index rows are dropped. - Index
Arm - Which payload layout sits behind the read stack’s
stree. - Writer
Arm - Which
ArchiveWritethe push path appends through.
Constants§
- ALL_ENV
- Every environment variable this crate reads outside its tests, in one place, so a consumer that carries them across a process or container boundary can assert its list against this one instead of against a count it remembers.
- DEFAULT_
REDB_ CACHE_ BYTES - 64 MiB. See
redb_cache_bytesfor how that number was arrived at. - ENV_
BOUNDARY_ DELTA - Environment variable switching the boundary re-delta off for an A/B
(
0/off/false; anything else, or unset, is on). Read once per process bycrate::delta::enabled. - ENV_
EMIT_ WORKERS - Environment variable setting the phase-1 emit workers per request. An
operator knob, not an arm — see
emit_workersingit_ops.rs. Read once per process. - ENV_
EXPLODE - Environment variable naming the explode policy of the
objects.explodedtable (off·graph·full). Read once per store open byExplodePolicy::from_env. - ENV_GC
- Environment variable naming the
Gcarm. - ENV_
INDEX - Environment variable naming the
ObjectIndexarm. - ENV_
REACH_ COMMITS - Environment variable capping the live reachability walk in commits. An
operator knob, not an arm — see
live_reach_policyingit_ops.rs. Read once per process. - ENV_
REDB_ CACHE - Environment variable bounding redb’s page cache, in bytes. See
redb_cache_bytes. - ENV_
WRITER - Environment variable naming the
ArchiveWritearm.
Functions§
- env_
reads getenvcalls this module has made since the process started.- env_
reads_ here - The same count, for the calling thread only.
- redb_
cache_ bytes - The page-cache ceiling for one repository’s two redb databases, in bytes.