Skip to main content

PeatNode

Struct PeatNode 

Source
pub struct PeatNode { /* private fields */ }
Expand description

Wraps AutomergeIrohBackend for authenticated document sync. Requires matching app_id and shared_key for peer connections.

Implementations§

Source§

impl PeatNode

Source

pub fn crdt_counter_value(&self) -> i64

Current merged value of the shared water-supply Counter.

Source

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.

Source

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.

Source

pub fn crdt_counter_snapshot(&self) -> String

Current save() bytes (hex), for periodic re-broadcast (catch-up).

Source

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.

Source

pub fn crdt_kv_all(&self, collection: String) -> String

All records in collection as a JSON object {key: value}.

Source

pub fn crdt_kv_merge(&self, collection: String, hex_doc: String)

Merge an inbound peer doc (hex) into collection.

Source

pub fn crdt_kv_snapshot(&self, collection: String) -> String

Current save() bytes (hex) of collection, for periodic re-broadcast.

Source

pub fn node_id(&self) -> String

Get this node’s unique identifier (hex-encoded)

Source

pub fn endpoint_addr(&self) -> String

Get this node’s endpoint address for peer connections

Source

pub fn peer_count(&self) -> u32

Get the number of connected peers

Source

pub fn connected_peers(&self) -> Vec<String>

Get list of connected peer IDs

Source

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.

Source

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.

Source

pub fn stop_sync(&self) -> Result<(), PeatError>

Stop sync operations

Source

pub fn sync_stats(&self) -> Result<SyncStats, PeatError>

Get sync statistics

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn connect_peer_nowait(&self, peer: PeerInfo) -> Result<(), PeatError>

Connect to a peer WITHOUT blocking the caller.

Same connect + formation-handshake + sync-trigger as [connect_peer] (they share [connect_peer_inner]), but spawned on the runtime so the FFI call returns immediately. The dial completes in the background; on success the peer appears in connected_peers and a Connected event fires. Intended for UI callers: a Dart isolate blocks on a synchronous FFI call, so connect_peer’s block_on freezes the UI for the whole dial (~seconds for an unreachable peer). There is no synchronous caller to hand a background failure to, so errors are surfaced via tracing (and android_log on Android) and otherwise dropped.

Source

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.

Source

pub fn put_document( &self, collection: &str, doc_id: &str, json_data: &str, ) -> Result<(), PeatError>

Store a JSON document in a collection

Source

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 through peat_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.

Source

pub fn delete_document( &self, collection: &str, doc_id: &str, ) -> Result<(), PeatError>

Delete a document from a collection

Source

pub fn list_documents(&self, collection: &str) -> Result<Vec<String>, PeatError>

List all document IDs in a collection

Source

pub fn sync_document( &self, collection: &str, doc_id: &str, ) -> Result<(), PeatError>

Manually trigger sync for a specific document

Source

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.

Source

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

Source

pub fn reconnect_known_peers(&self)

Run one reconnect pass immediately, dialing any disconnected, eligible roster member. Safe to call repeatedly — peers already connected or mid-dial are skipped, and failures are rate-limited by backoff. A “gentle” trigger: it does NOT clear backoffs (use Self::wake_reconnect for that). Sits on top of the periodic background tick.

Source

pub fn on_peer_observed(&self, node_id: String)

React to a hint that a specific roster member is reachable right now — e.g. a BLE neighbour advertisement, or a relay “peer online” signal.

If the peer is known, not already connected over any transport, and not mid-dial/backoff, it is dialed immediately — bypassing the periodic tick so the attempt lands inside a tight mobile background-execution budget. If the peer is already reachable over some transport (e.g. it just connected over BLE), this records that instead of dialing. Unknown peers are a no-op.

Source

pub fn wake_reconnect(&self)

React to a change that may have broadly restored connectivity — the network came up, or the app returned to foreground. Clears all backoffs so every known peer is immediately eligible, then runs one reconnect pass. Use Self::on_peer_observed when you know which peer is reachable; use this when you don’t.

Source§

impl PeatNode

Source

pub fn roster_upsert(&self, entry: RosterEntry)

Insert or update a known peer in the roster (keyed by node_id) and persist it. Idempotent — re-upserting refreshes addresses/relay/name and never moves last_seen_ms backwards.

Source

pub fn roster_remember(&self, group_id: String, peer: PeerInfo)

Convenience: remember a PeerInfo (the same struct handed to connect_peer) under a group, stamping last-seen as “never” (0). This is the call a consumer makes for each member when joining a group (e.g. from a scanned join token), so the reconnect supervisor can re-dial them. Idempotent; re-remembering refreshes addresses/relay/name.

Source

pub fn roster_remove(&self, node_id: String) -> bool

Remove a peer from the roster. Returns true if it was present.

Source

pub fn roster_get(&self, node_id: String) -> Option<RosterEntry>

Fetch a single roster entry by node_id.

Source

pub fn roster_list(&self) -> Vec<RosterEntry>

All roster entries, sorted by node_id.

Source

pub fn roster_list_by_group(&self, group_id: String) -> Vec<RosterEntry>

Roster entries for a single group.

Source§

impl PeatNode

Source

pub fn get_cells(&self) -> Result<Vec<CellInfo>, PeatError>

Get all cells from the sync document

Source

pub fn get_cell(&self, cell_id: &str) -> Result<Option<CellInfo>, PeatError>

Get a specific cell by ID

Source

pub fn put_cell(&self, cell: CellInfo) -> Result<(), PeatError>

Store a cell

Source

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.

Source

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).

Source

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.

Source

pub fn get_nodes(&self) -> Result<Vec<NodeInfo>, PeatError>

Get all nodes from the sync document

Source

pub fn put_node(&self, node: NodeInfo) -> Result<(), PeatError>

Store a node

Source

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.

Source

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.

Source

pub fn get_commands(&self) -> Result<Vec<CommandInfo>, PeatError>

Get all pending commands

Source

pub fn put_command(&self, command: CommandInfo) -> Result<(), PeatError>

Store a command (for C2 issuance)

Source§

impl PeatNode

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn blob_exists_locally(&self, hash_hex: &str) -> bool

Check if a blob exists locally without network fetch.

Source

pub fn blob_endpoint_id(&self) -> Option<String>

Get the blob endpoint ID as hex (returns None if blob transfer is disabled).

Source

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> LiftRef<UT> for PeatNode

Source§

impl<UT> LowerError<UT> for PeatNode

Source§

fn lower_error(obj: Self) -> RustBuffer

Lower this value for scaffolding function return Read more
Source§

impl<UT> LowerReturn<UT> for PeatNode

Source§

type ReturnType = <Arc<PeatNode> as LowerReturn<UniFfiTag>>::ReturnType

The type that should be returned by scaffolding functions for this type. Read more
Source§

fn lower_return(obj: Self) -> Result<Self::ReturnType, RustCallError>

Lower the return value from an scaffolding call Read more
Source§

fn handle_failed_lift( error: LiftArgsError, ) -> Result<Self::ReturnType, RustCallError>

Lower the return value for failed argument lifts Read more
Source§

impl<UT> TypeId<UT> for PeatNode

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CompatExt for T

Source§

fn compat(self) -> Compat<T>
where T: Sized,

Applies the Compat adapter by value. Read more
Source§

fn compat_ref(&self) -> Compat<&T>

Applies the Compat adapter by shared reference. Read more
Source§

fn compat_mut(&mut self) -> Compat<&mut T>

Applies the Compat adapter by mutable reference. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, UT> HandleAlloc<UT> for T
where T: Send + Sync,

Source§

fn new_handle(value: Arc<T>) -> Handle

Create a new handle for an Arc value Read more
Source§

unsafe fn clone_handle(handle: Handle) -> Handle

Clone a handle Read more
Source§

unsafe fn consume_handle(handle: Handle) -> Arc<T>

Consume a handle, getting back the initial Arc<> Read more
Source§

unsafe fn get_arc(handle: Handle) -> Arc<Self>

Get a clone of the Arc<> using a “borrowed” handle. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more