Skip to main content

Actor

Trait Actor 

Source
pub trait Actor:
    Sized
    + Send
    + 'static {
    type Props: Send + 'static;
    type Msg: Send + 'static;
    type Err: Send + Sync + 'static;

    // Required method
    fn init(
        ctx: &mut Ctx<Self>,
    ) -> impl Future<Output = Result<Self, Self::Err>> + Send;

    // Provided methods
    fn exit(
        this: Option<Self>,
        reason: ExitReason<Self>,
        ctx: &mut Ctx<Self>,
    ) -> impl Future<Output = ()> + Send { ... }
    fn sources(
        &self,
        ctx: &Ctx<Self>,
    ) -> impl Future<Output = Result<impl Sources<Self>, Self::Err>> + Send { ... }
    fn handle(
        &mut self,
        msg: Self::Msg,
        ctx: &mut Ctx<Self>,
    ) -> impl Future<Output = Result<(), Self::Err>> + Send { ... }
}
Expand description

A thin abstraction over tokio tasks and flume channels, allowing for easy message passing with a supervision tree to handle failures.

§Example

use speare::{Ctx, Actor};
use derive_more::From;

struct Counter {
    count: u32,
}

struct CounterProps {
    initial_count: u32,
    max_count: u32,
}

#[derive(From)]
enum CounterMsg {
    Inc(u32),
}

enum CounterErr {
    MaxCountExceeded,
}

impl Actor for Counter {
    type Props = CounterProps;
    type Msg = CounterMsg;
    type Err = CounterErr;

    async fn init(ctx: &mut Ctx<Self>) -> Result<Self, Self::Err> {
        Ok(Counter {
            count: ctx.props().initial_count,
        })
    }

    async fn handle(&mut self, msg: Self::Msg, ctx: &mut Ctx<Self>) -> Result<(), Self::Err> {
        match msg {
            CounterMsg::Inc(x) => {
                self.count += x;

                if self.count > ctx.props().max_count {
                    return Err(CounterErr::MaxCountExceeded);
                }
            }
        }

        Ok(())
    }
}

Required Associated Types§

Source

type Props: Send + 'static

Source

type Msg: Send + 'static

Source

type Err: Send + Sync + 'static

Required Methods§

Source

fn init( ctx: &mut Ctx<Self>, ) -> impl Future<Output = Result<Self, Self::Err>> + Send

Constructs the actor. Called on initial spawn and on every restart.

§Example
async fn init(ctx: &mut Ctx<Self>) -> Result<Self, Self::Err> {
    Ok(MyActor { count: ctx.props().initial })
}

Provided Methods§

Source

fn exit( this: Option<Self>, reason: ExitReason<Self>, ctx: &mut Ctx<Self>, ) -> impl Future<Output = ()> + Send

Cleanup hook called when the actor stops, restarts, or fails to init. this is None if init failed.

§Example
async fn exit(this: Option<Self>, reason: ExitReason<Self>, ctx: &mut Ctx<Self>) {
    if let ExitReason::Err(e) = reason {
        eprintln!("actor failed: {e:?}");
    }
}
Source

fn sources( &self, ctx: &Ctx<Self>, ) -> impl Future<Output = Result<impl Sources<Self>, Self::Err>> + Send

Sets up message sources (streams, intervals) after init.

Sources added earlier in the SourceSet chain have higher polling priority. If an earlier source is consistently ready, later sources may be starved.

§Example
async fn sources(&self, ctx: &Ctx<Self>) -> Result<impl Sources<Self>, Self::Err> {
    Ok(SourceSet::new()
        .interval(time::interval(Duration::from_millis(100)), || Msg::Tick)
        .stream(my_stream))
}
Source

fn handle( &mut self, msg: Self::Msg, ctx: &mut Ctx<Self>, ) -> impl Future<Output = Result<(), Self::Err>> + Send

Called everytime your Actor receives a message.

§Example
async fn handle(&mut self, msg: Self::Msg, ctx: &mut Ctx<Self>) -> Result<(), Self::Err> {
    match msg {
        Msg::Inc(n) => self.count += n,
    }

    Ok(())
}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§