Skip to content

fix: FusedCodecPipeline falls back to async path for sharded arrays with async-only inner codecs#4179

Open
d-v-b wants to merge 8 commits into
zarr-developers:mainfrom
d-v-b:fix/fused-pipeline-async-inner-codecs
Open

fix: FusedCodecPipeline falls back to async path for sharded arrays with async-only inner codecs#4179
d-v-b wants to merge 8 commits into
zarr-developers:mainfrom
d-v-b:fix/fused-pipeline-async-inner-codecs

Conversation

@d-v-b

@d-v-b d-v-b commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds a private method to the sharding codec to allow it to report whether the members of its codecs attributes support synchronous execution. I think this is an unfortunate move, and we should more formally approach the sync vs async nature of codecs. But that requires new codec classes, which is a lot of work. Until then, this change is sufficient to avoid a confusing error at chunk encode / decode time.

closes #4178

The original PR by claude is here: d-v-b#237

For reviewers

[What would you most value a second look at? What are you already confident in? For a refactor, say whether behavior is meant to be unchanged.]

Author attestation

  • I am a human, these are my changes, and I have reviewed and understood every change and can explain why each is correct.

TODO

  • Add unit tests and/or doctests in docstrings
  • Add docstrings and API docs for any new/modified user-facing classes and functions
  • New/modified features documented in docs/user-guide/*.md
  • Changes documented as a new file in changes/
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

d-v-b added 5 commits July 14, 2026 13:25
* fix: byte-order handling for structured dtypes in the bytes codec

The bytes codec neither byte-swapped structured-dtype fields to its
configured endian on encode (numpy reports byteorder '|' for void
dtypes, so the top-level byteorder comparison never detected a
mismatch) nor honored its endian when decoding, silently corrupting
any structured data whose field byte order differed from the stored
one (e.g. virtual references to external big-endian data).

Encode now detects byte-order mismatches by comparing full dtypes via
newbyteorder, and decode reinterprets raw bytes in the stored byte
order before converting to the data type's declared byte order, so the
stored layout (codec state) and the in-memory layout (array data type)
are independent.

Closes zarr-developers#4141

Assisted-by: ClaudeCode:claude-fable-5

* test: fold structured byte-order cases into existing bytes codec tests

Extend test_endian's parametrization with structured dtypes and
test_bytes_codec_sync_roundtrip with endian/dtype parametrization plus
stored-layout and decoded-dtype assertions, instead of adding parallel
test functions for the same properties.

Assisted-by: ClaudeCode:claude-fable-5

* refactor: rename stored_dtype to view_dtype in BytesCodec decode

The variable is the dtype used to view the raw chunk bytes (byte order
from the codec's endian configuration), not a property of the stored
data or of the returned buffer, which always carries the array's
declared dtype.

Assisted-by: ClaudeCode:claude-fable-5

* docs: note that the decode-side byte-order conversion copies the chunk

Assisted-by: ClaudeCode:claude-fable-5
…async-only inner codecs

Under the opt-in FusedCodecPipeline, a sharded array whose inner codec
chain contained a codec implementing only the async interface (no
SupportsSyncCodec) raised TypeError on both read and write:
ShardingCodec structurally satisfies SupportsSyncCodec, so the pipeline
built a top-level sync transform and took the sync fast path, which dove
into the sharding codec's sync shard paths and crashed constructing the
inner ChunkTransform. The default BatchedCodecPipeline handled the same
configuration fine.

Fix: sync capability is now a dynamic query (_codec_supports_sync) —
structural SupportsSyncCodec membership plus an optional _sync_capable
opt-out. ShardingCodec reports _sync_capable=False when its inner or
index codec chain is not fully sync-capable (recursively, so nested
sharding propagates). ChunkTransform consults the query, so its
construction raises for such chains and the pipeline's existing
top-level guard (evolve_from_array_spec -> sync_transform=None) now
declines the sync fast path, routing reads through the async partial
shard decode and writes through the async fallback — the same graceful
degradation already used for async-only top-level codecs and non-sync
stores. All-sync chains still build the sync transform and keep the
fast path.

Assisted-by: ClaudeCode:claude-fable-5
@github-actions github-actions Bot added the needs release notes Automatically applied to PRs which haven't added release notes label Jul 22, 2026
@d-v-b
d-v-b requested a review from ilan-gold July 22, 2026 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs release notes Automatically applied to PRs which haven't added release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unergonomic error for when using the FusedCodecPipeline + Sharding with an inner async-only codec

1 participant