pub trait Behavior: Send {
type Message: Message;
type Log: Serialize + DeserializeOwned + Send + 'static;
// Required method
fn context(&self) -> &Context<Self::Message, Self::Log>;
// Provided methods
fn initialize<'life0, 'async_trait>(
&'life0 mut self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn receive<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_message: &'life1 Self::Message,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn answer<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_message: &'life1 Self::Message,
) -> Pin<Box<dyn Future<Output = Result<Vec<Self::Message>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn start<'life0, 'async_trait>(
&'life0 mut self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn clean_up<'life0, 'async_trait>(
&'life0 mut self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
}Expand description
What an actor does at each point in its life. It initializes, makes an
opening move once every actor is running, then maps what it receives to
what it does: a statement goes to receive and a
request to answer, whose result is the reply. On
the way out it cleans up. Every method but context
has an empty default, so the simplest behavior is a context and nothing
else. Anything else the behavior wants to say, such as who it is, goes
inside its messages.
A behavior’s state is its own: the mailbox hands it one message at a time, so each step may change that state freely. Actors run on a multi-threaded runtime, so a behavior has to be sendable between threads.
A behavior keeps the Context it is built with and returns it from
context. The episode makes the context, and the
Builder in the actor’s ActorInit wraps the behavior around it:
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Note(String);
impl Message for Note {}
/// Writes down everything it hears.
struct Scribe {
context: Context<Note>,
}
#[async_trait]
impl Behavior for Scribe {
type Message = Note;
type Log = Note;
fn context(&self) -> &Context<Note> {
&self.context
}
async fn receive(&mut self, message: &Note) -> anyhow::Result<()> {
self.context.log(message.clone());
Ok(())
}
}
let init = ActorInit {
behavior: Box::new(|context| Scribe { context }),
can_send_to: HashSet::new(),
can_shut_down: HashSet::new(),
has_logger: true,
};Required Associated Types§
Sourcetype Log: Serialize + DeserializeOwned + Send + 'static
type Log: Serialize + DeserializeOwned + Send + 'static
What this behavior logs. Most often the message type.
Required Methods§
Provided Methods§
Sourcefn initialize<'life0, 'async_trait>(
&'life0 mut self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn initialize<'life0, 'async_trait>(
&'life0 mut self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Called before anything else: open a connection, say. No actor starts until every actor has initialized.
Sourcefn receive<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_message: &'life1 Self::Message,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn receive<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_message: &'life1 Self::Message,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Handle the statement message. By default it is ignored.
Sourcefn answer<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_message: &'life1 Self::Message,
) -> Pin<Box<dyn Future<Output = Result<Vec<Self::Message>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn answer<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_message: &'life1 Self::Message,
) -> Pin<Box<dyn Future<Output = Result<Vec<Self::Message>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Answer the request message. The result is the reply, which by
default is nothing.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".