The zipped-store byte source: chunks read out of one archive.
This is what lets MultiLevelCachingStore cache a .zarr.zip at all. The
store used to build a URL per chunk, which an archive member does not have;
with the ChunkSource seam it just asks this for bytes, and L1/L2 keep
keying on whole chunks exactly as they do for a directory store.
Caching matters more here than for a directory store, not less. Every
member read is a Range request against the SAME URL, so a repeat read cannot
be served from the browser's HTTP cache the way a repeat GET of a per-chunk
URL can — the reader deliberately sends cache: 'no-store', because Chrome
serialises same-URL range GETs through its HTTP-cache writer lock otherwise.
The chunk cache is what makes those repeats free.
Each member costs ONE ranged GET: LuxarZipStore sizes a window from the
central directory (local header + name + extra field + slack + compressed
payload) and answers both of unzipit's serial reads — the 30-byte local
header, then the payload — from it. (A local extra field larger than the slack
costs one more GET for that member.) Opening the archive is ONE suffix GET too,
shared with the identity probe when that runs first.
The zipped-store byte source: chunks read out of one archive.
This is what lets
MultiLevelCachingStorecache a.zarr.zipat all. The store used to build a URL per chunk, which an archive member does not have; with the ChunkSource seam it just asks this for bytes, and L1/L2 keep keying on whole chunks exactly as they do for a directory store.Caching matters more here than for a directory store, not less. Every member read is a
Rangerequest against the SAME URL, so a repeat read cannot be served from the browser's HTTP cache the way a repeat GET of a per-chunk URL can — the reader deliberately sendscache: 'no-store', because Chrome serialises same-URL range GETs through its HTTP-cache writer lock otherwise. The chunk cache is what makes those repeats free.Each member costs ONE ranged GET:
LuxarZipStoresizes a window from the central directory (local header + name + extra field + slack + compressed payload) and answers both ofunzipit's serial reads — the 30-byte local header, then the payload — from it. (A local extra field larger than the slack costs one more GET for that member.) Opening the archive is ONE suffix GET too, shared with the identity probe when that runs first.