pub struct TransportLadder<S> { /* private fields */ }Expand description
An ordered set of transports backed by an offline buffer.
Rungs are tried in the order they are added, so the cheapest, most-preferred
link is added first. A send that no rung accepts is buffered in the
[Store] and replayed by flush. The ladder is itself a
[Transport] and a [Receive]: a subscription goes onto every rung that
listens, and a receive takes whichever rung delivers first.
Implementations§
Source§impl<S: Store> TransportLadder<S>
impl<S: Store> TransportLadder<S>
Sourcepub fn rung(self, transport: impl Transport + Receive + Send + 'static) -> Self
pub fn rung(self, transport: impl Transport + Receive + Send + 'static) -> Self
Adds a rung that sends and listens, lowest-cost first.
§Arguments
transport- a link to try. Rungs added earlier are preferred, so add the cheapest link first and the costliest fallback last. The ladder subscribes on it and listens to it as well as sending over it.
§Returns
The ladder, for chaining.
Sourcepub fn uplink(self, transport: impl Transport + Send + 'static) -> Self
pub fn uplink(self, transport: impl Transport + Send + 'static) -> Self
Adds a rung that only sends, lowest-cost first.
This is the shape of a LoRa uplink, a satellite messenger, or any link that carries readings out but never a command back. The ladder sends over it in turn with the other rungs and never subscribes or listens on it.
§Arguments
transport- a send-only link to try, in the same cheapest-first order asrung.
§Returns
The ladder, for chaining.
Sourcepub async fn connect(&mut self) -> Result<()>
pub async fn connect(&mut self) -> Result<()>
Connects every rung that is not connected, best-effort.
A rung that fails to connect is left unreachable rather than failing the
whole ladder; sends simply fall through to the next rung or the buffer, and
the next call tries it again. A rung that connects receives every filter
the ladder has been asked to subscribe to, so a
subscription placed while a link was down takes effect when it returns.
§Returns
Ok(()) once every rung has been given the chance to connect.
§Errors
This call is best-effort and currently always returns Ok(()).
Sourcepub async fn send(&mut self, topic: &str, payload: &[u8]) -> Result<Delivery>
pub async fn send(&mut self, topic: &str, payload: &[u8]) -> Result<Delivery>
Sends a payload, falling back down the rungs and then to the buffer.
If the buffer is empty, each connected rung is tried in order and the first
to accept the message delivers it. If every rung fails, or the buffer
already holds a backlog, the message is buffered to preserve order, and only
flush drains a backlog. A rung that answers
[Error::Closed] is treated as down until the next
connect.
§Arguments
topic- the destination topic.payload- the bytes to send.
§Returns
Delivery::Sent if a rung delivered the message, or Delivery::Buffered
if it was queued for a later flush.
§Errors
Returns [Error::Io] if the message must be buffered
but the store cannot be written.
Sourcepub async fn send_text(&mut self, topic: &str, text: &str) -> Result<Delivery>
pub async fn send_text(&mut self, topic: &str, text: &str) -> Result<Delivery>
Sends text down the ladder: a reading or a command written out.
This is send with the text’s UTF-8 bytes, so a reading that is
already a number in words needs no encoding step; the far side reads it back with
Message::text or
Message::number.
§Arguments
topic- the destination topic.text- the text to send.
§Returns
Delivery::Sent if a rung delivered the message, or Delivery::Buffered
if it was queued for a later flush.
§Errors
Whatever send returns.
Sourcepub async fn flush(&mut self) -> Result<usize>
pub async fn flush(&mut self) -> Result<usize>
Drains the buffer across the rungs, oldest record first.
Each record is sent before it is removed, so the first record no rung can deliver halts the drain and leaves it, and everything after it, buffered in order for a later retry.
§Returns
The number of records forwarded before the buffer emptied or a rung refused one.
§Errors
Returns [Error::Io] if the store cannot be read or
written, or [Error::Codec] if a buffered record
cannot be decoded.
Sourcepub async fn buffered(&mut self) -> Result<usize>
pub async fn buffered(&mut self) -> Result<usize>
Returns how many messages are currently buffered.
Takes the ladder mutably, like the rest of its surface. Reading through a
shared borrow would hold one across the await, which would in turn oblige
every rung to be Sync rather than only Send, and that is a heavier
requirement than a transport should have to meet.
§Returns
The number of records waiting for a flush.
§Errors
Returns [Error::Io] if the store length cannot be
read.
Sourcepub async fn subscribe(&mut self, topic: &str) -> Result<()>
pub async fn subscribe(&mut self, topic: &str) -> Result<()>
Subscribes to a topic on every rung that listens.
The filter is kept for the life of the ladder: a rung that is down when it
is placed, or that later drops and reconnects, receives it on its next
connect. Subscribing while no rung is up therefore
succeeds, in the same way a send with no rung up is buffered rather than
refused.
§Arguments
topic- the topic filter, in the syntax the rungs’ links understand.
§Returns
Ok(()) once the filter is live on at least one rung, or is held for the
rungs to pick up as they connect.
§Errors
Returns the rung’s own [Error::Transport] if every connected rung refused
the filter. A rung that answers [Error::Closed] is treated as down rather
than as refusing.
Sourcepub async fn recv(&mut self) -> Result<Option<Message>>
pub async fn recv(&mut self) -> Result<Option<Message>>
Awaits the next message from any rung that listens.
Every connected, listening rung is polled together and the first to deliver
wins, starting from a different rung each call so a busy link cannot starve
a quiet one. A rung whose link ends, or that answers [Error::Closed], is
treated as down until the next connect, and the wait
continues on the rungs that remain.
The wait is cancel-safe when every rung’s receive is, as the receives of the
links pamoja ships are: a wait given up, by a timeout or a select!, takes no
message. That is how a node that both listens and reports shares one ladder,
waiting with a limit and sending between waits.
§Returns
Some(message) for the next message any rung delivers. None is never
returned: a ladder’s links come back with connect, so it
reports a closed state rather than an ended one.
§Errors
Returns [Error::Closed] if no connected rung listens: none was added with
rung, connect has not been called, or
every listening link has since ended. Returns a rung’s own
[Error::Transport] if its link fails while waiting.
Trait Implementations§
Source§impl<S: Store + Send> Receive for TransportLadder<S>
impl<S: Store + Send> Receive for TransportLadder<S>
Source§impl<S: Store + Send> Transport for TransportLadder<S>
impl<S: Store + Send> Transport for TransportLadder<S>
Source§async fn send(&mut self, topic: &str, payload: &[u8]) -> Result<()>
async fn send(&mut self, topic: &str, payload: &[u8]) -> Result<()>
Sends through the ladder; a buffered message counts as accepted for delivery, which is what the buffer is for.