Skip to content

Graphus v0.0.6

Choose a tag to compare

@FlavioCFOliveira FlavioCFOliveira released this 07 Jul 14:30

Graphus v0.0.6

Version: 0.0.6
Date: 2026-07-07
Tag: v0.0.6

Summary

Graphus v0.0.6 is a reliability-and-performance hardening release of Graphus, the
Label Property Graph (LPG) database server written in Rust for extreme load and concurrency.
It fixes a series of critical ACID and durability defects that could silently lose
committed data under extreme multi-core concurrency, bounds several memory and liveness
failure modes so that an adversarial or interrupted workload degrades gracefully instead of
aborting the server, and continues to scale reads, writes, and graph analytics across
cores
. It introduces no breaking changes and no new user-facing feature — the public
Cypher, Bolt, and REST contracts are unchanged, so v0.0.6 is a drop-in upgrade from
v0.0.5.

Throughout, the four inviolable guarantees held:

  • 100% ACID — full transactional reliability under power loss, faults, and crashes.
  • 100% openCypher TCK3914 / 3914 scenarios passing.
  • 100% Bolt protocol — byte-for-byte interoperability with the Neo4j driver ecosystem.
  • 100% PackStream — exact wire-level serialization.

Highlights

  • Committed data is safe under extreme multi-core concurrency. Three separate critical
    defects — an incremental garbage-collection pass that could silently forget a committed value
    written by an in-flight writer, a slot-reuse race that could make a committed edge invisible to
    a concurrent lock-free reader, and a free-list double-allocation on live rollback that could
    corrupt a property or incidence chain — are fixed, each with a gating regression test proven to
    fail before the fix. No crash is required to trigger any of them, and none leaves committed data
    at risk after the fix.
  • A healthy database always reopens. A transient device write error on a new page's unlogged
    seed flush can no longer leave an unrecoverable checksum-invalid page, a page torn during
    recovery is healed by its checksum, and crash recovery after a large or interrupted bulk-load no
    longer exhausts memory — so a database that shut down cleanly, crashed, or was force-detached
    comes back online without a larger host.
  • A single query can no longer take down the server. A deeply recursive Cypher query is now a
    bounded, recoverable error across every deep-recursion input shape rather than an uncatchable
    stack-overflow abort of the whole process, and hosted databases stay available.
  • Reads, writes, and analytics scale further across cores. A single heavy read is split across
    the reader pool with an adaptive morsel width, more concurrent committers share one durable
    fsync, seven more Graph Data Science algorithms run in parallel, and a group-by-over-expand
    aggregation is executed across cores.
  • Adversarial and slow clients degrade gracefully. Oversized .gcol uploads are bounded, a
    stalled reader can no longer pin garbage collection forever, and a slow consumer resumes across
    hardened group-commit batches instead of wedging.

Changed

  • A single heavy read now scales across cores. The off-thread reader pool uses an adaptive
    morsel width, so even one large frontier-seeded traversal — such as a friends-of-friends
    recommendation query — is split across the reader pool instead of running on a single worker
    thread.
  • Writes coalesce further under concurrency. Auto-commit write fsyncs are coalesced through
    group commit, and the commit pipeline is deepened past the previous batch-width ceiling, so more
    concurrent committers share a single durable fdatasync. Every durability invariant is
    preserved: a committer is acknowledged only after the fsync covering its commit record
    completes.
  • Graph Data Science algorithms run in parallel. The PageRank, weakly-connected-components,
    and degree-centrality parallelism gaps were closed, and seven previously single-threaded
    algorithms were parallelized across cores.
  • Parallel group-by aggregation. A group-by-over-expand aggregation — for example, counting
    each node's neighbours — is now executed across cores instead of on the engine thread alone.
  • Reader-safe procedures dispatched off-thread. Reader-safe procedures, including full-text
    and spatial procedures feeding an expansion, are dispatched to the off-thread reader pool and
    capture their index state in the read view, so they no longer serialize on the single engine
    thread (and no longer misfire a spurious "no such index" error when feeding an expansion).
  • Bounded write-ahead-log-to-store ratio. Background maintenance now runs at a
    store-proportional cadence built on an incremental, O(Δ) freeze sweep, bounding the
    WAL-to-store size ratio without reintroducing the O(store) per-checkpoint cost that a
    create-only workload would otherwise accrue as the store grows.
  • Durability invariants promoted to release-active. The two load-bearing durability
    invariants (doublewrite and seed-flush ordering) are now asserted in release builds, not only in
    debug builds.
  • Honest, multi-core example. The GDS-analytics example was corrected so that it demonstrates
    real multi-core execution rather than overstating it.
  • Leaner, better-scoped CI. The GitHub Actions pipeline no longer runs the DST / soak gate on
    plain feature-branch pushes (a feature branch reaches CI through its pull request), splits the
    fast cross-platform test job from a dedicated DST gate, adds incremental build caching, and
    cancels superseded runs. A trigger and permissions security audit added least-privilege
    contents: read permissions and hardened several workflow-input paths. The
    .github/dependabot.yml file was removed by request.

Fixed

  • Silent loss of a committed value under incremental garbage collection (critical, ACID). With
    an explicit BEGIN … COMMIT transaction in flight, a maintenance garbage-collection pass could
    advance its freeze frontier past the in-flight writer's records and then forget the writer, so
    once it committed a reader at the latest snapshot resolved its value as aborted — permanently
    losing a committed value with no crash required. The freeze frontier now tests live writer
    membership and keeps a writer's records unfrozen until it commits, restoring the
    freeze-before-prune ordering the prune's soundness depends on.
  • Lost committed edges under concurrent off-thread reads (critical, ACID isolation). A
    maintenance garbage collection could reclaim and reuse a record slot while a lock-free off-thread
    reader still held a pointer into it, so the reader decoded a foreign record and a committed live
    edge became invisible. A freed slot is now shadow-held from physical reuse until every
    transaction that predates the free has retired (an epoch / QSBR barrier), while remaining
    immediately reusable after a restart, when no readers are in flight. The path is allocation-free
    and deterministic when no reader holds a slot, so the deterministic simulator remains
    byte-identical.
  • Chain corruption from physical-id double-allocation on live rollback (critical, ACID
    durability).
    Under statement-interleaved SSI write load, restoring a rolling-back transaction's
    free list to the last durably-committed image could hand a freed id to a concurrent writer twice,
    producing a self-cyclic property or incidence chain and losing the data threaded below the cycle.
    Rollback now snapshots and restores the in-memory free lists around the catalog reload and
    withdraws only the aborting transaction's own pushes. Two related MVCC-stamp undo fixes landed
    alongside it: a non-LIFO-safe compare-and-set undo for tombstone stamps, and reclaiming an
    aborting transaction's own reused-id pops on rollback.
  • A transient write error could brick store reopen (critical, ACID / availability). A transient
    device error on a new page's unlogged seed flush left an all-zero, checksum-invalid page that no
    store mapped and no WAL record covered, so the next open failed checksum verification and a
    healthy database could never reopen. Cold-open reconstruction now classifies such an orphan page:
    an all-zero aborted-allocation phantom is safely skipped (crash recovery has already
    re-materialized every committed logged page), while a non-zero bad checksum still fails closed as
    genuine corruption — preserving the never-serve-an-untrusted-page mandate.
  • Torn page during crash recovery. A page torn mid-write while recovery is running is now healed
    by checksum-gating its page LSN, instead of propagating a partially written page.
  • Crash recovery could exhaust memory on a large or interrupted load (critical, recoverability).
    A large Mode A network bulk-import interrupted by a crash, kill, power loss, or force-detach left
    the entire retained WAL un-reclaimed, so crash recovery read gigabytes into memory and the
    out-of-memory killer aborted the reopen — committed data stayed correct but the database could
    not come back online without a larger host. Reopen memory is now bounded to the retained window
    for all large-WAL reopens, a mid-load maintenance pass reclaims the WAL prefix using the
    incremental freeze sweep, and a force-detach can no longer corrupt the store on reopen.
  • A deep query could stack-overflow-abort the whole server (critical, availability). A single
    authenticated Cypher query could drive native recursion deeper than the engine / reader-pool
    stack and trigger an uncatchable stack-overflow abort of the entire process, taking down every
    hosted database and connection with a crash-loop on retry. Query recursion depth is now bounded
    across all deep-recursion input shapes — runtime value nesting, clause chains, and long MATCH
    paths — and turned into a recoverable error; on aarch64 the runtime threads run on an 8 MiB stack
    so a deeply nested REST value cannot overflow the server.
  • A stalled reader or slow consumer could wedge the server or pin garbage collection. A stalled
    off-thread reader's egress wait is now bounded so it can no longer pin the garbage-collection
    watermark forever; the group-commit drain is bounded and reader GC-pins are released mid-storm;
    and parked slow-consumer statements now resume between hardened group-commit batches instead of
    stalling.
  • Adversarial or oversized inputs bounded. The .gcol bulk-upload path is bounded so one large
    or adversarial upload cannot exhaust server memory, and a RAII pin-guard ensures a panicking visit
    closure can no longer strand a buffer-pool frame.
  • Reliability residuals closed. Five remaining bounded reliability residuals were closed and a
    Mode A checkpoint-sentinel leak was fixed.

Verification

This release was validated empirically; no functional test reported an error.

  • Conformance gates intact. The openCypher TCK remains at 3914 / 3914 (100%), and the Bolt,
    PackStream, and ACID guarantees are unchanged. The deterministic simulator (DST / VOPR) ran
    safety, liveness, and mixed workloads across seed sweeps with byte-identical, deterministic
    outcomes.
  • Regression coverage. Every fix landed with a gating regression test proven to fail before the
    fix — including a visibility-based repro for the incremental-GC committed-value loss, a white-box
    repro for the reader-versus-GC slot-reuse race, the free-list rollback double-allocation test,
    the seed-flush write-error reopen test, the torn-during-recovery healing test, the bounded-reopen
    tests for the interrupted load, and stack-overflow probes that would abort their own test binary
    if the recursion bound regressed. Additional multicore-durability coverage (group-commit under
    crash, write-I/O-error, off-thread-reader versus GC, and a loom interleaving test) was added to
    close the gaps these defects exposed.
  • Concurrency-first analysis. The critical isolation defects were reproduced on the real
    threaded engine, because they are structurally invisible to a single-threaded simulator; each was
    then A/B-proven fixed under the same reproduction.

Compatibility

v0.0.6 is a drop-in upgrade from v0.0.5 — no public Cypher, Bolt, or REST API contract changed,
and no new user-facing feature was added. There is no behavioural change for a client: the
transaction and isolation model is exactly as in v0.0.5 (MySQL-style
autocommit reads at Snapshot Isolation, fully Serializable writes and explicit BEGIN … COMMIT
transactions; see docs/transactions.md). Every change in this release is
an internal reliability, durability, or performance improvement. The four inviolable guarantees
(ACID, openCypher TCK, Bolt, PackStream) remain at 100%.

Upgrading

# Docker Hub (multi-arch: linux/amd64 + linux/arm64)
docker pull flaviocfo/graphus:v0.0.6             # or :latest

See docs/getting-started.md for first-run instructions,
docs/transactions.md for the read/write isolation model, and
docs/rest-api.md for the network bulk-import endpoint.