Closes #4288. Blob reads in Node can now be cancelled. `BlobFile.read`, `readRange` and `readRanges`, and `Table.fetchBlobs` and `fetchBlobFiles` take an optional `{ signal?: AbortSignal }` (new `BlobReadOptions` type). When the signal aborts, the call rejects with `signal.reason` (an `AbortError` unless the caller gave a reason) and the native future is dropped, so the read stops instead of running to completion. A signal that is already aborted rejects before any read starts. How it works: - On the Rust side, these five methods are now sync `#[napi]` methods that return `env.spawn_future(...)`. The future is wrapped in `futures::future::abortable`, and the abort handle is registered with napi's `AbortSignal::on_abort`. napi's `AbortSignal` is `Rc`-based, so it can't be an argument of an `async fn`, which is why the methods changed shape. The TypeScript signatures are unchanged apart from the new optional argument. - napi-rs installs its own `onabort` on the signal it receives, which would overwrite a handler the caller set. So the TypeScript wrapper passes a private `AbortController` signal to the native call for each request, forwards the caller's abort to it with `addEventListener(..., { once: true })`, and removes the listener when the call settles. Tests in `table.test.ts`: - an already aborted signal rejects on all five methods, and the handle still reads afterwards - a custom abort reason is what the call rejects with - a read with a signal that never aborts returns normally and leaves no `abort` listener on the signal - aborting a 32 MiB `readRange` right after it starts rejects with `AbortError`, and the same handle reads again afterwards The Node docs under `docs/src/js` are regenerated. I didn't add a test for where the `read()` cursor ends up after a mid-flight abort on a local table. The remote `BlobFile` documents that a cancelled read leaves the cursor unchanged, but I haven't confirmed the same for the native Lance handle, so the docs don't claim it.
2.2 KiB
@lancedb/lancedb • Docs
@lancedb/lancedb / BlobFile
Class: BlobFile
A lazy handle to blob bytes. Create one with Table.fetchBlobFiles.
Methods
close()
close(): Promise<void>
Releases the handle. Reads after close() fail. Calling it again does
nothing.
Returns
Promise<void>
isClosed()
isClosed(): boolean
Returns true after BlobFile.close.
Returns
boolean
read()
read(maxBytes?, options?): Promise<Buffer>
Reads from the cursor and advances the cursor.
Reads to the end when maxBytes is omitted, or at most maxBytes bytes
otherwise. Returns an empty buffer at the end of the blob.
BlobFile.readRange does not move the cursor.
Parameters
-
maxBytes?:
bigint -
options?:
BlobReadOptions
Returns
Promise<Buffer>
readRange()
readRange(
start,
end,
options?): Promise<Buffer>
Reads the half-open byte range [start, end).
Fails when end is past the blob size. Does not move the cursor.
Parameters
-
start:
bigint -
end:
bigint -
options?:
BlobReadOptions
Returns
Promise<Buffer>
readRanges()
readRanges(ranges, options?): Promise<Buffer[]>
Reads several half-open byte ranges. Returns one buffer per range, in the order given.
Fails when any end is past the blob size. Does not move the cursor.
Parameters
-
ranges:
BlobRange[] -
options?:
BlobReadOptions
Returns
Promise<Buffer[]>
seek()
seek(position): Promise<void>
Moves the cursor to position, in bytes from the start of the blob.
Parameters
- position:
bigint
Returns
Promise<void>
size()
size(): bigint
Returns the blob size in bytes.
Returns
bigint
tell()
tell(): Promise<bigint>
Returns the cursor position in bytes.
Returns
Promise<bigint>