Files
lancedb/docs/src/js/classes/BlobFile.md
T
Bilal Atique 0a1c1a04c7 feat(node): accept an AbortSignal to cancel blob reads (#4350)
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.
2026-09-29 14:01:17 -05:00

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

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

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

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>