From eb68e0decee8b99c08d30299e30069413fc2f889 Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Mon, 24 Feb 2025 12:49:20 -0500 Subject: [PATCH] Propagate `getRange` support in `Listable` when available Previously, only `get` was propagated up. This makes sure we can also use `getRange` if supported when the store is consolidated. --- .changeset/rich-horses-count.md | 5 +++++ packages/core/__tests__/consolidated.test.ts | 14 +++++++++++++- packages/core/src/consolidated.ts | 9 ++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 .changeset/rich-horses-count.md diff --git a/.changeset/rich-horses-count.md b/.changeset/rich-horses-count.md new file mode 100644 index 00000000..dc0e66b1 --- /dev/null +++ b/.changeset/rich-horses-count.md @@ -0,0 +1,5 @@ +--- +"@zarrita/core": patch +--- + +Propagate getRange support in `Listable` when available diff --git a/packages/core/__tests__/consolidated.test.ts b/packages/core/__tests__/consolidated.test.ts index 4b1c3535..d3af42d3 100644 --- a/packages/core/__tests__/consolidated.test.ts +++ b/packages/core/__tests__/consolidated.test.ts @@ -1,6 +1,6 @@ import * as path from "node:path"; import * as url from "node:url"; -import { describe, expect, it } from "vitest"; +import { assert, describe, expect, it } from "vitest"; import { FileSystemStore } from "@zarrita/storage"; import { tryWithConsolidated, withConsolidated } from "../src/consolidated.js"; @@ -124,3 +124,15 @@ describe("tryWithConsolidated", () => { expect(store).toBeInstanceOf(FileSystemStore); }); }); + +describe("Listable.getRange", () => { + it("does not expose getRange if the underlying store does not support it", async () => { + let store = await tryWithConsolidated(new Map()); + expect("getRange" in store).toBeFalsy(); + }); + it("retrieves a byte range from an underlying store", async () => { + let root = path.join(__dirname, "../../../fixtures/v2/data.zarr"); + let store = await tryWithConsolidated(new FileSystemStore(root)); + assert(typeof store.getRange === "function"); + }); +}); diff --git a/packages/core/src/consolidated.ts b/packages/core/src/consolidated.ts index f903b823..56ed39b5 100644 --- a/packages/core/src/consolidated.ts +++ b/packages/core/src/consolidated.ts @@ -24,7 +24,9 @@ type ConsolidatedMetadata = { */ export interface Listable { /** Get the bytes at a given path. */ - get: Store["get"]; + get: (...args: Parameters) => Promise; + /** Get a byte range at a given path. */ + getRange: Store["getRange"]; /** List the contents of the store. */ contents(): { path: AbsolutePath; kind: "array" | "group" }[]; } @@ -93,6 +95,7 @@ export async function withConsolidated( for (let [key, value] of Object.entries(v2_meta.metadata)) { known_meta[`/${key}`] = value; } + return { async get( ...args: Parameters @@ -108,6 +111,10 @@ export async function withConsolidated( } return maybe_bytes; }, + // Delegate range requests to the underlying store. + // Note: Supporting range requests for consolidated metadata is possible + // but unlikely to be useful enough to justify the effort. + getRange: store.getRange?.bind(store), contents(): { path: AbsolutePath; kind: "array" | "group" }[] { let contents: { path: AbsolutePath; kind: "array" | "group" }[] = []; for (let [key, value] of Object.entries(known_meta)) {