manifests
blobmap.manifests ¶
Where manifests live: a bucket you own, at a path mirroring the data.
That mirroring is what makes this work for stores you must not alter --
nothing is ever written into the source. Inline _blob_root attributes, where
a store owner sets them, are an input to the partitioner; the manifest is
always the resolved output and the single authority for lookup.
Manifests are per scope, not per blob, so a PB is hundreds to a few thousand
small JSON objects. load_all is a LIST plus parallel GETs, which is why
blobtier needs no database at startup.
Conflict ¶
Bases: RuntimeError
Someone else wrote this key since we read it.
Raised when a conditional write fails its precondition. This turns two jobs partitioning the same scope into an error you can retry rather than a silent last-writer-wins.
Stored
dataclass
¶
Stored(manifest: Manifest, etag: str | None)
ManifestStore ¶
ManifestStore(store: Store, prefix: str = '')
Read and write manifests in a bucket you own.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store
|
Store
|
A storage handle for the manifest bucket, not the data. |
required |
prefix
|
str
|
Optional prefix within that bucket, if manifests share it with something else. |
''
|
Example
from obstore.store import MemoryStore from blobmap.model import Blob, Manifest manifests = ManifestStore(MemoryStore(), "blobmap") manifests.key("cordex/a.zarr") 'blobmap/cordex/a.zarr/manifest.json' _ = manifests.write(Manifest("cordex/a.zarr", ... (Blob("b", ("x",)),), ()), ... expect_absent=True) manifests.read("cordex/a.zarr").manifest.scope 'cordex/a.zarr'
Source code in src/blobmap/manifests.py
64 65 66 | |
key ¶
key(scope: str) -> str
Get the object key a scope's manifest lives at.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
str
|
Data prefix, such as |
required |
Returns:
| Type | Description |
|---|---|
str
|
The mirrored key in the manifest bucket. |
Source code in src/blobmap/manifests.py
68 69 70 71 72 73 74 75 76 77 78 | |
read ¶
read(scope: str) -> Stored | None
Read one manifest.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
str
|
Data prefix whose manifest to fetch. |
required |
Returns:
| Type | Description |
|---|---|
Stored | None
|
A |
Stored | None
|
has never been partitioned. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the object exists but is not a manifest this version can read. |
Source code in src/blobmap/manifests.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | |
scopes ¶
scopes() -> Iterator[str]
Every scope that has a manifest.
Yields:
| Type | Description |
|---|---|
str
|
Scope prefixes, derived from the manifest keys. One LIST, no |
str
|
GETs, so this is cheap enough to call on every scan. |
Source code in src/blobmap/manifests.py
103 104 105 106 107 108 109 110 111 112 113 114 115 | |
load_all ¶
load_all(workers: int = 16) -> list[Manifest]
Load every manifest, for building a Trie.
This is everything a resolving service needs at startup, with no database on the path. Manifests are per scope rather than per blob, so a petabyte is hundreds to a few thousand small JSON objects: one LIST plus parallel GETs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
workers
|
int
|
Thread pool size for the GETs. |
16
|
Returns:
| Type | Description |
|---|---|
list[Manifest]
|
Every valid manifest. A manifest whose declared scope does not |
list[Manifest]
|
match its location is skipped with a warning, since it would |
list[Manifest]
|
otherwise claim keys it has no business claiming. |
Source code in src/blobmap/manifests.py
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | |
write ¶
write(
manifest: Manifest,
*,
etag: str | None = None,
expect_absent: bool = False
) -> str | None
Validate and write a manifest.
Validation happens before every write, because a malformed manifest sitting in object storage is far more expensive than a failed partition run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
manifest
|
Manifest
|
The manifest to store. Its scope determines the key. |
required |
etag
|
str | None
|
Etag from a prior read, requiring the object to be unchanged. |
None
|
expect_absent
|
bool
|
Require that no manifest exists yet. |
False
|
Returns:
| Type | Description |
|---|---|
str | None
|
The new etag, or |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the manifest fails validation. Nothing is written. |
Conflict
|
If a conditional write fails its precondition. |
Source code in src/blobmap/manifests.py
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | |