VOOZH about

URL: https://deepwiki.com/stefanak-michal/php-bolt-driver/3.2-aprotocol-base-class-and-message-pipeline

⇱ AProtocol Base Class and Message Pipeline | stefanak-michal/php-bolt-driver | DeepWiki


Loading...
Last indexed: 14 February 2026 (a283bd)
Menu

AProtocol Base Class and Message Pipeline

Purpose and Scope

This document explains the AProtocol abstract base class and the message pipeline architecture that underpins all Bolt protocol communication. The AProtocol class serves as the foundation for all protocol version implementations (V1 through V6), providing the core mechanisms for sending and receiving binary messages over a connection. For information about server state management and state transitions, see Server State Management. For details on specific protocol version implementations and their message types, see Protocol Versions.

The message pipeline is the core architectural pattern that enables efficient communication with Neo4j by allowing multiple messages to be sent consecutively before consuming responses, reducing network round-trips and improving throughput.

AProtocol Class Architecture

The AProtocol class is defined at src/protocol/AProtocol.php21-192 and provides the abstract foundation for all protocol version implementations. It orchestrates the interaction between connections, serialization, and message handling.

Core Components


Sources: src/protocol/AProtocol.php21-62

Initialization and Dependencies

The constructor initializes the protocol with serialization components based on the requested PackStream version:

ComponentTypePurposeInitialization
$packerIPackerConverts PHP types to binary PackStream\Bolt\packstream\v{version}\Packer
$unpackerIUnpackerConverts binary PackStream to PHP types\Bolt\packstream\v{version}\Unpacker
$connectionIConnectionManages TCP socket communicationPassed from Bolt factory
$serverStateServerStateTracks current server stateSet by Bolt::build()

The constructor dynamically instantiates packer and unpacker classes based on the PackStream version src/protocol/AProtocol.php45-61 If the requested PackStream version is not implemented, it throws PackException or UnpackException.

Sources: src/protocol/AProtocol.php45-61 src/Bolt.php154-156

Message Pipeline Architecture

The message pipeline is the central architectural pattern that enables efficient Bolt protocol communication. Messages are queued for transmission and responses are consumed asynchronously, allowing multiple operations to be batched together.

Pipeline State Management


Message Pipeline Flow:

  1. Write Phase: Protocol methods (e.g., run(), pull()) serialize and send messages to the connection
  2. Queue Phase: Each message type is appended to $pipelinedMessages array src/protocol/AProtocol.php24
  3. Read Phase: getResponse() or getResponses() consume responses in FIFO order
  4. Dequeue Phase: Messages are removed from the queue as responses are processed

Sources: src/protocol/AProtocol.php24 src/protocol/AProtocol.php120-168

Pipelining Example

The following table demonstrates how messages are queued and consumed during a typical query execution:

StepActionpipelinedMessages QueueNetwork State
1$protocol->run('RETURN 1')[RUN]RUN sent to server
2$protocol->pull(['n' => -1])[RUN, PULL]PULL sent to server
3$protocol->getResponse()[PULL]Read RUN SUCCESS response
4$protocol->getResponse()[PULL]Read RECORD response (not dequeued)
5$protocol->getResponse()[]Read PULL SUCCESS response

Note that RECORD responses do not remove messages from the queue src/protocol/AProtocol.php151-152 allowing multiple record responses to be consumed for a single PULL message.

Sources: src/protocol/AProtocol.php120-168 tests/protocol/V1Test.php108-135

Write Operation Flow

The write operation converts protocol messages to binary PackStream format and transmits them through the connection. All protocol message methods follow a common pattern that leverages the base write() method.

Write Method Implementation


The write() method at src/protocol/AProtocol.php67-73 is protected and accepts an iterable generator from the packer. It iterates through each binary chunk and writes it to the connection, incrementing the $writeCalls counter for analytics tracking.

Key characteristics:

  • Generator-based: Packer returns a generator to support chunking large messages
  • Analytics tracking: Each write call increments $writeCalls src/protocol/AProtocol.php69
  • Exception propagation: ConnectException from connection writes bubble up
  • Fluent interface: Protocol methods return $this to enable method chaining

Sources: src/protocol/AProtocol.php67-73 src/protocol/AProtocol.php31

Message Method Pattern

Protocol version classes implement specific message methods that follow this pattern:


Example from V1 protocol test showing the expected write buffers for an init message tests/protocol/V1Test.php33-44:

0001b2 // Chunk header (2 bytes length)
000101 // Structure marker and signature (0x01 = INIT)
000988... // "bolt-php" string
0001a3 // Map with 3 entries
... // Authentication parameters

Sources: tests/protocol/V1Test.php27-60 tests/protocol/V3Test.php27-65

Read Operation Flow

The read operation receives binary responses from the server, deserializes them, and constructs Response objects. Unlike writes, reads are only performed when responses are explicitly consumed.

Read Method Implementation


The read() method at src/protocol/AProtocol.php79-103 implements the Bolt chunking protocol:

  1. Chunked reading: Messages may span multiple chunks, each prefixed with a 2-byte length header
  2. Termination: A 0x0000 header signals the end of the message
  3. Deserialization: The complete message buffer is passed to the unpacker
  4. Signature extraction: The unpacker provides the message signature via reference parameter
  5. Special handling: IGNORED responses return an empty array

Sources: src/protocol/AProtocol.php79-103

Response Consumption

The getResponse() and getResponses() methods consume responses from the pipeline:

MethodReturn TypeBehaviorUse Case
getResponse()ResponseConsumes one responseSingle message handling
getResponses()Iterator<Response>Consumes all queued responsesBatch processing

getResponse() Flow:


Key behaviors:

Sources: src/protocol/AProtocol.php130-168 src/protocol/AProtocol.php120-125

Response Object Structure

The Response class (defined in src/protocol/Response.php) encapsulates a server response:

PropertyTypeDescription
messageMessageThe message that generated this response
signatureSignatureResponse type (SUCCESS, FAILURE, RECORD, IGNORED)
contentarrayResponse payload data

Response signatures determine control flow:

  • SUCCESS (0x70): Operation completed successfully
  • FAILURE (0x7F): Operation failed with error details in content
  • RECORD (0x71): Data row from a query result
  • IGNORED (0x7E): Message was ignored (server in wrong state)

Sources: Protocol test files demonstrate expected signatures tests/protocol/V1Test.php29-31 tests/protocol/V3Test.php29-31

Integration with Serialization Layer

The protocol layer depends on PackStream serialization for all message encoding/decoding:


PackStream Version Selection:

The PackStream version is specified during protocol construction src/protocol/AProtocol.php50-60:

  • Version 1: Used by all currently implemented protocols
  • Version 2: Reserved for future use
  • Dynamic class loading: \Bolt\packstream\v{version}\Packer

Structure Lookup Tables:

Protocols define structure lookup tables for specialized types:

  • $packStructuresLt: Maps PHP objects to PackStream signatures for packing
  • $unpackStructuresLt: Maps PackStream signatures to PHP classes for unpacking

These tables enable protocol-specific structure handling (e.g., V6's Vector type).

Sources: src/protocol/AProtocol.php45-61 src/protocol/AProtocol.php54 src/protocol/AProtocol.php60

Analytics Integration

The protocol layer integrates with the anonymous analytics system to track usage:

MetricTracking MethodStorage
Query count$writeCalls counterIncremented on each write() call
Session countDestructor trackingIncremented once per protocol instance
AggregationDaily bucketsStored in PSR-16 cache with today's timestamp as key

Analytics tracking occurs in two places:

  1. Write tracking: src/protocol/AProtocol.php69 increments $writeCalls on each write operation
  2. Session tracking: src/protocol/AProtocol.php170-191 aggregates data on destruction

Users can opt out by setting the BOLT_ANALYTICS_OPTOUT environment variable.

Sources: src/protocol/AProtocol.php31 src/protocol/AProtocol.php69 src/protocol/AProtocol.php170-191

Protocol Version Extraction

Each protocol version class is named according to the pattern V{major}_{minor} (e.g., V4_3 for version 4.3). The getVersion() method src/protocol/AProtocol.php108-115 extracts the version string from the class name using pattern matching:

\Bolt\protocol\V4_3 → "4.3"
\Bolt\protocol\V6 → "6"

This version string is cached by persistent connections to avoid redundant handshakes (see Persistent Connections with PStreamSocket).

Sources: src/protocol/AProtocol.php108-115 src/Bolt.php139

Testing Protocol Messages

Protocol tests validate message serialization and state transitions using mocked connections:


The ProtocolLayer base class tests/protocol/ProtocolLayer.php17-123 provides infrastructure for protocol testing:

  • mockConnection(): Creates a mock AConnection with controlled read/write behavior
  • $writeBuffer: Array of expected hexadecimal write buffers
  • $readArray: Array of [signature, content] tuples to return from reads
  • readCallback(): Packs simulated responses using the real Packer

Example test demonstrating write buffer verification tests/protocol/V1Test.php33-44:


Sources: tests/protocol/ProtocolLayer.php17-123 tests/protocol/V1Test.php17-60 tests/protocol/V3Test.php17-65