HarperFast / HarperFast/harper
Use an options object for searchByIndex and the custom-index search() contract
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
`searchByIndex` in `resources/search.ts` has grown to eight positional parameters, the last of
which — `minResults` — was added in [#2125](https://github.com/HarperFast/harper/pull/2125) so a
query's `offset + limit` could reach an approximate index and stop it from silently truncating the
result set.
```ts
export function searchByIndex(
searchCondition: DirectCondition,
transaction: any,
reverse: boolean,
Table: any,
allowFullScan?: boolean,
filtered?: any,
context?: any,
minResults?: number
): AsyncIterable;
```
Five of those eight are optional, so most call sites pass a run of `undefined`s or stop early and
inherit defaults they never meant to choose. `resources/Table.ts` and the recursive relationship
calls inside `search.ts` pass nothing past `filtered`, which is harmless today only because none of
them lead with a vector sort.
The real cost is on the custom-index contract. `HierarchicalNavigableSmallWorld.search()` is the
in-tree implementation of an interface an external index can also implement, and its signature grew
the same way — `(searchCondition, context, filter?, minResults?)`. Every future capability that has
to reach an approximate index (a cursor for stable paging, a deadline, a recall target) is another
positional argument, and adding one is a breaking change for any index implemented outside this
repo. The contract is still unreleased, so reshaping it is cheap now and expensive later.
## Suggested shape
Collapse the optional tail into an options object on both sides:
```ts
searchByIndex(searchCondition, transaction, reverse, Table, {
allowFullScan,
filtered,
context,
minResults,
});
customIndex.search(searchCondition, context, { filter, minResults });
```
The four leading parameters are required at every call site and read fine positionally; it is the
optional tail that should become named. Whether the custom-index `search()` keeps `context`
positional is a judgment call — it is passed by every caller, so either works.
Worth deciding as part of this: whether the options object is also where a future paging cursor
lands, since #2125 documented `offset`/`limit` over an approximate index as best-effort rather than
a stable partition (see the "An approximate index returns at most `ef` rows" section in `DESIGN.md`).
## Scope
- `resources/search.ts` — `searchByIndex` signature, the two recursive call sites, and the
`customIndex.search()` call.
- `resources/Table.ts:4960` — call site.
- `resources/indexes/HierarchicalNavigableSmallWorld.ts` — `search()` signature.
- Custom-index documentation, if the contract is written down anywhere outside the code.
Mechanical; no behaviour change intended. Raised by @maurice-harper in review of #2125 and recorded
as item 6 of that PR's "For the human reviewer" section, where the positional argument was kept to
avoid reshaping the contract inside a correctness fix.
Contributor guide
Research direction
Start in resources/search.ts at searchByIndex, its recursive calls, and the customIndex.search() call; then inspect resources/Table.ts:4960 and the search() signature in resources/indexes/HierarchicalNavigableSmallWorld.ts. Check the approximate-index guidance in DESIGN.md and any custom-index documentation. Done means the optional arguments use named options at all listed call sites and the search behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- backend, databases
- Issue type
- Refactor
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100