Expand description
Neo4j’s Bolt protocol — the model is the graph database.
A client opens with the 4-byte magic 60 60 B0 17 and four version proposals; the server
answers with the version it picked (Bolt 5.0–5.8, see messages::negotiate). From then on
both sides exchange chunked PackStream messages. The model is asked exactly two things — may
this login in (actions::BOLT_AUTHENTICATE_EVENT), and what does this Cypher query return
(actions::BOLT_QUERY_EVENT) — and everything else is NetGet’s:
- The state machine. CONNECTED → (HELLO) → AUTHENTICATION → (LOGON) → READY; RUN →
STREAMING; PULL/DISCARD drain it back to READY; BEGIN → TX_READY, RUN → TX_STREAMING,
COMMIT/ROLLBACK → READY; a FAILURE → FAILED, where every message but RESET and GOODBYE is
answered IGNORED; RESET → READY from anywhere. A message that arrives ahead of a RESET the
client already sent is IGNORED (the INTERRUPTED state), and a message the current state does
not allow is a
Neo.ClientError.Request.InvalidFAILURE and a close. Bolt 5.0 carries the credentials in HELLO and goes straight to READY. - Result streaming. The model answers RUN with every row at once; NetGet sends the column
list in RUN’s SUCCESS, then as many RECORDs as each PULL’s
nasks for withhas_more, and the summary (type,db,stats, a bookmark for writes) at the end. Inside a transaction several results may be open at once and PULL/DISCARD address them byqid. - What costs no model call. HELLO, ROUTE (a single-server routing table naming the address
the client dialled), BEGIN/COMMIT/ROLLBACK, RESET, LOGOFF, TELEMETRY, and the admin queries
cypher-shellruns on every connect (CALL db.ping(),CALL dbms.licenseAgreementDetails(),CALL dbms.components()), so connecting costs nothing. - The password. With a
passwordstartup parameter NetGet compares the credential itself, in constant time, and a mismatch never reaches the model. The credential never appears in an event either way.
Three bounds, each refused before anything is allocated for it: the handshake must arrive
within first_byte_timeout_secs, a message is capped at packstream::MAX_MESSAGE_BYTES
summed over its chunks, and PackStream nesting at packstream::MAX_PACKSTREAM_DEPTH. The
read deadlines wrap the read, never the answer, so a query parked for a human under a
manual rule is not closed by idle_timeout_secs.
On a backend failure, an unusable answer or no answer, the client gets FAILURE
Neo.TransientError.General.DatabaseUnavailable with a fixed message (never the error text)
and the connection stays usable after RESET — Bolt’s own recovery path. A refused login closes
the connection, as Neo4j does.
Re-exports§
pub use packstream::MAX_MESSAGE_BYTES;pub use packstream::MAX_PACKSTREAM_DEPTH;
Modules§
- actions
- Bolt actions: what the model is told, and what its answers become.
- messages
- Bolt’s handshake and messages: what a client may send, and the four things a server answers with (SUCCESS, RECORD, IGNORED, FAILURE).
- packstream
- PackStream — Bolt’s value encoding — and Bolt’s message chunking.
- values
- The model’s JSON answers → PackStream, and the client’s PackStream parameters → JSON.
Structs§
- Bolt
Config - Startup configuration shared by every connection.
- Bolt
Server
Constants§
- DEFAULT_
NEO4J_ VERSION - Neo4j version the server claims unless
neo4j_versionsays otherwise. - FIRST_
BYTE_ TIMEOUT - How long a new connection may take to send its 20-byte handshake. Bolt is client-first and every driver sends it with the connect, so 30 seconds only ever matters for a peer that is not speaking Bolt at all.
- IDLE_
TIMEOUT - How long the server waits for the next message after the handshake. Drivers pool connections and leave them idle between queries; five minutes keeps a pooled connection useful without letting abandoned ones accumulate.