Communication

Actors can communicate in many ways depending on the situation and desired guarantees.

Fire and Forget

The most straightforward way is to send a message with minimal guarantees.

However, it's possible to choose the desired behavior by calling the most appropriate method. All variants can be described by the following template: (try_|unbounded_)send(_to).

Methods with the _to suffix allow to specify a destination address as the first argument. Otherwise, the routing subsystem will be used.

The prefix describes what should happen if the destination mailbox is full:

SyntaxError casesDescription
send().awaitClosedBlocks until a destination mailbox has space for new messages
try_send()Full, ClosedReturns Full if the mailbox is full
unbounded_send()ClosedIgnores the capacity of the mailbox

All methods can return Closed if the destination actor is closed.

The form send().await is used when desired behavior is backpressure, while try_send() is for actors with predicted latency, when it's acceptable to lose messages or it can be handled manually. unbounded_send() should be avoided because it can increase mailboxes unpredictably, leading to OOM.

Examples

#[message] struct SomeMessage; // Block if the destination mailbox is full. ctx.send(SomeMessage).await?; // Do not care if the target actor is closed or full. ctx.try_send(SomeMessage)?; // Forcibly push the message into the mailbox. ctx.unbounded_send(SomeMessage)?; // Manually implement backpressure, e.g. store messages. if let Err(err) = ctx.try_send(SomeMessage) { let msg = err.into_inner(); // msg: SomeMessage }

Blocking Request-Response

Some communications between actors require response message being sent back to the sender.

TODO

Examples

#[message(ret = Result<(), DoSomethingRejected>)] struct DoSomething; #[message] struct DoSomethingRejected(String); TODO

Non-blocking Request-Response

TODO

State

TODO

Examples

TODO

Subscriptions

TODO