# Executors

> USearch for JavaScript

A call that names no executor runs on the calling thread, single-threaded on RAM and on the handle's device and default stream on VRAM, and spawns nothing behind the caller's back.
An `Executor` owns the workers instead, and one can be shared by several indexes.
Each residency has its own factory:

```javascript
const hostPool = usearch.Executor.forRam({ threads: 2, memoryDomains: [0, 1] });
const devicePool = usearch.Executor.forVram({ devices: [0, 1], scratchLimit: 1 << 30 });
const diskPool = usearch.Executor.forNvme({ threads: 4, paths: ['/mnt/nvme0', '/mnt/nvme1'] });
```

`forRam` creates an executor of host threads and spreads them over the named NUMA nodes, absent naming none and spreading them over every node.
`onPool` borrows an existing ForkUnion pool by its `BigInt` address instead of spawning one.
`forVram` opens one CUDA stream per named ordinal, absent taking one free device, or borrows the `streams` given as `BigInt` addresses, one per device.
It takes no thread count because one host thread drives one stream per device, so the device list is what sizes the work rather than a number of workers.
`forNvme` opens one submission ring per worker over the named device or directory paths, absent deriving them.
Each factory's config holds only what its own C structure takes: `memoryDomains` for RAM, `devices` for VRAM, and `paths` for NVMe.

`drain(mood)` waits until no call holds the executor, then idles the workers in a `usearch.Mood`: `Parked` threads sleep, and `Spinning` ones stay hot for the next call's latency.
The collector frees an executor eventually, and `free()` waits out the call holding it and joins its workers now; a freed executor is refused by every later call.

### Receivers & Deferred Calls

The receiver chooses where a verb runs and how it completes, and the verb stays the same.
The index runs it on the calling thread, `index.on(executor)` blocks on an executor, and `index.deferred(executor)` submits it there and answers a `usearch.Deferred`:

```javascript
const matches = index.search(queries, 10, arena);                 // the calling thread
const onPool = index.on(executor).search(queries, 10, arena);     // blocking, holding the executor until it returns
const call = index.deferred(executor).search(queries, 10, arena); // Deferred<Matches>
```

`DenseIndexOn` and `DenseIndexDeferredOn` offer the same verbs with the same arguments.
Only the blocking receivers add `contains`, `cursor` and `searchStream`, whose every pull blocks, and only the index itself adds `attend`.
Constructors address no index yet, so no receiver offers them; the ones the C interface lets fan out take an `executor` in their config.

A `Deferred` keeps everything the library reads or writes alive until its call is final: the outcome, the inputs, the outputs and every handle it names.
It is awaitable, implementing the thenable protocol, so `await` reaches it like any other asynchronous value:

```javascript
const call = index.deferred(executor).search(queries, 10, arena);
if (call.status === usearch.Status.Deferred) {
  // other work
}
const matches = await call; // or: call.wait()
```

`await` waits on the libuv pool, so the event loop keeps turning, while `wait()` blocks the calling thread.
Both answer the same cached result, or throw the same failure, however often they are asked, and `status` reads the outcome without blocking.
`using call = ...` waits for the call before its block ends, and one dropped unfinished is handed back to the collector until it is final, so nothing it borrowed is freed under the library.
Refusals this binding catches before the call crosses, like keys that do not match the rows, throw at submission.

One call holds an executor at a time, so a second call finding it held finishes at once with `Status.Contended`, and nothing queues.
A deferred call on a caller-exclusive pool runs on the pool's thread 0, so polling `status` alone finishes it, and its progress handler and predicate run on the pool's threads; a single thread, WebAssembly or a VRAM executor runs it at submission.
Calls depending on each other are ordered by waiting on the first before submitting the second.
The arrays a deferred verb is handed must not change until it is final, since the library reads them until then.

`import * as usearch from 'usearch';`

`import { DenseVerbs } from 'usearch';`

`import { DenseIndexOn } from 'usearch';`

`import { DenseIndexDeferredOn } from 'usearch';`

`import { Executor } from 'usearch';`

`import { Deferred } from 'usearch';`

## Mood

What an executor does with its threads or streams once it goes idle.

```typescript
enum Mood
```

- `Parked` = `&quot;parked&quot;`: Idle threads sleep; the next call pays a wake-up.
- `Spinning` = `&quot;spinning&quot;`: Idle threads stay hot, trading power for the next call's latency.

## ExecutorForRamConfig

Where the host threads of a RAM executor are placed, how many there are, and how many deferred calls it tracks.

```typescript
interface ExecutorForRamConfig
```

- `memoryDomains?` `number[]`: NUMA node IDs the workers are spread over; absent spreads them over every node.
- `threads?` `number`: Workers to spawn; absent takes 7/8 of the cores the domains carry.
- `deferredLimit?` `number`: Deferred calls tracked at once; absent takes a default.
- `cpuClass?` `string`: The CPU class to dispatch as by its canonical name; absent dispatches as the machine.

## ExecutorOnPoolConfig

Where the borrowed pool of a RAM executor is placed, and how many deferred calls it tracks.

```typescript
interface ExecutorOnPoolConfig
```

- `memoryDomains?` `number[]`: NUMA node IDs of the indexes it will drive; absent derives every node.
- `deferredLimit?` `number`: Deferred calls tracked at once; absent takes a default.
- `cpuClass?` `string`: The CPU class to dispatch as by its canonical name; absent dispatches as the machine.

## ExecutorForVramConfig

Which devices a VRAM executor drives, and on which streams.

```typescript
interface ExecutorForVramConfig
```

- `devices?` `number[]`: CUDA ordinals to drive; absent takes one free device.
- `streams?` `bigint[]`: Borrowed CUDA stream addresses, one per device in `devices` order; absent creates its own.
- `scratchLimit?` `number`: Ceiling on scratch bytes per device; absent lets scratch grow as geometry asks.
- `deferredLimit?` `number`: Deferred calls tracked at once; absent takes a default.
- `gpuClass?` `string`: The GPU class to dispatch as by its canonical name; absent dispatches as the devices.

## ExecutorForNvmeConfig

Where an NVMe executor submits its reads.

```typescript
interface ExecutorForNvmeConfig
```

- `paths?` `string[]`: Device or directory paths; absent derives them.
- `threads?` `number`: Workers to spawn, one submission ring apiece; absent derives from the devices' queue capabilities.
- `deferredLimit?` `number`: Deferred calls tracked at once; absent takes a default.
- `cpuClass?` `string`: The CPU class to dispatch as by its canonical name; absent dispatches as the machine.

## DenseVerbs

The verbs every receiver of a dense index shares, written once.

```typescript
abstract class DenseVerbs<Receiving extends "blocking" | "deferred">
```

The receiver chooses where a verb runs and how it completes, and the verb stays the same: a
[`DenseIndex`](https://www.unum.cloud/docs/usearch/javascript/metrics.md#DenseIndex) runs it on the calling thread, `index.on(executor)` blocks on an executor, and
`index.deferred(executor)` submits it there and answers a [`Deferred`](https://www.unum.cloud/docs/usearch/javascript/errors.md#Deferred).

## *

Claims room for a total entry count ahead of insertion, a hint, since insertions grow the index on demand.

```typescript
reserve(capacity: number): Answer<Receiving, void>
```

- `capacity`: The desired total capacity, the current size included.

## *

Erases every entry, keeping the reserved capacity and the frozen geometry.

```typescript
clear(): Answer<Receiving, void>
```

## *

Reports the frozen metadata and the current counters in one call.

```typescript
describe(): Answer<Receiving, DenseIndexDescription>
```

## *

Audits how much of the graph a search reaches from its landmarks.

```typescript
health(): Answer<Receiving, DenseReachability>
```

## *

Counts the entries stored under one key.

```typescript
count(key: KeyLike): Answer<Receiving, number>
```

- `key`: The identifier to be enumerated.

Throws: Will throw an error if the key is spelled in none of the accepted forms.

## *

Add vectors to the index.

```typescript
insert(
    keys: KeysLike,
    vectors: RowsView | Vector,
    config: DenseInsertConfig = {},
): Answer<Receiving, void>
```

A typed array is one row, and a [`RowsView`](https://www.unum.cloud/docs/usearch/javascript/inputs-and-outputs.md#RowsView) is a batch borrowed in place. A single key
broadcasts across every row. A batch is all-or-nothing: a rejected one leaves the index
untouched.

Rows keep whatever type they arrived in and the engine converts them into the index's own
quantization, so the two are independent - a packed `u1x8` or a `bf16` row travels as
bytes with its [`RowsView`](https://www.unum.cloud/docs/usearch/javascript/inputs-and-outputs.md#RowsView) naming what they mean.

- `keys`: Input identifiers for every vector.
- `vectors`: One row, or a run of rows of the index width.
- `config`: Per-call breadth and telemetry sink.

Throws: Will throw an error if the length of keys doesn't match the number of vectors
or if it's not a single key.

## *

Re-selects the neighbors of every stored entry against the finished graph.

```typescript
refine(
    config: DenseRefineConfig = {},
): Answer<Receiving, DenseRefineReport>
```

A cheap insertion pass followed by one refinement reaches a better graph, in less total
time, than a single expensive insertion pass - so a wide breadth belongs here.

- `config`: Per-call breadth and telemetry sink.

## *

Searches the index for the nearest neighbours of every query row.

```typescript
search(
    queries: RowsView | Vector,
    wanted: number,
    arena: Arena,
    config: DenseSearchConfig = {},
): Answer<Receiving, Matches>
```

The matches land in `arena` and come back as a view into it, so a recall sweep reusing one
arena allocates once.

- `queries`: One query row, or a run of them, at the index's own width.
- `wanted`: Matches per query, the "k" in "kANN".
- `arena`: The memory the matches land in, rewound by the call.
- `config`: Per-call breadth and telemetry sink.

Throws: Will throw when the queries do not split into whole rows of the index geometry.

## *

Late-interaction scoring of multi-row queries: every query row takes its best match within a key, and those maxima sum to that key's score.

```typescript
maxsim(
    queries: RowsView | Vector,
    rowsPerQuery: number,
    wanted: number,
    arena: Arena,
    config: DenseMaxsimConfig = {},
): Answer<Receiving, DenseProducts>
```

The run is over keys rather than rows, which is what an index built with `valuesPerKey`
above one exists for. Runs on the inner-product kinds alone.

- `queries`: The token rows of every query, end to end.
- `rowsPerQuery`: Rows in every query; uniform, so padded queries apply as is.
- `wanted`: Documents per query, not per token row; zero keeps every document a query scored.
- `arena`: The memory the scored keys land in, rewound by the call.
- `config`: Per-call breadth and telemetry sink.

Throws: Will throw when the token rows do not split into whole queries.

## *

Retrieves the vectors stored under one key, one row per entry, in insertion order.

```typescript
get(
    key: KeyLike,
    arena: Arena,
    config: DenseGetConfig = {},
): Answer<Receiving, DenseVectors>
```

Rows land in `arena` and come back as a view into it, converted into [`scalar`](https://www.unum.cloud/docs/usearch/javascript/retrieval-and-streaming.md#scalar), shaped by the
width and stride the call reports.

- `key`: The identifier whose entries are exported.
- `arena`: The memory the rows land in, rewound by the call.
- `config`: The kind to export as.

## *

Multiplies a matrix against the index, sparsely - every pair the walk scored, not only the nearest.

```typescript
multiply(
    left: RowsView | Vector,
    arena: Arena,
    config: DenseMultiplyConfig = {},
): Answer<Receiving, DenseProducts>
```

How many pairs a walk scores is known only once it ends, so the products land in `arena` and
come back as views into it. The scores are unnormalized logits, so the handle must hold the
inner-product kind.

- `left`: One row, or a run of rows, at the index's own width.
- `arena`: The memory the pairs and their offsets land in, rewound by the call.
- `config`: Per-call pair bound, breadth and telemetry sink.

## *

Absorbs every donor into this index, one after another, keeping their graphs rather than re-inserting their vectors and linking each in across the appended part.

```typescript
absorb(
    donors: DenseIndex[],
): Answer<Receiving, DenseRefineReport>
```

A donor the library consumed refuses every later verb with [`Status.Uninitialized`](https://www.unum.cloud/docs/usearch/javascript/errors.md#Uninitialized); one it
did not absorb, like a donor of another scalar refused with [`Status.ConfigMismatch`](https://www.unum.cloud/docs/usearch/javascript/errors.md#ConfigMismatch), stays
a live index the caller still owns, though its entries may already have moved here. Until a
deferred absorb is final, every donor it names refuses every verb, and no other absorb can name it.

- `donors`: The indexes to absorb.

## *

Splits this index into the receivers, the inverse of [`absorb`](https://www.unum.cloud/docs/usearch/javascript/metrics.md#absorb): graph-local parts keeping their edges, one per receiver, leaving this index empty but live.

```typescript
split(
    receivers: DenseIndex[],
    config: DenseSplitConfig = {},
): Answer<Receiving, DenseRefineReport>
```

Receivers must be empty and share the index's residency, scalar, class, metric, geometry and
shard count, or the call refuses with [`Status.ConfigMismatch`](https://www.unum.cloud/docs/usearch/javascript/errors.md#ConfigMismatch), moving nothing.

- `receivers`: Two or more empty indexes, each receiving one part.
- `config`: The seed and breadth.

## *

Draws keys around `config.focus`, or across the whole index, each hanging from a shown or earlier draw and placed in three dimensions beside the shown ones.

```typescript
sample(
    wanted: number,
    arena: Arena,
    config: DenseSampleConfig = {},
): Answer<Receiving, DenseDraws>
```

A larger `wanted` draws a superset, so a view grows one connected sample as it zooms. Only RAM
samples yet.

- `wanted`: The upper bound on draws.
- `arena`: The memory the draws land in, rewound by the call.
- `config`: The shown keys and their coordinates, the focus, the seed and the breadth.

## *

Saves the index in the layout the path extension picks - one `.safegraphs` monolith, or a `.safegraphs.json` manifest beside its shards.

```typescript
save(path: string): Answer<Receiving, void>
```

- `path`: File path to write.

Throws: Will throw an error if `path` is not a string.

## save*

Writes the index into memory as one monolith.

```typescript
saveBuffer(arena: Arena): Answer<Receiving, Monolith>
```

The bytes are what a checkpoint holds, so a service that keeps its indexes in an object
store never touches the filesystem. They land in `arena` and come back as a view into it.

- `arena`: The memory the monolith lands in, rewound by the call.

## executor

The executor the verbs run on; absent runs them on the calling thread.

```typescript
readonly executor: Executor | undefined
```

## DenseIndexOn

The verbs of one index, blocking on one executor: `index.on(executor)`.

```typescript
class DenseIndexOn extends DenseVerbs<"blocking">
```

Every call starts after every earlier submission to that executor, and returns with its outputs written.

## DenseIndexOn

Made by `index.on(executor)`, never directly.

```typescript
new DenseIndexOn(
    compiled: CompiledIndex,
    executor: Executor | undefined,
)
```

## contains

Verifies the presence of one key in the index.

```typescript
contains(key: KeyLike): boolean
```

Binding-only sugar over [`count`](https://www.unum.cloud/docs/usearch/javascript/metrics.md#count).

- `key`: The identifier to be checked for presence in the index.

## cursor

Opens a walk over the current contents, every pull on this receiver's executor.

```typescript
cursor(starts?: KeysLike): DenseCursor
```

Without `starts` it yields every entry as stored; with them, the start keys' own entries first in order, then the entries those link to breadth-first, each once.

- `starts`: The keys to walk from; absent walks every entry.

## searchStream

Opens a resumable nearest-neighbor walk over one query row, every pull on this receiver's executor.

```typescript
searchStream(
    query: RowsView | Vector,
    config: DenseSearchStreamInitConfig = {},
): DenseSearchStream
```

- `query`: A single query row of the index geometry.
- `config`: The breadth.

## executor

The executor the verbs run on; absent runs them on the calling thread.

```typescript
readonly executor: Executor | undefined
```

## DenseIndexDeferredOn

The verbs of one index, submitted to one executor and answered as [`Deferred`](https://www.unum.cloud/docs/usearch/javascript/errors.md#Deferred) calls: `index.deferred(executor)`.

```typescript
class DenseIndexDeferredOn extends DenseVerbs<"deferred">
```

Cursors, streams and [`contains`](https://www.unum.cloud/docs/usearch/javascript/metrics.md#contains) stay blocking, so this receiver offers none of them.

A verb with outputs borrows its arena as the blocking verb does, and waits into the same view.

## DenseIndexDeferredOn

Made by `index.deferred(executor)`, never directly.

```typescript
new DenseIndexDeferredOn(
    compiled: CompiledIndex,
    executor: Executor,
)
```

## executor

The executor the verbs run on; absent runs them on the calling thread.

```typescript
readonly executor: Executor | undefined
```

## Executor

The workers a fanned-out verb runs on, shared across indexes.

```typescript
interface Executor extends Disposable
```

An executor owns host threads or device streams; an index owns entries. Keeping them apart is
what lets one pool serve several indexes, and what makes the cost of spawning visible at the
line that spawns it. The collector frees it eventually; [`free`](https://www.unum.cloud/docs/usearch/javascript/retrieval-and-streaming.md#free) joins the workers now.

## forRam

Spawns host worker threads for a RAM-resident index.

```typescript
static forRam(config?: ExecutorForRamConfig): Executor
```

- `config`: The NUMA nodes, the thread count and the deferred limit.

## onPool

Borrows a ForkUnion `fu_pool_t` for a RAM-resident index, keeping its lender's mood.

```typescript
static onPool(
    pool: bigint,
    config?: ExecutorOnPoolConfig,
): Executor
```

- `pool`: The pool's address; it must outlive the executor.
- `config`: The NUMA nodes and the deferred limit.

## forVram

Opens one stream per device for a VRAM-resident index, driven from a single host thread.

```typescript
static forVram(config?: ExecutorForVramConfig): Executor
```

- `config`: The devices, borrowed streams, scratch ceiling and deferred limit.

## forNvme

Opens one submission ring per worker for an NVMe-resident index.

```typescript
static forNvme(config?: ExecutorForNvmeConfig): Executor
```

- `config`: The device or directory paths, the thread count and the deferred limit.

## drain

Waits for every call submitted to this executor so far, then idles in `mood`.

```typescript
drain(mood?: Mood): void
```

- `mood`: What the threads or streams do once they go idle.

## free

Runs every deferred call and joins the workers now; a freed executor refuses every later call, and a second [`free`](https://www.unum.cloud/docs/usearch/javascript/retrieval-and-streaming.md#free) does nothing.

```typescript
free(): void
```

Refuses with [`Status.Contended`](https://www.unum.cloud/docs/usearch/javascript/errors.md#Contended) while a GPU arena made on it is live.

## Deferred

A call submitted by a deferred receiver, final once its executor finishes it.

```typescript
class Deferred<T> implements PromiseLike<T>, Disposable
```

It keeps everything the library reads or writes alive until then - the outcome, the inputs,
the outputs and every handle it names - so none of them is collected under the call, and it
borrows its arena as a blocking call does. A result read after the arena was rewound or freed
throws [`Status.Uninitialized`](https://www.unum.cloud/docs/usearch/javascript/errors.md#Uninitialized). [`status`](#status) polls without
blocking, [`wait`](#wait) blocks and answers, and `await` runs that wait on the libuv pool; both answer
the same cached result, or throw the same failure, however often they are asked.

```
const matches = await call; // or: call.wait()
```

## Deferred

Made by a verb of a deferred receiver, never directly.

```typescript
new Deferred(call: CompiledDeferred, answer: (raw: never) => T)
```

## wait

Blocks the calling thread until the call is final, then answers its result or throws its failure.

```typescript
wait(): T
```

## then

Waits on the libuv pool rather than the calling thread, which is what `await` reaches for.

```typescript
then<Fulfilled = T, Rejected = never>(
    onFulfilled?: ((value: T) => Fulfilled | PromiseLike<Fulfilled>) | null,
    onRejected?: ((reason: unknown) => Rejected | PromiseLike<Rejected>) | null,
): Promise<Fulfilled | Rejected>
```

## status

[`Status.Deferred`](https://www.unum.cloud/docs/usearch/javascript/errors.md#Deferred) until the call is final, then [`Status.Success`](https://www.unum.cloud/docs/usearch/javascript/errors.md#Success) or its failure.

```typescript
readonly status: Status
```

Reads the outcome without blocking.

