SwimDriver
SwimDriver: runtime I/O glue for the pure Swim state machine (P2 L3).
Owns the RNG and period timer so the transport layer just calls step(state, now, events) each tick. The driver picks probe targets and indirect helpers randomly, advances the Swim FSM, and returns the Actions the transport must perform (send ping, send ping-req, gossip). The transport reads frames, decodes them into Events, and calls step again.
Wire protocol (Msgpack array, first element is the tag): 0 SwimPing(sender_id) 1 SwimPingAck(sender_id) 2 SwimPingReq(requester_id, target_id) 3 SwimGossip(node_id, status_int, incarnation) status_int: 0=Alive, 1=Suspect, 2=Dead 3 SwimGossipLoad(node_id, status_int, incarnation, [load_ints]) 5-element frame: the 5th element is a Msgpack array of NodeLoad ints (same tag 3, distinguished by element count)
Period lifecycle (period_ms ≈ 1000–5000 ms is typical):
- step() at period boundary: end prior probe → expire suspects →
refute if suspected → begin new period (pick random target).
2. step() mid-period: if ack_timeout has elapsed and probe is unacked,
escalate to k-way indirect ping-req.
3. Transport delivers PingAck events when acks arrive; GossipFrame events
when gossip frames are decoded; PeerDown events on socket close.Anti-entropy (P5a): anti_entropy_peers(s, now) returns live peers when the 30s timer fires. The transport calls this each tick and sends REGISTRY_SYNC_REQ to peers. bump_anti_entropy(s, now) resets the timer after firing.
Load gossip (P4): peer_loads tracks the last NodeLoad heard from each live peer. dispatch_all_with_load embeds the local NodeLoad in outgoing Gossip frames.