pub struct PeatNode { /* private fields */ }Expand description
A Peat network node with P2P sync capabilities
Wraps AutomergeIrohBackend for authenticated document sync. Requires matching app_id and shared_key for peer connections.
Implementations§
Source§impl PeatNode
impl PeatNode
Sourcepub fn crdt_counter_value(&self) -> i64
pub fn crdt_counter_value(&self) -> i64
Current merged value of the shared water-supply Counter.
Sourcepub fn crdt_counter_increment(&self, delta: i64) -> String
pub fn crdt_counter_increment(&self, delta: i64) -> String
Apply delta liters to the shared Counter; returns the doc’s save()
bytes (hex) for the caller to broadcast to peers.
Sourcepub fn crdt_counter_merge(&self, hex_doc: String) -> i64
pub fn crdt_counter_merge(&self, hex_doc: String) -> i64
Merge an inbound peer doc (hex of its save() bytes); returns the new value. Safe with duplicate / stale / relayed / out-of-order input.
Sourcepub fn crdt_counter_snapshot(&self) -> String
pub fn crdt_counter_snapshot(&self) -> String
Current save() bytes (hex), for periodic re-broadcast (catch-up).
Sourcepub fn crdt_kv_put(
&self,
collection: String,
key: String,
value_json: String,
) -> String
pub fn crdt_kv_put( &self, collection: String, key: String, value_json: String, ) -> String
Upsert key = value_json in collection; returns the doc’s save()
bytes (hex) to broadcast.
Sourcepub fn crdt_kv_all(&self, collection: String) -> String
pub fn crdt_kv_all(&self, collection: String) -> String
All records in collection as a JSON object {key: value}.
Sourcepub fn crdt_kv_merge(&self, collection: String, hex_doc: String)
pub fn crdt_kv_merge(&self, collection: String, hex_doc: String)
Merge an inbound peer doc (hex) into collection.
Sourcepub fn crdt_kv_snapshot(&self, collection: String) -> String
pub fn crdt_kv_snapshot(&self, collection: String) -> String
Current save() bytes (hex) of collection, for periodic re-broadcast.
Sourcepub fn endpoint_addr(&self) -> String
pub fn endpoint_addr(&self) -> String
Get this node’s endpoint address for peer connections
Sourcepub fn peer_count(&self) -> u32
pub fn peer_count(&self) -> u32
Get the number of connected peers
Sourcepub fn connected_peers(&self) -> Vec<String>
pub fn connected_peers(&self) -> Vec<String>
Get list of connected peer IDs
Sourcepub fn endpoint_socket_addr(&self) -> Option<String>
pub fn endpoint_socket_addr(&self) -> Option<String>
Return this node’s iroh-endpoint first IP listening address
as an "ip:port" string, or None if no socket has been
bound yet.
Intended for two-instance instrumented tests where two nodes
in the same process need to dial each other on loopback —
neither has the other’s address from discovery, so the test
harness fetches it here and passes it to connectPeerJni on
the dialing side. peat-mesh#138 M4.
Sourcepub fn start_sync(&self) -> Result<(), PeatError>
pub fn start_sync(&self) -> Result<(), PeatError>
Start sync operations
The authenticated accept loop (with formation handshake) is already running from sync_backend.initialize() in create_node(). This method starts the sync coordination layer: event-based and polling-based sync handlers.
Sourcepub fn sync_stats(&self) -> Result<SyncStats, PeatError>
pub fn sync_stats(&self) -> Result<SyncStats, PeatError>
Get sync statistics
Sourcepub fn peer_transport_state(
&self,
peer_id: String,
) -> Result<PeerTransportState, PeatError>
pub fn peer_transport_state( &self, peer_id: String, ) -> Result<PeerTransportState, PeatError>
ADR-032 §Amendment A — unified per-peer transport state.
Walks TransportManager for the given peer, calls
peer_link_state on each registered transport that can reach
it, and overlays the registered TransportInstance.id onto the
returned LinkState.transport_id (per the host-rendering rule:
the producer doesn’t know its own registered id, the consumer
fills it). Returns Ok(PeerTransportState { peer_id, links: vec![] })
for peers no transport reports — “absence is a valid state.”
Hex-encoded peer_id matches the form connected_peers()
returns. Invalid hex is propagated as-is to peat-mesh’s
NodeId::new, which is also a String wrapper — invalid input
surfaces as an empty links vec rather than an error, matching
the absence contract.
Sourcepub fn all_peer_transport_states(
&self,
) -> Result<Vec<PeerTransportState>, PeatError>
pub fn all_peer_transport_states( &self, ) -> Result<Vec<PeerTransportState>, PeatError>
ADR-032 §Amendment A — transport state for the peer set this
peat-ffi instance currently enumerates from iroh.
Designed for the plugin’s periodic poll (~2 s) — the implementation walks transport state in a single pass without per-peer recursion.
Coverage caveat (Slice-4.d-interim — not the final SSOT
shape). This method enumerates peers exclusively from
self.iroh_transport.connected_peers(). BLE-only peers
(peers reachable via peat-btle but not currently visible to
iroh) are not included. Plugin authors must continue to
merge BLE-only peers from peat-btle’s UniFFI surface
directly until the single-source-of-truth migration
completes. The Amendment A SSOT promise — “peat-ffi is the
single source of truth, the plugin MUST NOT reach into
peat-btle’s UniFFI directly” — is the destination, not the
current implementation; this method’s coverage is a strict
subset of that destination. Treat the cross-FFI peat-btle
reach as a documented interim, not an idiom to standardize on.
Tracked under defenseunicorns/peat#828.
Sourcepub fn request_sync(&self) -> Result<(), PeatError>
pub fn request_sync(&self) -> Result<(), PeatError>
Request a full document sync with all connected peers. This pushes all local documents to each peer and pulls any documents they have. Useful for ensuring newly created documents propagate after the initial connection.
Sourcepub fn connect_peer(&self, peer: PeerInfo) -> Result<(), PeatError>
pub fn connect_peer(&self, peer: PeerInfo) -> Result<(), PeatError>
Connect to a peer node with formation handshake
Establishes a QUIC connection, performs formation-key authentication, and emits a Connected event to trigger immediate sync handler spawning.
Sourcepub fn disconnect_peer(&self, node_id: &str) -> Result<(), PeatError>
pub fn disconnect_peer(&self, node_id: &str) -> Result<(), PeatError>
Disconnect from a peer by node ID
Note: Currently disconnects matching peer from internal connection map.
Sourcepub fn put_document(
&self,
collection: &str,
doc_id: &str,
json_data: &str,
) -> Result<(), PeatError>
pub fn put_document( &self, collection: &str, doc_id: &str, json_data: &str, ) -> Result<(), PeatError>
Store a JSON document in a collection
Sourcepub fn get_document(
&self,
collection: &str,
doc_id: &str,
) -> Result<Option<String>, PeatError>
pub fn get_document( &self, collection: &str, doc_id: &str, ) -> Result<Option<String>, PeatError>
Retrieve a document from the raw-bytes store as JSON.
§Storage path
This reads from storage_backend.collection() — the raw
key-value store. It will NOT see documents that were:
- Published via
publishDocumentJni(which goes throughpeat_mesh::Node::publish, the document layer) - Received from a peer via Automerge sync (which writes into the document layer’s CRDT, not the raw store)
The JNI counterpart getDocumentJni deliberately uses
peat_mesh::Node::get() instead so it round-trips with
publishDocumentJni. If you’re writing a new JNI method
that reads documents published or synced via the document
layer, follow getDocumentJni’s pattern, not this method’s.
Sourcepub fn delete_document(
&self,
collection: &str,
doc_id: &str,
) -> Result<(), PeatError>
pub fn delete_document( &self, collection: &str, doc_id: &str, ) -> Result<(), PeatError>
Delete a document from a collection
Sourcepub fn list_documents(&self, collection: &str) -> Result<Vec<String>, PeatError>
pub fn list_documents(&self, collection: &str) -> Result<Vec<String>, PeatError>
List all document IDs in a collection
Sourcepub fn sync_document(
&self,
collection: &str,
doc_id: &str,
) -> Result<(), PeatError>
pub fn sync_document( &self, collection: &str, doc_id: &str, ) -> Result<(), PeatError>
Manually trigger sync for a specific document
Sourcepub fn subscribe(
&self,
callback: Box<dyn DocumentCallback>,
) -> Result<Arc<SubscriptionHandle>, PeatError>
pub fn subscribe( &self, callback: Box<dyn DocumentCallback>, ) -> Result<Arc<SubscriptionHandle>, PeatError>
Subscribe to document changes
Returns a SubscriptionHandle that must be kept alive to receive callbacks. When the handle is dropped or cancel() is called, the subscription stops.
The callback will receive DocumentChange events for all documents. Filter by collection in your callback implementation if needed.
Note: Only one subscription per node is supported. Calling subscribe again will fail if a subscription is already active.
Sourcepub fn subscribe_poll(&self) -> Result<Arc<SubscriptionHandle>, PeatError>
pub fn subscribe_poll(&self) -> Result<Arc<SubscriptionHandle>, PeatError>
Subscribe to document changes using a poll-based model.
Returns a SubscriptionHandle whose
SubscriptionHandle::poll_changes method drains buffered
DocumentChange events. Callers drive delivery by periodically
calling poll_changes (e.g. from a Dart isolate loop or
Timer.periodic) — no foreign callback interface is required.
Drop or call SubscriptionHandle::cancel on the handle to stop.
§Broadcast lag
The underlying channel has a bounded capacity. If poll_changes is not
called frequently enough relative to the document-change rate, the
broadcast channel will lag and silently drop events — poll_changes
returns a partial set with no indication that events were missed.
Callers should treat a long gap between poll_changes calls (e.g. the
app was backgrounded) as a signal to trigger a full collection resync
rather than relying on the change stream alone.
Source§impl PeatNode
impl PeatNode
Sourcepub fn get_cells(&self) -> Result<Vec<CellInfo>, PeatError>
pub fn get_cells(&self) -> Result<Vec<CellInfo>, PeatError>
Get all cells from the sync document
Sourcepub fn get_cell(&self, cell_id: &str) -> Result<Option<CellInfo>, PeatError>
pub fn get_cell(&self, cell_id: &str) -> Result<Option<CellInfo>, PeatError>
Get a specific cell by ID
Sourcepub fn get_tracks(&self) -> Result<Vec<TrackInfo>, PeatError>
pub fn get_tracks(&self) -> Result<Vec<TrackInfo>, PeatError>
Get all tracks from the sync document.
Reads via peat_mesh::Node::query(...) so the writer/reader API
stays consistent with ingest_position_via_translator’s
Node::publish_with_origin path. The earlier implementation
scanned AutomergeBackend::collection(...).scan() directly,
expecting the bytes to be flat JSON of the original body — but
publish_with_origin writes a Document whose Automerge map
shape doesn’t match that expectation, so every body field came
back at parse_track_json’s unwrap_or defaults (peat#832).
Going through Node::query decodes the Document fields
properly and the read result matches what the writer published.
The track_tests::ingest_position_via_translator_then_get_tracks_preserves_body
test locks this in.
Sourcepub fn get_track(&self, track_id: &str) -> Result<Option<TrackInfo>, PeatError>
pub fn get_track(&self, track_id: &str) -> Result<Option<TrackInfo>, PeatError>
Get a specific track by ID. Routes through Node::get for the
same writer/reader symmetry reason as get_tracks (peat#832).
Sourcepub fn put_track(&self, track: TrackInfo) -> Result<(), PeatError>
pub fn put_track(&self, track: TrackInfo) -> Result<(), PeatError>
Store a track. Publishes through Node::publish so the
resulting Document lives in the same storage namespace
Node::query / Node::get read from — the BLE-bridged
ingest_position_via_translator path already publishes this
way, so unifying the typed put_track path keeps writer/reader
symmetric for both publish surfaces (peat#832).
Behavioral change vs pre-#836: this now fires through
TransportManager fan-out (the Node::publish path emits a
ChangeEvent that BLE / iroh transport drains observe), where
the pre-fix coll.upsert(json_bytes) only emitted the
in-process observer broadcast. No production caller exists
today (production tracks come in via ingestPositionJni), so
the change is observable only via UniFFI Kotlin / Swift
consumers if any appear later. Documented here so the next
reader doesn’t have to re-trace the change to find out.
Sourcepub fn get_nodes(&self) -> Result<Vec<NodeInfo>, PeatError>
pub fn get_nodes(&self) -> Result<Vec<NodeInfo>, PeatError>
Get all nodes from the sync document
Sourcepub fn get_markers(&self) -> Result<Vec<MarkerInfo>, PeatError>
pub fn get_markers(&self) -> Result<Vec<MarkerInfo>, PeatError>
Get all markers from the sync document.
Returns the canonical typed list of operator-placed pins across the mesh. Origin-agnostic — locally-created and peer-synced markers are indistinguishable in the result. Plugin consumers (PeatMapComponent’s periodic refresh, the Peat Markers panel readout) call this and render every entry with the same code path.
Sourcepub fn put_marker(&self, marker: MarkerInfo) -> Result<(), PeatError>
pub fn put_marker(&self, marker: MarkerInfo) -> Result<(), PeatError>
Store a marker.
Persists into the markers collection. peat-mesh’s fan-out
observes the change and routes via the registered transports
(universal-Document path on BLE via LiteBridgeTranslator,
iroh sync for cross-mesh peers). Receivers see the same
MarkerInfo shape on their side.
Sourcepub fn get_commands(&self) -> Result<Vec<CommandInfo>, PeatError>
pub fn get_commands(&self) -> Result<Vec<CommandInfo>, PeatError>
Get all pending commands
Sourcepub fn put_command(&self, command: CommandInfo) -> Result<(), PeatError>
pub fn put_command(&self, command: CommandInfo) -> Result<(), PeatError>
Store a command (for C2 issuance)
Source§impl PeatNode
impl PeatNode
Sourcepub fn enable_blob_transfer(
&self,
bind_addr: Option<SocketAddr>,
) -> Result<(), PeatError>
pub fn enable_blob_transfer( &self, bind_addr: Option<SocketAddr>, ) -> Result<(), PeatError>
Enable the parallel blob-transfer endpoint.
Constructs a NetworkedIrohBlobStore on the tokio runtime owned by
this node and stores it for later use via blob_put / blob_get.
Bind address defaults to 0.0.0.0:0 (ephemeral) when None.
Sourcepub fn blob_add_peer(
&self,
peer_id_hex: &str,
address: &str,
) -> Result<(), PeatError>
pub fn blob_add_peer( &self, peer_id_hex: &str, address: &str, ) -> Result<(), PeatError>
Add a known blob peer by hex EndpointId and socket address.
Uses peat-mesh’s add_peer_from_hex so no iroh types cross into
peat-ffi.
Sourcepub fn blob_put(
&self,
data: &[u8],
content_type: &str,
) -> Result<String, PeatError>
pub fn blob_put( &self, data: &[u8], content_type: &str, ) -> Result<String, PeatError>
Store bytes in the local blob store. Returns the content hash as hex.
Sourcepub fn blob_get(&self, hash_hex: &str) -> Result<Vec<u8>, PeatError>
pub fn blob_get(&self, hash_hex: &str) -> Result<Vec<u8>, PeatError>
Fetch blob bytes by content hash (hex). Tries local first, then known peers. Returns the bytes or an error.
Sourcepub fn blob_exists_locally(&self, hash_hex: &str) -> bool
pub fn blob_exists_locally(&self, hash_hex: &str) -> bool
Check if a blob exists locally without network fetch.
Sourcepub fn blob_endpoint_id(&self) -> Option<String>
pub fn blob_endpoint_id(&self) -> Option<String>
Get the blob endpoint ID as hex (returns None if blob transfer is disabled).
Sourcepub fn blob_bound_addr(&self) -> Option<String>
pub fn blob_bound_addr(&self) -> Option<String>
Get the blob endpoint’s bound socket address as “ip:port”. Useful for configuring remote peers and for tests.
Trait Implementations§
Source§impl<UT> LowerError<UT> for PeatNode
impl<UT> LowerError<UT> for PeatNode
Source§fn lower_error(obj: Self) -> RustBuffer
fn lower_error(obj: Self) -> RustBuffer
Source§impl<UT> LowerReturn<UT> for PeatNode
impl<UT> LowerReturn<UT> for PeatNode
Source§type ReturnType = <Arc<PeatNode> as LowerReturn<UniFfiTag>>::ReturnType
type ReturnType = <Arc<PeatNode> as LowerReturn<UniFfiTag>>::ReturnType
Source§fn lower_return(obj: Self) -> Result<Self::ReturnType, RustCallError>
fn lower_return(obj: Self) -> Result<Self::ReturnType, RustCallError>
Source§fn handle_failed_lift(
error: LiftArgsError,
) -> Result<Self::ReturnType, RustCallError>
fn handle_failed_lift( error: LiftArgsError, ) -> Result<Self::ReturnType, RustCallError>
Auto Trait Implementations§
impl !Freeze for PeatNode
impl !RefUnwindSafe for PeatNode
impl !UnwindSafe for PeatNode
impl Send for PeatNode
impl Sync for PeatNode
impl Unpin for PeatNode
impl UnsafeUnpin for PeatNode
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T, UT> HandleAlloc<UT> for T
impl<T, UT> HandleAlloc<UT> for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more