Graphus v0.0.7
Graphus v0.0.7
Version: 0.0.7
Date: 2026-07-07
Tag: v0.0.7
Summary
Graphus v0.0.7 is a Bolt / Neo4j-driver interoperability fix for Graphus, the Label
Property Graph (LPG) database server written in Rust for extreme load and concurrency. It restores
automatic retry of contended transactions for every application that uses the Neo4j driver
ecosystem's recommended managed-transaction pattern (session.execute_write(...) /
session.execute_read(...)).
Under a serialization conflict, Graphus correctly classified the aborted transaction as a
retriable TransientError, but emitted the error title Neo.TransientError.Transaction.Terminated.
That title is a driver poison title: every official Neo4j driver keeps a fixed
ERROR_REWRITE_MAP that rewrites it to a non-retriable Neo.ClientError.Transaction.Terminated,
regardless of the class the server sent. The retry logic therefore never fired, and every contended
transaction failed permanently for apps following the idiomatic pattern. The abort now carries
Neo.TransientError.Transaction.Outdated — the semantically-accurate optimistic-concurrency code
that drivers do not rewrite — across both the Bolt and REST interfaces.
This is a drop-in upgrade from v0.0.6: the transaction, isolation, Cypher,
and data contracts are unchanged, and no new user-facing feature was added. The only behavioural
change is the retriable error code returned on a conflict. ACID was never at risk — the conflict
was always resolved correctly, with no lost updates; only the driver-side retry signalling was
broken.
Throughout, the four inviolable guarantees held:
- 100% ACID — full transactional reliability under power loss, faults, and crashes.
- 100% openCypher TCK — 3914 / 3914 scenarios passing.
- 100% Bolt protocol — byte-for-byte interoperability with the Neo4j driver ecosystem.
- 100% PackStream — exact wire-level serialization.
Highlights
- Contended transactions retry again on the official drivers. The idiomatic
session.execute_write(...)/session.execute_read(...)managed-transaction functions once more
recover automatically from a serialization conflict, instead of surfacing a permanent, non-retriable
failure to the application. - Bolt ↔ REST parity preserved. Both interfaces share the same corrected retriable code, so a
conflict looks identical over Bolt-over-TCP, Bolt-over-UDS, and the REST WebAPI. - Proven against a real driver on a live server. The fix was found and A/B-verified against the
live instance with the realneo4jPython driver 6.2.0, exercising the driver's own classification
path, and guarded by anti-poison-title regression tests on both interfaces. - No ACID or data-contract change. Correctness was already intact; this release only corrects the
wire signal that tells a driver a conflict is safe to retry.
Fixed
- Retriable serialization conflicts were poisoned for the Neo4j driver ecosystem (Bolt / driver
conformance). Under a serialization conflict — an SSI dangerous-structure abort or a write–write
conflict — both the Bolt and REST interfaces emitted the error title
Neo.TransientError.Transaction.Terminated. TheTransientErrorclassification was correct
(the failure is safe to retry), but.Terminated— like.LockClientStopped— is a driver
poison title: every official Neo4j driver keeps a fixedERROR_REWRITE_MAPthat downgrades it to
Neo.ClientError.Transaction.Terminated, a non-retriableClientError, regardless of the class
the server sent. As a result, the idiomatic managed-transaction retry (session.execute_write(...))
never recovered from a serialization conflict, so every contended transaction failed permanently
for applications following Neo4j's recommended pattern — a violation of the "100% Bolt-protocol /
Neo4j-driver-ecosystem compatible" guarantee. ACID itself was never at risk: the conflict was always
resolved correctly, with no lost updates. The abort now carries
Neo.TransientError.Transaction.Outdated, the semantically-accurate optimistic-concurrency code
("transaction state invalidated by concurrent updates; retry may succeed"), which drivers do not
rewrite — so a driver correctly seesis_retryable() == true. The retriable-code constant is renamed
(CODE_TXN_CONFLICT_RETRYABLE) and documented with the reason, the Bolt (graphus-bolt) and REST
(graphus-rest) code paths are kept byte-identical for cross-wire parity, and regression tests assert
the emitted code ends with neither.Terminatednor.LockClientStoppedon both interfaces.
Verification
This release was validated empirically; no functional test reported an error.
- Empirical, real-driver proof. The defect was discovered and the fix A/B-verified against the
live server instance using the realneo4jPython driver 6.2.0, driven through the driver's
own classification path (_hydrate_neo4j):.Outdatedresolves tois_retryable() == true, whereas
the previous.Terminatedresolved tofalse. This was surfaced by the real-driver stability run,
not by a mock. - Regression coverage on both interfaces. New anti-poison-title regression asserts were added to
graphus-boltandgraphus-rest, checking that a transaction abort still classifies as
TransientErrorand that its title is neither.Terminatednor.LockClientStopped; the REST
router integration test for a conflicting single-statement write was updated to expect the corrected
retriable code on the409response. - Conformance gates intact. The openCypher TCK remains at 3914 / 3914 (100%), and the ACID,
Bolt, and PackStream guarantees are unchanged.cargo test -p graphus-bolt -p graphus-restis green,
including the new regression asserts, andcargo fmtis clean.
Compatibility
v0.0.7 is a drop-in upgrade from v0.0.6. The transaction and isolation model is exactly as in
v0.0.6 (MySQL-style autocommit reads at Snapshot Isolation, fully Serializable
writes and explicit BEGIN … COMMIT transactions; see docs/transactions.md),
and no new user-facing feature was added.
The single behavioural change is the error code returned on a serialization conflict: over both Bolt
and REST it changes from Neo.TransientError.Transaction.Terminated to
Neo.TransientError.Transaction.Outdated. Both remain in the retriable TransientError class, so a
conformant Neo4j driver — which classifies by class, not by the exact title — now retries the conflict
automatically. No action is required unless an application special-cased the exact string
.Terminated; such code should match the retriable TransientError class (or the driver's
is_retryable()), not the specific title.
Upgrading
# Docker Hub (multi-arch: linux/amd64 + linux/arm64)
docker pull flaviocfo/graphus:v0.0.7 # or :latestSee docs/getting-started.md for first-run instructions,
docs/transactions.md for the read/write isolation model and how to retry a
serialization failure, and docs/rest-api.md for the REST WebAPI error codes.