Skip to content

Correct metadata emission for generation > 1 and appending buffers - #30

Merged
eagmon merged 1 commit into
mainfrom
fix/xarray-metadata-emission
Aug 21, 2026
Merged

Correct metadata emission for generation > 1 and appending buffers#30
eagmon merged 1 commit into
mainfrom
fix/xarray-metadata-emission

Conversation

@eagmon

@eagmon eagmon commented Aug 21, 2026

Copy link
Copy Markdown
Member

Ports the substantive fixes from vEcoli PR #414 commit f62a183a ("Fixes to Xarray/Zarr metadata emission"), reconciled against viva-emitters' diverged writer/transducer.

Two bugs (both invisible on a single-buffer, generation-1 run)

1. generation > 1 arrays got Zarr's default chunking. Coordinate-data emission and encoding computation were coupled under one flag (include_static, true only for the first buffer of generation 1). So every generation > 1 partition's freshly created arrays were written with no encoding and fell back to default chunks.

Fix: decouple into two predicates on AsyncBufferWriter

  • is_1st_buf_in_lineage gates the lineage-shared coordinate data (written once),
  • is_1st_buf_in_generation gates encoding computation (recomputed on the first buffer of every generation), so gen>1 arrays get their intended b * buf_size chunks.

2. Child-variable unit attributes were mis-keyed and erased. The unit was stored under the per-generation gen=N key instead of the variable's own name; and appending buffers reassembled the child node from data variables only (no attrs), so dump_to_store erased the units. Fix: VariableSpec.attr_name keys the unit by variable name, and render() re-attaches child_coords[p].attrs on every appending buffer.

Mechanics

  • Split XarrayBuffer.render (returns the DataTree) from new XarrayBuffer.encodings.
  • VariableSpec.encoding takes include_coo; explicit chunks on the right of the codec union so they always win.
  • XarrayTransducer.flush derives both predicates from the writer.
  • close() keeps its num_writes > 0 guard to avoid a behavior change against viva's mark_success() num_writes = -1 sentinel.

Skipped from f62a183a: the explicit coo/var default-codec classmethods (Fix 6 — depends on zarr-internal symbols; revisit with the zarr 3.3 bump) and vEcoli-specific test changes. Fixes viva already has (single-lookup merge_attributes; alloc() invariant via check_layout) are left as-is.

Verification

tests/test_xarray_multigen_encoding.py drives two colony generations with a unit-bearing view and buffers_per_chunk=2. Verified to FAIL on the pre-fix code (time chunk 3 != 6; unit absent) and pass after. Full suite: 109 passed, 4 skipped.

Part of the PR #414 reconciliation (follows the buffer-sizing PR #29).

🤖 Generated with Claude Code

…ng buffers

Ports the substantive fixes from vEcoli PR #414 commit f62a183a, reconciled
against viva-emitters' diverged writer/transducer.

Two bugs, both invisible on a single-buffer generation-1 run:

1. generation > 1 arrays got Zarr's default chunking. Coordinate-data
   emission and *encoding* computation were coupled under one flag
   (`include_static`, true only for the first buffer of generation 1), so
   every generation > 1 partition's freshly created arrays were written with
   no encoding. Decouple into two predicates on AsyncBufferWriter:
   `is_1st_buf_in_lineage` gates the lineage-shared coordinate DATA, while
   `is_1st_buf_in_generation` gates ENCODING computation — recomputed on the
   first buffer of every generation, so gen>1 arrays get their intended
   `b * buf_size` chunks.

2. child-variable unit attributes were mis-keyed and erased. The unit was
   stored under the per-generation `gen=N` key instead of the variable's own
   name (VariableSpec.attr_name); and appending buffers reassembled the child
   node from data variables only (no attrs), so dump_to_store erased the
   units the first buffer wrote. render() now re-attaches
   child_coords[p].attrs on every appending buffer.

Mechanics: split XarrayBuffer.render (returns the DataTree) from a new
XarrayBuffer.encodings; VariableSpec.encoding takes include_coo and puts
explicit chunks on the right of the codec union so they always win.
XarrayTransducer.flush derives both predicates from the writer instead of
taking include_static. close() keeps its `num_writes > 0` guard to avoid a
behavior change against viva's mark_success() num_writes=-1 sentinel.

Skipped from f62a183a: the explicit coo/var default-codec classmethods (Fix
6, depends on zarr-internal symbols) and vEcoli-specific test changes. Fixes
already present in viva (single-lookup merge_attributes; alloc() invariant
via check_layout) are left as-is.

New test tests/test_xarray_multigen_encoding.py drives two colony
generations with a unit-bearing view and buffers_per_chunk=2; verified to
FAIL on the pre-fix code (time chunk 3 != 6; unit absent) and pass after.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@eagmon
eagmon merged commit a794bce into main Aug 21, 2026
1 check passed
@eagmon
eagmon deleted the fix/xarray-metadata-emission branch August 21, 2026 07:06
@eagmon eagmon mentioned this pull request Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant