Core Concepts
Understand brokers, services, nodes, ring buffers, templates, and routing identifiers.
RingLoom has a small set of concepts. The important idea is that an application service always talks to its local broker and uses the same client model whether the target service is on the same host or a remote broker node.
Nodes and brokers
A node is a broker identity. Each broker has a unique broker.node.id in the range 0..255 and listens on broker.local.host.port for peer broker TCP connections.
A broker owns service ID 0 on its node. It creates a broker metadata file, accepts service registrations, maintains service discovery state, watches heartbeats, and routes cross-node messages.
A single-node deployment omits broker.member.host.ports. A multi-node deployment configures every peer as nodeId@host:port, for example:
broker.node.id=1
broker.local.host.port=10.0.0.1:9100
broker.member.host.ports=2@10.0.0.2:9100,3@10.0.0.3:9100
Services
A service is an application process that starts RingLoomEngine. Startup does four things:
- opens the local broker metadata file;
- allocates or reuses a service ID;
- creates a service metadata file;
- sends a registration message to the broker control ring.
A service is identified by (node_id, service_id) and discovered by service_name. Multiple instances can use the same service name. The broker sends complete instance snapshots to subscribers whenever the set changes.
Metadata files
Every broker and service owns a metadata file under:
<storage_path>/<group>/services/
A broker file contains a fixed header, a control ring, and a send ring. A service file contains a fixed header, a control ring, and a message ring. Monitoring regions and counters live in the same mapped metadata file so external tools can inspect runtime state without calling into the process.
The fixed header stores values such as buffer lengths, service ID, node ID, PID, start timestamp, and heartbeat timestamp.
Ring buffers
RingLoom’s shared-memory transport is based on MPSC ring buffers:
| Ring | Owner | Direction | Purpose |
|---|---|---|---|
| Broker control ring | broker | services → broker | registration, discovery subscriptions, heartbeats, unregisters |
| Broker send ring | broker | services → broker | outbound messages destined for remote nodes |
| Service control ring | service | broker → service | registration responses, service-instance snapshots, leader changes |
| Service message ring | service | producers → service | application messages from local services or the broker receiver |
Ring capacities are powers of two. The ring trailer stores producer and consumer positions, a correlation counter, and consumer heartbeat state. Progress is position-based, which keeps producers and consumers independent.
Local message path
When the target service is on the same node, a ServiceClient uses an IpcProducer for the target service’s message ring. The producer claims space, writes the payload, and commits the record. The target service’s message consumer thread reads the record and invokes the registered handler.
This path is same-host shared-memory IPC. It avoids socket syscalls and keeps the payload in mapped memory.
Remote message path
When the target service is on a different node, the same client API writes to the local broker’s send ring with target node and service identifiers in the message header. The broker sender event loop drains that ring, frames the message for TCP, and writes it to the peer broker. The remote broker receiver event loop reads the frame and writes the payload into the target service’s message ring.
Application routing is always based on (target_node_id, target_service_id). Service discovery hides those details from normal callers by keeping the ServiceClient instance list current.
Templates, payloads, and correlation IDs
RingLoom separates transport metadata from application payloads:
template_ididentifies the application message type.correlation_idlinks requests, responses, and traces.source_node_id,source_service_id,target_node_id, andtarget_service_ididentify routing endpoints.payload_lengthdescribes the application bytes following the RingLoom message header.
For low latency, keep application payloads fixed-size where possible. The samples use extern struct layouts and compile-time size checks. Variable text, JSON, allocation, and formatting should stay off the hot path.
Service discovery and load balancing
RingLoomEngine.createClient("service-name") creates a client proxy and subscribes to broker updates for that service name. The broker returns complete snapshots of known instances. The client then maintains local producers for same-node targets and broker-routed producers for remote targets.
The default client selects among available instances with round-robin balancing. You can also send to a specific (node_id, service_id) when you need explicit routing.
Leader election
Services can enable leader election when they register. The broker designates one leader among same-name instances and sends leader changes to subscribers. Callers can use leader-aware send paths such as sendToLeader or claim-to-leader variants so they do not need to implement their own coordination layer.
Broker nodes also participate in cluster-level leader election for control-plane responsibilities.
Heartbeats and liveness
Services update the heartbeat timestamp in their metadata file roughly once per second. The broker periodically checks registered services. When a service times out, the broker unregisters it, closes cached buffers, broadcasts removal to peer brokers, and sends updated discovery snapshots to local subscribers.
Broker-to-broker liveness is primarily driven by TCP connection state and broker heartbeat/admin traffic.
Back-pressure and flow control
A send can fail when a ring is full, no target instance is available, a peer is disconnected, or flow-control state says the downstream target is congested. The service client exposes these as typed send errors such as NoAvailableInstance, SendBufferFull, BackPressure, PeerCongested, and PeerDisconnected.
Production services should treat send failure as part of the normal control flow: count it, retry or shed work according to the application policy, and avoid blocking the hot path indefinitely.
Event loops
The broker runs three primary loops:
- Control loop — registration, discovery, heartbeats, leader election, cluster state, and flow-control updates.
- Sender event loop — drains the broker send ring and writes framed messages to peer brokers.
- Receiver event loop — reads peer TCP frames and routes messages to local service rings.
The default dedicated threading mode runs these loops independently. Idle strategies such as busy_spin, yielding, sleeping, backoff, and blocking tune latency versus CPU usage.