TCP Transport
Broker-to-broker framed TCP transport with platform-specific I/O engines.
ringloom_tcp is the broker-to-broker transport layer. It is a standalone Zig module that provides connection management, handshakes, message framing, and platform-specific non-blocking I/O backends.
The service runtime does not depend on ringloom_tcp. Services write remote messages into their local broker’s send ring. The broker uses ringloom_tcp to move those messages between broker nodes.
Responsibilities
| Responsibility | Description |
|---|---|
| Platform I/O | Use io_uring on Linux and kqueue on macOS/BSD-style platforms behind a common API. |
| Connection lifecycle | Listen for incoming peer connections, initiate outbound connections, reconnect with backoff, and track connection state. |
| Handshake | Validate peer node ID, target node ID, protocol version, direction, group identity, and session epoch. |
| Framing | Convert TCP byte streams into bounded length-prefixed frames and handle partial reads/writes. |
| Socket configuration | Apply options such as non-blocking mode, reuse, no-delay, and configured send/receive buffer sizes. |
Layering
The module is organized in three layers:
| Layer | Key concepts |
|---|---|
| Platform backend | IoUringEngine, KqueueEngine, socket wrappers, completion harvesting. |
| I/O interface | ConnectionHandle, Completion, submit/harvest operations. |
| Transport API | TcpTransport, ConnectionManager, FrameReader, FrameWriter, handshake and frame types. |
The root module selects the default engine at compile time based on the target platform:
- Linux uses
io_uring; - macOS and FreeBSD use
kqueue; - unsupported platforms fail at compile time for the TCP transport.
Frame format
Broker-to-broker application and admin traffic is carried in a 24-byte frame header followed by payload bytes. The header includes:
| Field | Purpose |
|---|---|
frame_length |
Total frame size: header plus payload. |
flags |
Heartbeat/admin/data markers and future extensions. |
source_node_id |
Broker node that sent the frame. |
target_node_id |
Broker node that should receive the frame. |
source_service_id |
Service ID that originated the application message, or broker/admin source. |
target_service_id |
Destination service ID for application frames. |
template_id |
Application or admin message type. |
correlation_id |
Request/response or tracing correlation. |
The frame header keeps broker-to-broker routing simple: there is no stream multiplexing and no application-level reliable transport layered on top of TCP.
Handshake
Every peer connection starts with a fixed-size handshake. The receiver validates:
- magic value;
- protocol version;
- source node ID;
- expected target node ID;
- connection direction;
- group-name hash;
- session epoch;
- reserved bytes.
The session epoch lets brokers distinguish a fresh peer process from stale connections after restart. A group mismatch prevents accidental cross-cluster traffic when multiple RingLoom deployments share hosts or networks.
Sender integration
The broker sender event loop drains records from the broker send ring. For each remote target, it finds the peer connection, enqueues the frame into that peer’s write queue, and submits writes through the transport.
Important operational properties:
- writes are budgeted per peer to avoid one peer monopolizing the sender loop;
- per-peer write queues smooth short bursts;
- disconnected peers cause drops/counters rather than unbounded buffering;
- optional per-peer send counters expose pending bytes and connection state to service clients and monitoring tools.
Receiver integration
The broker receiver event loop owns the listener socket and incoming peer connections. It accepts connections, completes handshakes, reads frame headers and payloads, and dispatches complete frames.
Frame categories:
| Category | Handling |
|---|---|
| Application data | Route to the target local service’s message ring. |
| Admin traffic | Forward to the broker control/cluster path. |
| Heartbeat | Update peer liveness state. |
The receiver follows an always-read model. It keeps reading from sockets and records delivery failures instead of pausing a peer socket when one target service is slow.
Backends
Linux: io_uring
The Linux backend batches submissions and completions through io_uring. RingLoom uses it for accept, connect, recv, send, and close operations. Tuning properties include queue depth, completion queue depth, registered buffers, SQPOLL, single-issuer, cooperative task-run, sender CQE batch size, receiver CQE batch size, receive buffer size, and receive buffer count.
macOS / BSD-style: kqueue
The kqueue backend uses non-blocking sockets and read/write readiness notifications. It gives the broker the same completion-style interface while mapping to the platform’s event model.
Configuration knobs
Common transport-related broker properties include:
| Property | Purpose |
|---|---|
broker.local.host.port |
TCP listener endpoint for this broker. |
broker.member.host.ports |
Peer endpoints in nodeId@host:port format. |
broker.max.frame.length |
Upper bound for frame validation. |
broker.peer.write.queue.capacity |
Per-peer outbound queue capacity. |
broker.tcp.send.buffer.size |
OS send buffer size. |
broker.tcp.recv.buffer.size |
OS receive buffer size. |
broker.heartbeat.interval.ms |
Peer heartbeat send cadence. |
broker.heartbeat.timeout.ms |
Peer heartbeat timeout. |
broker.reconnect.initial.delay.ms |
Initial reconnect backoff. |
broker.reconnect.max.delay.ms |
Maximum reconnect backoff. |
broker.io.uring.* |
Linux-specific backend tuning. |
Delivery model
RingLoom relies on TCP for in-order byte delivery while a connection is alive. It does not add application-level replay across disconnects. If a peer disconnects, in-flight messages in kernel buffers or broker queues may be lost. Applications that need end-to-end guarantees should use correlation IDs, acknowledgements, timeouts, retries, or domain-level reconciliation.