macula_peer_versions behaviour (macula v15.4.0)

View Source

The version floor each peer is held to, and the node-wide handshake counters (docs/design/WIRE_1_0.md sections 4.6 and 8).

A node records, per peer node_id, the highest handshake version it completed with, and never completes below it. The floor is raised only after a handshake completes, and only upward. It survives restarts through the connection's version_floor option, a store {Mod, Arg} with Mod:floor(Arg, NodeId) -> Version | none and Mod:raise(Arg, NodeId, Version) -> ok | {error, term()}. Without one, a node keeps the floor for the run, as an SDK host with no writable store does. A raise the store fails to persist keeps the completed connection and the floor in memory, and counts and logs version_floor_unpersisted; it never crashes the node or closes the link.

The table belongs to macula_peering_sup, which creates it with new_table/0 and holds every connection that reads it, so the memory lasts as long as those connections can, whichever child of that supervisor dies (macula#50). There is no process here: every read and write goes to the table directly, so no connection queues on it.

Summary

Functions

Count one handshake event, node-wide.

Every handshake counter, zero included.

The floor held for NodeId: the one this run holds, else the store's, or none.

Create the table, owned by the calling process: macula_peering_sup, whose life is the run's.

A handshake with NodeId completed at Version: the floor rises to it when it is higher, in memory and in the store. A store that fails keeps the floor in memory and counts version_floor_unpersisted.

Types

counter/0

-type counter() ::
          v5_connections | downgrade_detected | negotiation_mismatch | version_below_floor |
          session_proof_invalid | session_proof_missing | session_proof_rate | exporter_unavailable |
          version_floor_unpersisted.

store/0

-type store() :: {module(), term()} | none.

Callbacks

floor/2

-callback floor(Arg :: term(), NodeId :: <<_:256>>) -> macula_handshake:version() | pos_integer() | none.

raise/3

-callback raise(Arg :: term(), NodeId :: <<_:256>>, Version :: pos_integer()) -> ok | {error, term()}.

Functions

count(Name)

-spec count(counter()) -> ok.

Count one handshake event, node-wide.

counters()

-spec counters() -> #{counter() => non_neg_integer()}.

Every handshake counter, zero included.

floor(NodeId, Store)

-spec floor(<<_:256>>, store()) -> pos_integer() | none.

The floor held for NodeId: the one this run holds, else the store's, or none.

new_table()

-spec new_table() -> ok.

Create the table, owned by the calling process: macula_peering_sup, whose life is the run's.

raise(NodeId, Version, Store)

-spec raise(<<_:256>>, pos_integer(), store()) -> ok.

A handshake with NodeId completed at Version: the floor rises to it when it is higher, in memory and in the store. A store that fails keeps the floor in memory and counts version_floor_unpersisted.