macula_peer_connector (macula v0.14.3)
View SourcePeer Connector - Establishes direct QUIC connections to remote peers (v0.8.0+).
This module enables peer-to-peer communication by establishing outbound QUIC connections to arbitrary peers. Used by DHT for STORE/FIND_VALUE message propagation and by RPC/PubSub for direct delivery.
Overview
Pattern: Connection-pooled utility module with NAT-aware fallback - Uses macula_peer_connection_pool for connection reuse - Falls back to NAT-aware routing (hole punch, relay) on failure - Fire-and-forget message sending
Connection Strategy (v0.12.0+)
1. Try pooled connection (fastest, cached) 2. Try direct QUIC connection (new connection) 3. Fall back to NAT-aware routing via macula_nat_connector: a. Direct connection (if NAT allows) b. Hole punch (coordinated NAT traversal) c. Relay via gateway (guaranteed fallback)
Usage
Used internally by: - macula_pubsub_dht: Direct pub/sub delivery to discovered subscribers - macula_service_registry: DHT STORE propagation to k=20 nodes - Future: Multi-hop RPC routing
%% Send a DHT STORE message to a peer
Endpoint = <<"192.168.1.100:9443">>,
Message = #{
key => <<"service.calculator.add">>,
value => <<"192.168.1.50:9443">>,
ttl => 300
},
ok = macula_peer_connector:send_message(Endpoint, dht_store, Message).Performance Characteristics
v0.8.0: Fire-and-forget pattern (now legacy fallback) - Creates new connection per message - Simple but inefficient for high-frequency messaging
v0.10.0: Connection pooling (current) - Reuses existing connections via macula_peer_connection_pool - 1.5-2x latency improvement for repeated messaging
v0.12.0: NAT-aware routing (current) - Automatic fallback to hole punch and relay - Works across all NAT types
Summary
Functions
Send a message to a remote peer (fire-and-forget). Uses connection pool for efficiency, falls back to direct connection.
Send a message to a remote peer with custom timeout.
Send a message and wait for a reply (request-response pattern). This is used for messages like NAT_PROBE that expect a reply. Returns {ok, ReplyMessage} on success, {error, timeout} if no reply received.
Send a message using NAT-aware routing (hole punch, relay fallback). Use this when sending to peers that may be behind NAT. LocalNodeId is required for hole punch coordination.
Send a message using NAT-aware routing with options. Options: - endpoint: Target endpoint (if known, skips DHT lookup) - relay_endpoint: Specific relay to use - skip_hole_punch: true to skip hole punch attempts
Functions
Send a message to a remote peer (fire-and-forget). Uses connection pool for efficiency, falls back to direct connection.
Send a message to a remote peer with custom timeout.
-spec send_message_and_wait(binary(), atom(), map(), timeout()) -> {ok, {atom(), map()}} | {error, term()}.
Send a message and wait for a reply (request-response pattern). This is used for messages like NAT_PROBE that expect a reply. Returns {ok, ReplyMessage} on success, {error, timeout} if no reply received.
Send a message using NAT-aware routing (hole punch, relay fallback). Use this when sending to peers that may be behind NAT. LocalNodeId is required for hole punch coordination.
Send a message using NAT-aware routing with options. Options: - endpoint: Target endpoint (if known, skips DHT lookup) - relay_endpoint: Specific relay to use - skip_hole_punch: true to skip hole punch attempts