Skip to content

Releases: Hikari-Systems/slater

v0.24.1

Choose a tag to compare

@github-actions github-actions released this 18 Jul 11:51

v0.24.1 — correctness fixes, cache scalability, and an internal refactor

Two correctness fixes, a read-path scalability improvement, and a structural
split of the two largest source files. No storage-format change; no config change.

Correctness

  • toInteger() on an out-of-range or non-finite float now returns a clear error
    instead of silently saturating (1e19 became i64::MAX, NaN became 0).
    toIntegerOrNull() returns NULL for those same inputs, and toInteger("abc")
    stays NULL as before. The same guard closes the integer index-argument path
    (list.remove / list.insert / …), which had the identical trap.
  • The auto-consolidation log classifier branches on a typed error code rather
    than matching message text, so a benign "already in progress" single-flight
    race can never be mis-logged if the wording changes.

Performance

  • The query-result cache and the vector-index cache (resident PQ codes + the
    Vamana block LRU) now use a CLOCK second-chance eviction with a shared-read-lock
    hit path, instead of a global mutex that rewrote an ordered LRU on every hit.
    Concurrent cache hits no longer serialise: measured roughly 2x aggregate hit
    throughput across four threads, where the previous path fell below parity as
    cores were added. This brings both pools in line with the decompressed-block
    cache, which already had this design.

Internal (no behaviour change)

  • The Cypher executor and the Bolt server — the two largest files in the tree —
    are each carved into cohesive submodules: the executor Engine into
    exec/{access, driver, matchclause, proc, knn, traverse, scan, project, eval},
    and the server into server/{registry, conn, listen, handle, write,
    consolidate, query}. Pure relocations; the full test suite is unchanged.

Full Changelog: v0.24.0...v0.24.1

v0.24.0

Choose a tag to compare

@github-actions github-actions released this 17 Jul 22:47

slater 0.24.0 — dot-product (MIPS) vector search + a security & correctness hardening pass

Makes dot-product (inner-product / MIPS) a first-class vector metric and folds in a
whole-codebase review remediation. Builds on the v0.23.0 FreshDiskANN writable vector
ladder. No on-disk format-version change — existing generations open unchanged.

Dot-product (MIPS) vector search — now properly supported (HIK-137)
Dot-product kNN previously recalled only ~0.32–0.50: the graph reached inner-product
neighbours via a norm-augmentation reduction that navigates poorly under wide norm
spreads. 0.24.0 adds an IP-native navigator — inner-product closeness, top-R-by-IP
neighbour selection, highest-norm entry, and an IP-trained PQ codebook — across the whole
write ladder: delta, sealed segment, consolidate, merge and delete. On the measurement
fixture recall@10 rises from ~0.40 to ~0.99–1.0 and holds rung-to-rung, verified against an
independent brute-force inner-product ground truth. The navigator is an additive, optional
discriminator: cosine and L2 navigation is unchanged, and a forged inner-product navigation
on a cosine/L2 index is refused rather than mis-served.

Security & correctness hardening (whole-codebase review)

  • Session state no longer outlives the identity it belonged to — LOGOFF / failed re-LOGON
    could leave one connection's buffered rows and open-transaction graph readable by the next
    user on that connection, bypassing the read ACL. (HIK-123)
  • A label removal is a scope change, not an embedding delete — consolidation no longer
    permanently destroys a de-labelled node's vector. (HIK-122)
  • Disk cache is bounded across restarts (adopts prior-run files, LRU-evictable) and its
    write-behind queue is byte-bounded — closing an unbounded-disk path and an unaccounted-RSS
    path. (HIK-124, HIK-125)
  • On-disk widths, offset tables and PQ code bytes are validated where they enter memory — a
    corrupt or forged block now errors instead of panicking or silently returning wrong
    results. (HIK-126, HIK-128, HIK-132, HIK-133)
  • Non-finite embedding components are rejected at ingest and query; out-of-range duration
    components are rejected instead of saturating to a wrong value; WAL tail and commit-marker
    handling corrected. (HIK-134, HIK-127, HIK-130, HIK-135)
  • User range indexes are retained on the pk property during build. (HIK-129)

Tooling & tests

  • A committed, reproducible performance suite for the vector write ladder, with recall scored
    against an independent brute-force ground truth (docs/PERF-REPORT.md). (HIK-120, HIK-121)
  • CI now compiles and runs the s3/gcs feature-gated test code that the default build never
    touched — the blind spot where the disk-cache bugs had survived. (HIK-138)

Upgrade notes
No format-version change; v0.23.0 generations open as-is. Dot-product graphs opt into the new
IP-native navigation; cosine/L2 behaviour is unchanged.

Full Changelog: v0.23.0...v0.24.0

v0.23.0

Choose a tag to compare

@github-actions github-actions released this 15 Jul 16:17

slater 0.23.0 — FreshDiskANN: writable disk-native vector search

This release makes embeddings a first-class writable value. Vector search was
previously a read-only, build-time index (cosine only); it is now a full write ladder
you can insert into, update, and delete from in place — without an offline rebuild —
and it gains the L2 and dot-product (MIPS) metrics alongside cosine.

Highlights

  • Writable embeddings. SET n.embedding = vecf32([…]) and REMOVE n.embedding
    land in the write delta and are immediately KNN-visible with exact rank, then survive
    a segment flush, a merge, and a consolidation.
  • A three-level read path. A query merges a sealed base index, a sealed per-segment
    index, and an in-memory RW-index (a live mutable Vamana over the delta), so KNN
    latency stays flat as writes accumulate instead of growing with the pending-write
    count.
  • Deletes stop costing query IO. A deleted vector becomes a navigational hole that a
    background delete-consolidation splices out of the graph; measured ~3x fewer node
    fetches per query at 67% deleted, at equal recall.
  • Consolidation without a rebuild. Because the on-disk graph addresses neighbours by
    layout position rather than node id, a consolidation carries the Vamana graph by
    reference — hard-linked, byte-identical — and rewrites only a small id column, folding
    vector writes into the base without the O(N) graph reconstruction.
  • cosine / L2 / dot indexes (dot via a norm-augmentation transform).
  • A committed performance bench suite (crates/slater/benches/) and a written report
    (docs/PERF-REPORT.md).

Upgrade note

  • On-disk format 7 → 8: rebuild required. Existing generations must be rebuilt with
    the 0.23.0 builder; the server refuses an older format legibly rather than misreading
    it. There are no legacy installs to migrate.

Full Changelog: v0.22.1...v0.23.0

v0.22.1

Choose a tag to compare

@github-actions github-actions released this 14 Jul 07:15

slater v0.22.1

Whole-codebase review remediation: 46 findings fixed — 40 from a full
security/correctness/performance review of the codebase, plus 6 follow-ups
discovered while fixing those — each landed with a regression test and a
clean-room verification of the integration branch.

Security & robustness

  • Every untrusted-input decode path is now bounded: the Bolt PackStream decoder,
    zstd block decompression, the on-disk column/segment/index decoders, the
    property-value wire format, and query nesting depth. A malformed or hostile
    input can no longer drive an unbounded allocation or a stack-overflow abort.
  • The whole pre-authentication connection window is bounded — TLS handshake,
    reads, and writes each on one deadline — and password verification and write
    execution now run off the async reactor behind concurrency caps, so a
    connection or login flood can no longer stall the server for everyone.
  • Object-store integrity re-hashes an object body when the store carries no
    server-side checksum, instead of silently falling back to a length-only check.

Correctness

  • ORDER BY direction and DISTINCT are read from the parsed keyword rather than a
    substring scan of the clause text.
  • Graph export round-trips every node label and backtick-quotes identifiers, so a
    dump rebuilds faithfully and cannot inject into the rebuild.
  • The write-ahead log rolls back a partially written batch and recovers from a
    poisoned lock, closing the case where an unacknowledged write could be
    resurrected on replay; segment creation fsyncs its parent directory.
  • Integer arithmetic overflow now errors cleanly instead of wrapping silently,
    rand() is uniform over [0,1), and relationship-uniqueness is enforced across
    fixed-length patterns.

Performance

  • The block cache and the decoded-block cache are sharded with a lock-free read
    path, so hit throughput scales with cores instead of collapsing under
    contention.
  • Anchor scans stream in bounded windows, so LIMIT short-circuits and resident
    memory stays bounded whether or not a write delta is present.

Resident memory remains bounded independent of graph size: a 90M-node /
1.5B-edge graph serves within the documented few-hundred-MB target.

Full Changelog: v0.22.0...v0.22.1

v0.22.0

Choose a tag to compare

@github-actions github-actions released this 13 Jul 15:50

slater v0.22.0

Live, durable writes — and a re-planed, smaller on-disk format. Slater still
serves graphs bigger than RAM over Bolt at a fixed cache budget; this release adds
a durable write path on the same immutable image and generalises the storage codecs
so the format is smaller and usable in its encoded form.

Writes (the headline)

  • A durable write layer over the immutable core: writes land in an in-RAM memtable,
    flush to immutable L0 delta segments, and fold back into the core by background
    consolidation — all over standard Bolt, so existing drivers write as well as read.
    Group-committed batches (write-UNWIND), off-heap L0, size-tiered and fraction-of-core
    auto-consolidation with a hard-cap throttle, and an off-peak consolidation window.
  • Business-key MERGE / SET / DELETE on the live graph: create-on-absent, patch a core
    node/edge in place (including relocating a moved indexed value), properties on
    delta-born nodes and edges, delete by business key. The read cost of a write scales
    with the delta, not the graph: count(*) and label/reltype marginals stay metadata
    reads with writes outstanding.
  • GQL INSERT write spelling alongside Cypher.

Storage format (FORMAT_VERSION 7 — no back-compat, rebuild generations)

  • A generic per-chunk "plane" codec (Elias-Fano / RLE / bit-packed / raw / zstd,
    chosen per chunk) backs the degree column, resident key columns, endpoint postings,
    node labels and the topology CSR — usable encoded, no decompress on the hot path.
  • Topology carries a per-reltype directory: a typed expansion decodes only the matching
    relationship type's runs.
  • Codec discipline: every codec carries its Constant/RLE/complement co-candidate rather
    than committing to one — a dense endpoint set stores its sparse complement, a
    single-label column is a run, and a constant chunk is just a single-run RLE. On the
    91.6M-node / 1.49B-edge reference graph this keeps node_labels at 242 MB (not 1.1 GB)
    and the reltype postings under a megabyte, all decompress-free.

Query performance

  • k-hop count(endpoint) summed over a maintained per-node degree column instead of
    walking the final hop; hub-degree streaming bounds multi-hop counts on dense graphs.

Full Changelog: v0.21.0...v0.22.0

v0.21.0

Choose a tag to compare

@github-actions github-actions released this 01 Jul 18:59

slater v0.21.0

External-build memory fixes for the large-graph pipeline. Both cut peak RSS
sharply on the 91.6M-node / 1.49B-edge reference build with a byte-identical
generation (content-hash unchanged), verified end-to-end.

Highlights

  • resolve: the edge-endpoint resolve phase no longer overshoots its memory
    budget. Its per-partition external sorters now spill inline instead of through
    the shared parallel spill pool, which had multiplied each sort's run count (and
    therefore the k-way merge's resident block footprint) inside an already
    thread-saturated stage. Peak RSS 9.33 GB -> 2.61 GB; phase ~11% faster.
  • cluster: the locality-reorder adjacency sort gets its full memory budget back.
    A single non-concurrent sort had been starved 16x under a convention meant for
    phases that fan out many concurrent sorters, which inflated run count and hurt
    both memory and speed. Peak RSS 6.54 GB -> 1.70 GB; phase back below its
    pre-regression wall time.

Both fixes are output-preserving: every sort key involved is a total order, so
run count cannot change the merged result.

Full Changelog: v0.20.0...v0.21.0

v0.20.0

Choose a tag to compare

@github-actions github-actions released this 01 Jul 13:15

v0.20.0

Query engine:

  • Whole-graph label/reltype metadata (label/reltype counts, self-loop counts,
    first-label counts, the (srcLabel, reltype, tgtLabel) schema cube, undirected
    and labelled variants) is now answered directly from resident manifest
    metadata for unanchored MATCH shapes — zero block reads, versus a full
    unanchored scan before. Now also composes with ORDER BY / LIMIT.
  • Fixed a correctness bug where MATCH (a)-[r]->(a) (same variable on both
    ends, i.e. a self-loop constraint) was incorrectly treated as two bare
    endpoints by the metadata fast path; it now declines to the matcher.

Build (slater-build):

  • Fixed a real bug where the offline builder's emit.graph_summaries phase
    (whole-graph label/reltype/schema-cube summaries, computed at build time)
    re-decompressed a node's entire on-disk block on every single per-node
    lookup, with zero caching. At real dataset scale this made the phase
    effectively unbounded (confirmed via profiling: never finished after 27+
    minutes, on pace for 20-30+ hours). Fixed via a small, block-sequential
    cache shared with the query engine's existing block-cache design
    (extracted into a common module so both crates use the same well-tested
    cache) — the phase now completes in well under 5 minutes even on a
    91M-node / 1.5B-edge generation.
  • Added an opt-in --features profiling build (off by default, verified
    absent from the default dependency graph) for heap-profiling the builder
    during future investigations.

Known issues carried into this release (not yet fixed, flagged intentionally
rather than silently shipped):

  • The external resolve pass (business-key edge resolution) has a real
    memory-accounting gap: observed resident memory during this phase runs to
    several GB against a nominal much smaller configured working-memory budget,
    on large generations. Root-caused in part (a fixed-size internal buffer
    pool whose aggregate footprint isn't counted against the configured
    budget), but a further, size-scaling contributor is not yet isolated.
  • An attempted fix to the offline builder's clustering pass (bounding its
    internal sort's memory the same way other passes do) regressed both wall
    time and peak memory at large scale instead of improving them, and needs
    to be revisited or reverted.
    Neither affects correctness of the resulting on-disk generation — both are
    performance/resource-usage issues in the build path only.

Full Changelog: v0.19.0...v0.20.0

v0.19.0

Choose a tag to compare

@github-actions github-actions released this 30 Jun 19:48

v0.19.0 — CASE and operators in the build-time SET dialect

slater-build can now ingest business-key MERGE dumps whose SET right-hand
sides use CASE expressions and infix operators, not just function calls,
literals, and same-node property references.

Highlights

  • Build-time SET gains a full scalar-expression grammar: CASE
    (searched and simple), comparison (=, <>, <, <=, >, >=),
    arithmetic and string concatenation (+, -, *, /, %), and
    boolean AND/OR/NOT, with standard precedence and parentheses.
  • A common accumulator idiom now builds unmodified, e.g.
    SET n.summary = CASE WHEN coalesce(n.summary,'') = '' THEN x ELSE n.summary + '; ' + x END. Each assignment folds against the node's
    accumulated properties in input order, so the result matches a live graph
    engine's — without the quadratic read-grow-rewrite cost.
  • Operator, comparison, and truthiness semantics are shared with the query
    engine through slater-scalar, so build-time and query-time evaluation
    agree (string-concat +, three-valued =/NULL handling, Kleene booleans).
  • CASE branches evaluate lazily: only the selected THEN/ELSE runs.

Scope and compatibility

  • Edge SET and overlay-patch SET remain literal-only.
  • Existing dumps are unaffected; this is strictly a superset of the prior
    dialect.

No configuration changes are required.

Full Changelog: v0.18.0...v0.19.0

v0.18.0

Choose a tag to compare

@github-actions github-actions released this 30 Jun 15:43

slater v0.18.0

Faster cold start, and per-query timing at the info level.

Startup now opens every graph — and, within each, its range indexes and
per-file integrity checks — concurrently rather than one object at a time.
On an object-store backend a fresh process previously streamed hundreds of
small files serially (a HEAD per inventory file, a footer read per range
index) before the Bolt listener bound, so a large multi-graph deployment
could take the better part of a minute to accept connections. The opens
are independent, so fanning them out cuts cold start to roughly the slowest
single graph. Validation, the readers, and the on-disk format are
unchanged, and the first error still aborts the open.

The per-query query executed metrics summary now logs at info instead of
debug, and the default log level is now info. The summary therefore appears
out of the box without the chatty debug SDK and wire tracing; the
instrumentation that produces it is gated at info as well, so raising the
level to warn restores the zero-overhead hot path.

No format, on-disk, or wire changes; upgrade in place.

Full Changelog: v0.17.1...v0.18.0

v0.17.1

Choose a tag to compare

@github-actions github-actions released this 29 Jun 10:14

slater v0.17.1

Per-query observability on every query, not just the CLI.

The query executed metrics summary that the query CLI subcommand
emits is now produced on the Bolt path as well, and both carry the same
figures:

  • query cost (elements charged against the budget)
  • execution / encode / total timings and the result row count
  • result-cache hit or miss
  • block-cache hit/miss delta for the query, plus the hit ratio

The summary is gated on the debug log level — when it is off the hot
path takes no timestamps and no cache snapshots — and the default log
level is now debug, so the summary appears out of the box. Raise the
level to info to silence it and restore the zero-overhead path.

The startup line now reports the compiled build version.

No format, on-disk, or wire changes; upgrade in place.

Full Changelog: v0.17.0...v0.17.1