Skip to content

Drop Options generic and thread signal directly#391

Merged
manzt merged 2 commits into
mainfrom
manzt/drop-options
Apr 13, 2026
Merged

Drop Options generic and thread signal directly#391
manzt merged 2 commits into
mainfrom
manzt/drop-options

Conversation

@manzt
Copy link
Copy Markdown
Owner

@manzt manzt commented Apr 13, 2026

AsyncReadable<Options> existed so stores could receive arbitrary per-call state. Auth headers, presigning context, cancellation signals, even chunk-layer concerns like caching and prefetch priority (#296, vole-core's wrapArray).

It was a catch-all for extensions that had nowhere else to live, and the cost was a pile of type magic: higher-kinded-type encoding in the store middleware system (#384), threading generic types that didn't actually provide that much type safety. (TypeScript could often bail out to any when inference broke.)

Those extensions now have proper homes. Store middleware (#384) gives transport-layer concerns (auth, presigning, request transformation) a proper extension point, and the custom fetch option on FetchStore (#388) handles the per-store cases at the callsite. Chunk-layer concerns will move to zarr.extendArray in a follow-up.

What's left is signal, which now lives properly on the (non-generic) AsyncReadable interface and can be passed directly in zarr.get and zarr.set from the caller:

// Before
interface AsyncReadable<Options = unknown> {
  get(key: AbsolutePath, opts?: Options): Promise<Uint8Array | undefined>;
}
await zarr.get(arr, null, { opts: { signal: ctl.signal } });

// After
interface AsyncReadable {
  get(key: AbsolutePath, opts?: { signal?: AbortSignal }): Promise<Uint8Array | undefined>;
}
await zarr.get(arr, null, { signal: ctl.signal });

Batched caller signals in withRangeBatching are now merged with AbortSignal.any instead of a user-supplied mergeOptions reducer. The deprecated opts?: { signal? } shape still works for one major version and is folded into the new signal via AbortSignal.any.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 13, 2026

⚠️ No Changeset found

Latest commit: c4784ce

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@manzt manzt force-pushed the manzt/drop-options branch 2 times, most recently from f2b0041 to 6f886c5 Compare April 13, 2026 01:15
@manzt manzt added the enhancement New feature or request label Apr 13, 2026
@manzt manzt force-pushed the manzt/drop-options branch from 0c6386d to a2998f9 Compare April 13, 2026 16:22
@manzt manzt force-pushed the push-krknkpkmxlrn branch from 5f1b5d0 to 3d6ae17 Compare April 13, 2026 16:22
@manzt manzt force-pushed the manzt/drop-options branch from a2998f9 to 188c71d Compare April 13, 2026 16:24
@manzt manzt force-pushed the push-krknkpkmxlrn branch from d9fff4c to bfc6d6a Compare April 13, 2026 16:33
@manzt manzt force-pushed the manzt/drop-options branch from 188c71d to 552db13 Compare April 13, 2026 16:33
Base automatically changed from push-krknkpkmxlrn to main April 13, 2026 16:44
manzt added 2 commits April 13, 2026 12:44
`AsyncReadable<Options>` existed so stores could receive arbitrary
per-call state. Auth headers, presigning context, cancellation signals,
even chunk-layer concerns like caching and prefetch priority (#296,
vole-core's `wrapArray`).

It was a catch-all for extensions that had nowhere else to live, and the
cost was a pile of type magic: higher-kinded-type encoding in the store
middleware system (#384), threading generic types that didn't actually
provide that much type safety. (TypeScript could often bail out to `any`
when inference broke.)

Those extensions now have proper homes. Store middleware (#384) gives
transport-layer concerns (auth, presigning, request transformation) a
proper extension point, and the custom `fetch` option on `FetchStore`
(#388) handles the per-store cases at the callsite. Chunk-layer concerns
will move to `zarr.extendArray` in a follow-up.

What's left is `signal`, which now lives properly on the (non-generic)
`AsyncReadable` interface and can be passed directly in `zarr.get` and
`zarr.set` from the caller:

    // Before
    interface AsyncReadable<Options = unknown> {
      get(key: AbsolutePath, opts?: Options): Promise<Uint8Array | undefined>;
    }
    await zarr.get(arr, null, { opts: { signal: ctl.signal } });

    // After
    interface AsyncReadable {
      get(key: AbsolutePath, opts?: { signal?: AbortSignal }): Promise<Uint8Array | undefined>;
    }
    await zarr.get(arr, null, { signal: ctl.signal });

Batched caller signals in `withRangeBatching` are now merged with
`AbortSignal.any` instead of a user-supplied `mergeOptions` reducer. The
deprecated `opts?: { signal? }` shape still works for one major version
and is folded into the new `signal` via `AbortSignal.any`.
Covers the three paths that previously only worked incidentally through
the `Options` generic: `zarr.get()` with a first-class `signal`,
propagation through the sharded chunk getter (#306), and the deprecated
`opts.signal` shim.
@manzt manzt force-pushed the manzt/drop-options branch from 552db13 to c4784ce Compare April 13, 2026 16:44
@manzt manzt merged commit 0dfa50d into main Apr 13, 2026
2 checks passed
@manzt manzt deleted the manzt/drop-options branch April 13, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant