Skip to content

feat: reduce round trips for bulk and schema-checked reads - #683

Merged
pdlug merged 3 commits into
mainfrom
feat/bulk-and-schema-checked-reads
Sep 11, 2026
Merged

feat: reduce round trips for bulk and schema-checked reads#683
pdlug merged 3 commits into
mainfrom
feat/bulk-and-schema-checked-reads

Conversation

@pdlug

@pdlug pdlug commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Graph reads can spend extra round trips resolving inbound edges, retrying projected selections, and probing schema freshness before fetching data. This adds set-oriented reverse reads and an explicit schema-checked read API, and plans whole-entity selections before execution.

store.bulkFindEdgesTo and its pinned-view counterpart mirror bulkFindEdgesFrom, grouping inbound edges by target across node and edge kinds. They share the existing endpoint-set implementation and preserve input ordering, repeated and empty buckets, temporal visibility, and per-input limits. The existing single-kind edges.Kind.bulkFindTo remains available.

Selectors returning whole nodes or edges, including nested and spread selections, choose full rows before issuing SQL. This avoids the projected-query/full-fetch retry for fresh query instances. Data-dependent selectors retain the existing fallback when their runtime field needs cannot be inferred ahead of execution.

executeChecked(expectedSchemaVersion) reads relational results and the active schema version in one statement snapshot. It throws SchemaChangedError before invoking the selector on a mismatch, including empty results, so callers can reload the schema, rebuild the query, and retry. Bundled backends expose the schema-version table binding; custom backends without it are refused. Checked reads use full projections and reject recursive and relevance-ranked queries. They check one statement without changing store-open caching or write-fence semantics.

Documentation also shows the existing ordered traversal with LIMIT 1 for fetching the newest target in one statement. A minor changeset records the additive APIs.

The compatibility ledger records exact exceptions for the additive methods on library-created handles and the new reverse-read parameter type. Existing custom backend implementations gain no required members.

Closes #684

@pdlug
pdlug merged commit ce35043 into main Sep 11, 2026
23 checks passed
@pdlug
pdlug deleted the feat/bulk-and-schema-checked-reads branch September 11, 2026 21:32
@github-actions github-actions Bot mentioned this pull request Sep 11, 2026
pdlug added a commit that referenced this pull request Sep 11, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @nicia-ai/typegraph@0.58.0

### Highlights

TypeGraph 0.58 reduces database round trips in graph read paths.
`store.bulkFindEdgesTo` and its pinned-view counterpart resolve inbound
edges for a set of targets across node and edge kinds, mirroring
`bulkFindEdgesFrom`. Callers can replace per-target lookups with a
set-oriented read while retaining input order, repeated and empty target
buckets, temporal visibility, and per-input limits. For a single edge
kind, the existing `edges.Kind.bulkFindTo` remains available.

Whole-node and whole-edge selections now choose a full-row fetch before
executing SQL, including nested and spread selections detected during
planning. Previously, a fresh query instance could issue a projected
query, discover that the selector needed the complete entity, and fetch
again. These selections now avoid that extra statement without requiring
applications to retain query instances between requests. Selectors whose
field needs depend on row values keep the existing fallback.

`executeChecked(expectedSchemaVersion)` combines a relational read with
an active schema-version check in one statement snapshot. It offers an
explicit alternative to probing the committed version before fetching
data: a mismatch raises `SchemaChangedError` before the selector runs,
even when the query returns no rows. Applications can then reload the
schema and rebuild the query before retrying. The check covers that
statement; it does not pin later reads in the request or replace write
fences.

### Upgrade notes

- Update hand-built `Store` mocks and wrappers exposing the full store
surface with `bulkFindEdgesTo`; query wrappers exposing the full
executable-query surface must also forward `executeChecked`.
Library-created stores, pinned views, and queries provide the new
methods automatically.
- When adopting `executeChecked`, catch `SchemaChangedError`, reload the
reconciled schema, and rebuild the query before retrying. Start a new
transaction if the old transaction holds a repeatable-read snapshot. An
expected version of `undefined` means no active schema and is distinct
from version zero.
- Use checked reads for relational queries with ordinary bound values.
They fetch full rows and support traversals, ordering, offsets, and
limits; recursive and relevance-ranked queries require a separate schema
probe. Replace named `param()` references with bound values before
building a checked query.
- Custom backends adopting checked reads must supply
`tableNames.schemaVersions`, naming a relation with `graph_id`,
`version`, and `is_active` columns whose active row agrees with
`getActiveSchema`. A missing binding raises `ConfigurationError` before
SQL execution. Bundled SQLite and PostgreSQL backends supply it
automatically; this release requires no database migration.

### Minor Changes

- [#683](#683)
[`ce35043`](ce35043)
Thanks [@pdlug](https://github.com/pdlug)! - Add `store.bulkFindEdgesTo`
and its pinned-view counterpart for set-oriented inbound reads across
edge kinds. Detect whole-node and whole-edge selections before issuing a
projected query, avoiding a redundant fetch for fresh query instances.
Add `executeChecked(expectedSchemaVersion)` for a relational read and
committed-schema check in one statement, with `SchemaChangedError` on
mismatch, including empty results.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Paul Dlug <paul@nicia.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Record compatibility assessment for additive graph-read APIs

1 participant