moczarr.store
Store layer: obstore-backed access to hive store roots and leaves.
One backend (obstore) by design — the walk's termination rule ("no digit children ⇒ nothing finer exists") and the debris model both lean on strongly-consistent, uncached delimiter-LIST semantics reaching this code unmediated, so a second backend would be a second correctness surface (rationale on the plan thread, espg/moczarr#1).
Leaf functions take (store_root, leaf) with leaf a store-relative
path (from :func:moczarr.convention.leaf_path or :func:walk_leaves), so
every access — local or S3 — goes through one store handle and a missing
leaf is uniformly a clean GET miss, never a backend-dependent error.
Postures, per the design's D9 discipline:
- The manifest is the bootstrap: absent reads
None, malformed raises — there is no degraded mode without it. - Cache tiers (root MOC) are tolerant: garbage reads as absent with a debug
log, and the caller degrades to :func:
walk_leaves— never wrong answers. - The commit stamp gates completeness: an unstamped or malformed-stamp leaf
is debris and reads
None. Presence requires the stamp; absence (a clean LIST/GET miss) is trustworthy on its own. - A PRESENT-but-corrupt bitmap sidecar raises (see
moczarr.coverage).
bitmap_and(store_root, leaf, aoi, *, store=None, **store_kwargs)
Exact cell-level intersection via a leaf's coverage (bitmap or full).
Reads the stamp once. encoding: "full" short-circuits to MOC
membership against the shard's own id — no sidecar GET, no expansion.
The "bitmap" path pays the one sidecar GET. None when the leaf
carries neither (box-only, debris, absent) — the caller falls back to
the box verdict. An empty array is a definitive miss: both encodings
are exact, not conservative.
Source code in src/moczarr/store.py
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | |
load_root_coverage(store_root, *, store=None, **store_kwargs)
The store-root coverage envelope, or None when unusable.
Tolerant (the root MOC is a regenerable cache): a missing object,
unparsable JSON, or an unknown spec/encoding all read as absent — with a
debug log so the degradation is discoverable — and the caller falls back
to :func:walk_leaves.
Source code in src/moczarr/store.py
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | |
open_object_store(path, *, anonymous=False, **kwargs)
Open an obstore store at path (s3://... or a local directory).
Read-only posture: a missing local directory raises FileNotFoundError
(the writer creates stores; the reader never does). anonymous=True
skips request signing for public buckets (the source.coop case);
kwargs pass through to S3Store.from_url (region=... etc.).
Source code in src/moczarr/store.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
read_commit(store_root, leaf, *, store=None, **store_kwargs)
A leaf's commit stamp, or None for debris / absent leaves.
One GET of the leaf's root zarr.json (the leaf is vanilla zarr v3 by
convention, so the root group metadata is that one object; no zarr
machinery needed to check completeness). A missing object, a missing
stamp, and a malformed (non-mapping) stamp are the same answer: not
complete. A present-but-unparsable zarr.json raises — that leaf
claims to exist and cannot be half-trusted.
Source code in src/moczarr/store.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | |
read_commits(store_root, leaves, *, store=None, concurrency=32, **store_kwargs)
Commit stamps for many leaves, batched (issue #5).
One result per input leaf, aligned by position, each with
:func:read_commit semantics — None for debris/absent, a raise for
a present-but-unparsable zarr.json. concurrency bounds the
in-flight GETs (obstore.get_async behind a semaphore); None or
1 keeps the serial per-leaf path for debugging.
Source code in src/moczarr/store.py
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | |
read_coverage_bitmap(store_root, leaf, *, coverage=None, store=None, **store_kwargs)
A leaf's exact occupied cell words from its bitmap sidecar, or None.
None for anything without a "bitmap" sidecar to read: debris, a
box-only envelope, encoding: "full" (there IS no sidecar — the shard
id is the exact MOC; :func:bitmap_and short-circuits on it), or a
missing sidecar object. A present-but-corrupt sidecar raises (decoder's
posture). The shard id comes from the leaf basename via the frozen
first-_ split; cell_order from the envelope. Pass an
already-read coverage envelope to skip the stamp GET.
Source code in src/moczarr/store.py
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | |
read_json(store, key)
GET+parse one small JSON object; None when it does not exist.
Parse errors propagate — tolerant callers wrap this per their tier's posture.
Source code in src/moczarr/store.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 | |
read_leaf_coverage(store_root, leaf, *, store=None, **store_kwargs)
A leaf's coverage envelope off its commit stamp, or None.
Source code in src/moczarr/store.py
229 230 231 232 233 | |
read_manifest(store_root, *, store=None, **store_kwargs)
The store's validated morton_hive.json; None when absent.
Loud on malformed content (bad JSON or a failed :func:parse_manifest):
the manifest is the reader's bootstrap, so garbage here is an error, not
a degradable cache.
Source code in src/moczarr/store.py
109 110 111 112 113 114 115 116 117 | |
walk_leaves(store_root, *, store=None, concurrency=None, path_grouping=1, **store_kwargs)
Yield the store-relative path of every leaf zarr — the discovery walk.
The fallback/verification path (never the hot path): one delimiter-LIST
per digit node — no digit children means nothing finer exists (LIST is
strongly consistent and object stores have no empty prefixes, so absence
is definitive). Yields stamped and debris leaves alike — completeness is
the caller's check (:func:read_commit), matching the tiered postures.
path_grouping is the manifest's digit-chunking (spec §6.1) — child
classification depends on it, so callers walking a grouped store must
pass the manifest's value (readers hold the manifest before any path
work; D10).
concurrency > 1 batches the LISTs breadth-parallel, one tree level
at a time (obstore.list_with_delimiter_async behind a semaphore).
The yielded SET is identical to the serial walk's; the ORDER may differ
(level-by-level vs depth-first) — callers sort, per the contract.
Source code in src/moczarr/store.py
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | |
warn_if_stale(store_root, shard, envelope)
O7 lazy staleness detection for one opened, commit-stamped leaf.
Call with POSITIVE evidence of a committed shard (an opened leaf with a
stamp) that the root MOC does not list. Usually benign — a run in
progress writes the root MOC only at end of run — so this warns ONCE per
store per process with the context, returns whether stale, and never
auto-walks. envelope may be None (no root MOC at all): that is
absence, not staleness, and reads False. A malformed envelope cannot
vouch for the shard and counts as stale.
Source code in src/moczarr/store.py
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | |