Trait aurum_actors::core::Actor[][src]

pub trait Actor<U: Case<S> + UnifiedType, S: Send + RootMessage<U>> where
    Self: Send + 'static, 
{ fn recv<'life0, 'life1, 'async_trait>(
        &'life0 mut self,
        ctx: &'life1 ActorContext<U, S>,
        msg: S
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
; fn pre_start<'life0, 'life1, 'async_trait>(
        &'life0 mut self,
        __arg1: &'life1 ActorContext<U, S>
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: Send + 'async_trait
, { ... }
fn post_stop<'life0, 'life1, 'async_trait>(
        &'life0 mut self,
        __arg1: &'life1 ActorContext<U, S>
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: Send + 'async_trait
, { ... } }
Expand description

Defines how actors process messages.

Each actor runs on at least one asynchronous task. Messages are received and processed atomically. Actors are lightweight and have good scalability locally. Node uses the Tokio runtime to schedule its tasks. Aurum operates under the same rules as Rust’s (and Tokio’s) asynchrony: tasks are IO-bound. Code running in tasks is expected to await often, and starvation can occur if asynchronous code performs heavy compute operations or synchronous IO.

It is recommended to implement Actor the async_trait annotation. Rust cannot have async functions in traits yet, so this is a temporary work-around. async_trait changes the type signatures of the member funtions for Actor. Just pretend the trait looks like this instead of the monstrosity below:

pub trait Actor<U: Case<S> + UnifiedType, S: Send + RootMessage<U>>
where
Self: Send + 'static,
{
  async fn pre_start(&mut self, _: &ActorContext<U, S>) {}
  async fn recv(&mut self, ctx: &ActorContext<U, S>, msg: S);
  async fn post_stop(&mut self, _: &ActorContext<U, S>) {}
}

You’ll need to use async_trait for every implementation of Actor.

use async_trait::async_trait;
use aurum_actors::AurumInterface;
use aurum_actors::core::{Actor, ActorContext, ActorRef, Case, UnifiedType};
use serde::{Serialize, Deserialize};

#[derive(AurumInterface, Serialize, Deserialize)]
#[serde(bound = "U: UnifiedType")]
enum Ball<U: UnifiedType + Case<Ball<U>>> {
  Ping(ActorRef<U, Self>),
  Pong(ActorRef<U, Self>),
}

struct Player<U: UnifiedType + Case<Ball<U>>> {
  initial_contact: Option<ActorRef<U, Ball<U>>>
}
#[async_trait]
impl<U: UnifiedType + Case<Ball<U>>> Actor<U, Ball<U>> for Player<U> {
  async fn pre_start(&mut self, ctx: &ActorContext<U, Ball<U>>) {
    if let Some(r) = &self.initial_contact {
      r.remote_send(&ctx.node, &Ball::Ping(ctx.interface())).await;
    }
  }
  async fn recv(&mut self, ctx: &ActorContext<U, Ball<U>>, msg: Ball<U>) {
    match msg {
      Ball::Ping(r) => {
        r.remote_send(&ctx.node, &Ball::Pong(ctx.interface())).await;
      }
      Ball::Pong(r) => {
        r.remote_send(&ctx.node, &Ball::Ping(ctx.interface())).await;
      }
    }
  }
}

Required methods

Called whenever the actor receives a message.

Provided methods

A setup function. This is called before the actor starts receiving messages.

Called when the actor terminates gracefully and has stopped receiving messages.

Implementors