Expand description

The module with the supervisor and related types.

Supervisor

A supervisor supervises an actor and handles any errors it encounters. A supervisor generally does two things; logging of the error and deciding whether to stop or restart the actor. Its advised to keep a supervisor small and simple.

When encountering an error it usually means someone has to be notified (to fix it), something often done via logging.

Next the supervisor needs to decide if the actor needs to be stopped or restarted. If the supervisor decides to restart the actor it needs to provide the argument to create a new actor (used in calling the NewActor::new method).

The restarted actor will have the same message inbox as the old (stopped) actor. Note however that if an actor retrieved a message from its inbox, and returned an error when processing it, the new (restarted) actor won’t retrieve that message again (messages aren’t cloned after all).

Restarting or stopping?

Sometimes just restarting an actor is the easiest way to deal with errors. Starting the actor from a clean slate will often allow it to continue processing. However this is not possible in all cases, for example when a new argument can’t be provided. For example the TcpServer found in the heph-rt. In those cases the supervisor should still log the error encountered.

Actors and sync actors

As actors come in two flavours, regular/asynchronous actors and synchronous actors, thus so do the supervisor traits, Supervisor and SyncSupervisor.

Provided implementations

There are two Supervisor implementations provided by Heph. First, the NoSupervisor can be used when the actor never returns an error (i.e. Result<(), !> or no return type) and thus doesn’t need supervision.

Second, the restart_supervisor! macro, which can be used to easily create a supervisor implementation that restarts the actor.

Examples

Supervisor that logs the errors of a badly behaving actor and stops it.

#![feature(never_type)]

use heph::actor;
use heph::supervisor::SupervisorStrategy;
use heph_rt::spawn::ActorOptions;
use heph_rt::{self as rt, ThreadLocal, Runtime};
use log::error;

fn main() -> Result<(), rt::Error> {
    // Enable logging so we can see the error message.
    std_logger::init();

    let mut runtime = Runtime::new()?;
    runtime.run_on_workers(|mut runtime_ref| -> Result<(), !> {
        runtime_ref.spawn_local(supervisor, bad_actor as fn(_) -> _, (), ActorOptions::default());
        Ok(())
    })?;
    runtime.start()
}

/// The error returned by our actor.
struct Error;

/// Supervisor that gets called if the actor returns an error.
fn supervisor(err: Error) -> SupervisorStrategy<()> {
    error!("Actor encountered an error!");
    SupervisorStrategy::Stop
}

/// Our badly behaving actor.
async fn bad_actor(_: actor::Context<!, ThreadLocal>) -> Result<(), Error> {
    Err(Error)
}

Structs

A supervisor implementation for actors that never return an error.

A supervisor implementation that stops the actor and logs the error.

Enums

The strategy to use when handling an error from an actor.

Traits

The supervisor of an actor.