8000 feat(query): streaming engine core, Scan and oracle (#544, PR 1 of 3) by adityamukho · Pull Request #588 · project-minigraf/minigraf · GitHub
[go: up one dir, main page]

Skip to content

feat(query): streaming engine core, Scan and oracle (#544, PR 1 of 3) - #588

Merged
adityamukho merged 5 commits into
v3from
feat/544-operator-core
Oct 14, 2026
Merged

adityamukho merged 5 commits into
v3from
feat/544-operator-core

Conversation

@adityamukho
Copy link
Copy Markdown
Collaborator

Part 2 of the streaming engine (#473), first of three PRs for #544. Plan: docs/superpowers/plans/2026-10-14-544-operator-core.md (steps 1–6).

What changes

Queries whose :where is one pattern with a stored attribute and whose :find holds plain variables run on a new engine in src/query/engine/. Everything else runs on the existing executor as before.

  • Key-level reads. CommittedReader::key_source() → KeySource: DICT accessors and live_keys, which walks an index range with net-assert on keys (perf: compute net-assert on v8 index keys before resolving facts (O(live) point queries) #379) and resumes after a whole triple. A read holds no lock between batches.
  • Scan. Picks EAVT, AEVT or AVET from the bound positions; [?e :a C] reads the AVET range of C (perf: attribute+value patterns scan the whole attribute; AVET index is never read #518). It reads the committed range, leaving out triples that a pending record decides, then reads the pending range by whole (entity, attribute) runs (Snapshot::pending_live).
  • Cells and ids. Batches of 1,024 rows hold id cells until Project, so only returned rows are translated (perf: committed scans look up every entity id in the DICT tree #530, for these queries). Pending entities and idents get provisional ids per query.
  • Oracle. Under cfg(test) and the new test-oracle feature, every query the engine runs is also run by the executor on the same snapshot, and the answers must agree as bags. The new oracle job in rust.yml runs the whole suite with the feature, so the model-based, property, golden-corpus and integration suites check the engine.

The cursor is still eager in this PR: the engine drains into a QueryResult. Laziness, close propagation and counters come in PR 3. Filter/Bind, pseudo-attributes and keyword/UUID/float constants come in PR 2.

Deviations from the spec

They are listed in the plan. Briefly:

Measurements

Measured with the #394 envelope at 100K and 1M facts on an idle machine. Base e2bddeb and this branch ran in parallel on separate sockets, with the nodes swapped for a second round. Values are p50.

Query 1M base 1M PR RSS base → PR
attribute_value [?e :name "p…"] 344 ms 20 µs 142 → 3 MiB
attribute_scan (166,666 rows) 577 ms 268 ms 172 → 57 MiB
point_entity 27 µs 23 µs 3 MiB
as_of / valid_at 26 / 24 µs 23 / 17 µs 3 MiB

Queries that stay on the executor (joins, recursion, count_grouped, hot_*) are within ±3%.

Checks

  • cargo test: 1,467 passed, 10 ignored.
  • cargo test --features test-oracle: same result.
  • Mutation checks: the oracle fails the suite when one row is dropped in Project, and the engine tests fail when pending records no longer hide the committed records they replace.
  • clippy -D warnings: native, --all-features, wasm, wasm32 browser, and wasm32-wasip1.
  • Codex review: one finding (float constants matched exactly). It does not apply, because the planner sends float constants to the executor; a test now pins that.

#518 is fixed by this PR and will be closed by hand after merge. #530 remains open until joins move over (#545). No closing keyword for #473, #544 or #530.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HyLscCUuJ1GQpdAeX79EdR

adityamukho and others added 5 commits October 14, 2026 13:50
Three PRs: key-level reads, Scan, Project, planner v1 and the oracle;
Filter/Bind, pseudo-attributes and cross-kind constants; the lazy cursor,
measurement and docs. Limit/Offset move to #306.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyLscCUuJ1GQpdAeX79EdR
Part 2 of the streaming engine (#473), first PR. Queries with one pattern
and plain :find variables run on a new engine in src/query/engine/:

- CommittedReader::key_source gives key-level reads: live_keys walks an
  index range with net-assert on keys and resumes after a whole triple,
  so a read holds no lock between batches; DICT accessors.
- Scan reads the committed range (EAVT, AEVT or AVET by the bound
  positions; [?e :a C] reads the AVET range of C, #518), leaving out the
  triples a pending record decides, then the pending range by whole
  (entity, attribute) runs. Cells hold ids until Project (#530);
  pending entities and idents get provisional ids.
- Every other query, and reads inside a write transaction, stay on the
  executor. The executor is the oracle: under cfg(test) and the
  test-oracle feature each engine query also runs there and the answers
  must agree; CI runs the whole suite with the feature.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyLscCUuJ1GQpdAeX79EdR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyLscCUuJ1GQpdAeX79EdR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyLscCUuJ1GQpdAeX79EdR
@codecov
codecov Bot commented Oct 14, 2026
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.42334% with 20 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/query/engine/plan.rs 90.38% 5 Missing ⚠️
src/query/engine/ids.rs 92.30% 4 Missing ⚠️
src/query/engine/scan.rs 97.12% 4 Missing ⚠️
src/query/engine/project.rs 91.30% 2 Missing ⚠️
src/storage/mod.rs 0.00% 2 Missing ⚠️
src/storage/reader.rs 96.15% 2 Missing ⚠️
src/graph/storage.rs 98.41% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@adityamukho
adityamukho merged commit 82875e0 into v3 Oct 14, 2026
25 checks passed
@adityamukho
adityamukho deleted the feat/544-operator-core branch October 14, 2026 08:59
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.

1 participant

0